~axect/Peroxide

263bbc98d96d58e04538c0357194850242f73130 — axect 6 months ago 17a7b26
Ver 0.16.2 - Plot with pair
5 files changed, 65 insertions(+), 9 deletions(-)

M Cargo.toml
M RELEASES.md
M example_data/lm_test.png
A example_data/plot_test.png
M src/util/plot.rs
M Cargo.toml => Cargo.toml +1 -1
@@ 1,6 1,6 @@
[package]
name = "peroxide"
version = "0.16.1"
version = "0.16.2"
authors = ["axect <edeftg@gmail.com>"]
description = "Rust comprehensive scientific computation library contains linear algebra, numerical analysis, statistics and machine learning tools with farmiliar syntax"
repository = "https://github.com/Axect/Peroxide"

M RELEASES.md => RELEASES.md +5 -0
@@ 1,3 1,8 @@
# Release 0.16.2 (2019-09-21)

* Now, we can insert pair of data to `plot`
    * `fn insert_pair(&self, pait: (Vec<f64>, Vec<f64>)) -> &mut Self`

# Release 0.16.1 (2019-09-19)

* More generic `optimize`

M example_data/lm_test.png => example_data/lm_test.png +0 -0

A example_data/plot_test.png => example_data/plot_test.png +0 -0

M src/util/plot.rs => src/util/plot.rs +59 -8
@@ 83,7 83,7 @@ use self::pyo3::types::IntoPyDict;
use self::pyo3::{PyResult, Python};
pub use self::Grid::{Off, On};
pub use self::Markers::{Circle, Line, Point};
use self::PlotOptions::{Domain, Images, Legends, Path};
use self::PlotOptions::{Domain, Images, Pairs, Legends, Path};
use std::collections::HashMap;

type Vector = Vec<f64>;


@@ 92,6 92,7 @@ type Vector = Vec<f64>;
pub enum PlotOptions {
    Domain,
    Images,
    Pairs,
    Legends,
    Path,
}


@@ 112,6 113,7 @@ pub enum Grid {
pub trait Plot {
    fn set_domain(&mut self, x: Vec<f64>) -> &mut Self;
    fn insert_image(&mut self, y: Vec<f64>) -> &mut Self;
    fn insert_pair(&mut self, xy: (Vec<f64>, Vec<f64>)) -> &mut Self;
    fn set_title(&mut self, title: &str) -> &mut Self;
    fn set_xlabel(&mut self, xlabel: &str) -> &mut Self;
    fn set_ylabel(&mut self, ylabel: &str) -> &mut Self;


@@ 129,6 131,7 @@ pub trait Plot {
pub struct Plot2D {
    domain: Vector,
    images: Vec<Vector>,
    pairs: Vec<(Vector, Vector)>,
    title: String,
    xlabel: String,
    ylabel: String,


@@ 146,12 149,14 @@ impl Plot2D {
        let mut default_options: HashMap<PlotOptions, bool> = HashMap::new();
        default_options.insert(Domain, false);
        default_options.insert(Images, false);
        default_options.insert(Pairs, false);
        default_options.insert(Legends, false);
        default_options.insert(Path, false);

        Plot2D {
            domain: vec![],
            images: vec![],
            pairs: vec![],
            title: "Title".to_string(),
            xlabel: "$x$".to_string(),
            ylabel: "$y$".to_string(),


@@ 183,6 188,14 @@ impl Plot for Plot2D {
        self
    }

    fn insert_pair(&mut self, xy: (Vec<f64>, Vec<f64>)) -> &mut Self {
        if let Some(t) = self.options.get_mut(&Pairs) {
            *t = true
        }
        self.pairs.push(xy);
        self
    }

    fn set_title(&mut self, title: &str) -> &mut Self {
        self.title = title.to_owned();
        self


@@ 244,22 257,40 @@ impl Plot for Plot2D {
    fn savefig(&self) -> PyResult<()> {
        // Check domain
        match self.options.get(&Domain) {
            Some(x) => {
                assert!(*x, "Domain is not defined");
            Some(x) if !*x => {
                match self.options.get(&Pairs) {
                    Some(xy) if !*xy => {
                        panic!("There are no data to plot");
                    }
                    None => {
                        panic!("There are some serious problems in plot system");
                    }
                    _ => (),
                }
            }
            None => {
                assert!(false, "Domain is None");
                panic!("There are some serious problems in plot system");
            }
            _ => (),
        }

        // Check images
        match self.options.get(&Images) {
            Some(x) => {
                assert!(*x, "Images are not defined");
            Some(x) if !*x => {
                match self.options.get(&Pairs) {
                    Some(xy) if !*xy => {
                        panic!("there are no data to plot");
                    }
                    None => {
                        panic!("There are some serious problems in plot system");
                    }
                    _ => (),
                }
            }
            None => {
                assert!(false, "Images are None");
                panic!("There are some serious problems in plot system");
            }
            _ => (),
        }

        // Check legends


@@ 267,7 298,7 @@ impl Plot for Plot2D {
            Some(x) => {
                assert!(*x, "Legends are not defined");
                assert!(
                    self.images.len() == self.legends.len(),
                    self.images.len() + self.pairs.len() == self.legends.len(),
                    "Legends are not matched with images"
                );
            }


@@ 283,7 314,9 @@ impl Plot for Plot2D {
        // Input data
        let x = self.domain.clone();
        let ys = self.images.clone();
        let pairs = self.pairs.clone();
        let y_length = ys.len();
        let pair_length = pairs.len();
        let title = self.title.clone();
        let fig_size = self.fig_size;
        let dpi = self.dpi;


@@ 300,7 333,9 @@ impl Plot for Plot2D {
        let globals = vec![("plt", py.import("pylab")?)].into_py_dict(py);
        globals.set_item("x", x)?;
        globals.set_item("y", ys)?;
        globals.set_item("pair", pairs)?;
        globals.set_item("n", y_length)?;
        globals.set_item("p", pair_length)?;
        globals.set_item("fs", fig_size)?;
        globals.set_item("dp", dpi)?;
        globals.set_item("gr", grid)?;


@@ 325,6 360,10 @@ impl Plot for Plot2D {
                plot_string
                    .push_str(&format!("plt.plot(x,y[{}],label=r\"{}\")\n", i, legends[i])[..])
            }
            for i in 0..pair_length {
                plot_string
                    .push_str(&format!("plt.plot(pair[{}][0],pair[{}][1],label=r\"{}\")\n", i, i, legends[i+y_length])[..])
            }
        } else {
            for i in 0..y_length {
                match self.markers[i] {


@@ 338,6 377,18 @@ impl Plot for Plot2D {
                    ),
                }
            }
            for i in 0..pair_length {
                match self.markers[i+y_length] {
                    Line => plot_string
                        .push_str(&format!("plt.plot(pair[{}][0],pair[{}][1],label=r\"{}\")\n", i, i, legends[i+y_length])[..]),
                    Point => plot_string.push_str(
                        &format!("plt.plot(pair[{}][0],pair[{}][1],\".\",label=r\"{}\")\n", i, i, legends[i+y_length])[..],
                    ),
                    Circle => plot_string.push_str(
                        &format!("plt.plot(pair[{}][0],pair[{}][1],\"o\",label=r\"{}\")\n", i, i, legends[i+y_length])[..],
                    ),
                }
            }
        }

        plot_string.push_str("plt.legend(fontsize=12)\nplt.savefig(pa)");