From 374e2e39bac9e57b6a2970abd60b477b8fa54264 Mon Sep 17 00:00:00 2001 From: Dorival Pedroso Date: Wed, 25 Sep 2024 21:33:48 +1000 Subject: [PATCH] Use num-traits Num for input requiring numbers --- Cargo.toml | 1 + src/barplot.rs | 19 ++++--------- src/boxplot.rs | 69 +++++++++++++++++++++------------------------- src/contour.rs | 10 ++----- src/conversions.rs | 9 +++--- src/curve.rs | 20 +++----------- src/histogram.rs | 13 +++------ src/image.rs | 7 ++--- src/plot.rs | 5 ++-- src/surface.rs | 8 ++---- 10 files changed, 60 insertions(+), 101 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 19b90bb..dd25a53 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -12,3 +12,4 @@ categories = ["mathematics", "science"] keywords = ["plot", "2D", "3D", "python", "matplotlib"] [dependencies] +num-traits = "0.2" diff --git a/src/barplot.rs b/src/barplot.rs index 8dd7d27..c4a4a53 100644 --- a/src/barplot.rs +++ b/src/barplot.rs @@ -1,4 +1,5 @@ -use super::{vector_to_array, generate_list_quoted, AsVector, GraphMaker}; +use super::{generate_list_quoted, vector_to_array, AsVector, GraphMaker}; +use num_traits::Num; use std::fmt::Write; /// Generates a Barplot plot @@ -138,14 +139,10 @@ impl Barplot { } /// Draws the bar plot - /// - /// # Notes - /// - /// * The type `U` of the input array must be a number. pub fn draw<'a, T, U>(&mut self, x: &'a T, y: &'a T) where T: AsVector<'a, U>, - U: 'a + std::fmt::Display, + U: 'a + std::fmt::Display + Num, { vector_to_array(&mut self.buffer, "x", x); vector_to_array(&mut self.buffer, "y", y); @@ -170,16 +167,10 @@ impl Barplot { } /// Draws the bar plot with strings - /// - /// # Notes - /// - /// * The type `S` of the input array must be a string. - /// * The type `U` of the input array must be a number. - pub fn draw_with_str<'a, S, T, U>(&mut self, x: &[S], y: &'a T) + pub fn draw_with_str<'a, T, U>(&mut self, x: &[&str], y: &'a T) where - S: std::fmt::Display, T: AsVector<'a, U>, - U: 'a + std::fmt::Display, + U: 'a + std::fmt::Display + Num, { generate_list_quoted(&mut self.buffer, "x", x); vector_to_array(&mut self.buffer, "y", y); diff --git a/src/boxplot.rs b/src/boxplot.rs index d6869bd..fb6da66 100644 --- a/src/boxplot.rs +++ b/src/boxplot.rs @@ -1,4 +1,5 @@ use super::{generate_list, generate_nested_list, matrix_to_array, AsMatrix, GraphMaker}; +use num_traits::Num; use std::fmt::Write; /// Draw a box and whisker plot @@ -86,18 +87,18 @@ use std::fmt::Write; /// /// See also integration test in the **tests** directory. pub struct Boxplot { - symbol: String, // The default symbol for flier (outlier) points. - horizontal: bool, // Horizontal boxplot (default is false) - whisker: Option, // The position of the whiskers - positions: Vec, // The positions of the boxes - width: Option, // The width of the boxes - no_fliers: bool, // Disables fliers - patch_artist: bool, // If false, produces boxes with the Line2D artist. Otherwise, boxes are drawn with Patch artists. - medianprops: String, // The properties of the median - boxprops: String, // The properties of the box - whiskerprops: String, // The properties of the whisker - extra: String, // Extra commands (comma separated) - buffer: String, // Buffer + symbol: String, // The default symbol for flier (outlier) points. + horizontal: bool, // Horizontal boxplot (default is false) + whisker: Option, // The position of the whiskers + positions: Vec, // The positions of the boxes + width: Option, // The width of the boxes + no_fliers: bool, // Disables fliers + patch_artist: bool, // Enables the use of Patch artist to draw boxes + median_props: String, // The properties of the median + box_props: String, // The properties of the box + whisker_props: String, // The properties of the whisker + extra: String, // Extra commands (comma separated) + buffer: String, // Buffer } impl Boxplot { @@ -111,9 +112,9 @@ impl Boxplot { width: None, no_fliers: false, patch_artist: false, - medianprops: String::new(), - boxprops: String::new(), - whiskerprops: String::new(), + median_props: String::new(), + box_props: String::new(), + whisker_props: String::new(), extra: String::new(), buffer: String::new(), } @@ -125,13 +126,9 @@ impl Boxplot { /// /// * `data` -- Is a sequence of 1D arrays such that a boxplot is drawn for each array in the sequence. /// [From Matplotlib](https://matplotlib.org/3.6.3/api/_as_gen/matplotlib.pyplot.boxplot.html) - /// - /// # Notes - /// - /// * The type `T` must be a number. pub fn draw(&mut self, data: &Vec>) where - T: std::fmt::Display, + T: std::fmt::Display + Num, { generate_nested_list(&mut self.buffer, "x", data); if self.positions.len() > 0 { @@ -147,14 +144,10 @@ impl Boxplot { /// /// * `data` -- Is a 2D array (matrix) such that a boxplot is drawn for each column in the matrix. /// [From Matplotlib](https://matplotlib.org/3.6.3/api/_as_gen/matplotlib.pyplot.boxplot.html) - /// - /// # Notes - /// - /// * The type `U` must be a number. pub fn draw_mat<'a, T, U>(&mut self, data: &'a T) where T: AsMatrix<'a, U>, - U: 'a + std::fmt::Display, + U: 'a + std::fmt::Display + Num, { matrix_to_array(&mut self.buffer, "x", data); if self.positions.len() > 0 { @@ -204,7 +197,7 @@ impl Boxplot { self } - /// Enable fill the boxes + /// Enables the use of Patch artist to draw boxes instead of Line2D artist pub fn set_patch_artist(&mut self, flag: bool) -> &mut Self { self.patch_artist = flag; self @@ -214,19 +207,19 @@ impl Boxplot { /// /// [See Matplotlib's documentation](https://matplotlib.org/3.6.3/api/_as_gen/matplotlib.pyplot.boxplot.html) pub fn set_medianprops(&mut self, props: &str) -> &mut Self { - self.medianprops = props.to_string(); + self.median_props = props.to_string(); self } /// Set the properties of the box pub fn set_boxprops(&mut self, props: &str) -> &mut Self { - self.boxprops = props.to_string(); + self.box_props = props.to_string(); self } /// Set the properties of the whisker pub fn set_whiskerprops(&mut self, props: &str) -> &mut Self { - self.whiskerprops = props.to_string(); + self.whisker_props = props.to_string(); self } @@ -268,14 +261,14 @@ impl Boxplot { if self.patch_artist { write!(&mut opt, ",patch_artist=True").unwrap(); } - if self.medianprops != "" { - write!(&mut opt, ",medianprops={}", self.medianprops).unwrap(); + if self.median_props != "" { + write!(&mut opt, ",medianprops={}", self.median_props).unwrap(); } - if self.boxprops != "" { - write!(&mut opt, ",boxprops={}", self.boxprops).unwrap(); + if self.box_props != "" { + write!(&mut opt, ",boxprops={}", self.box_props).unwrap(); } - if self.whiskerprops != "" { - write!(&mut opt, ",whiskerprops={}", self.whiskerprops).unwrap(); + if self.whisker_props != "" { + write!(&mut opt, ",whiskerprops={}", self.whisker_props).unwrap(); } if self.extra != "" { write!(&mut opt, ",{}", self.extra).unwrap(); @@ -310,9 +303,9 @@ mod tests { assert_eq!(boxes.width, None); assert_eq!(boxes.no_fliers, false); assert_eq!(boxes.patch_artist, false); - assert_eq!(boxes.medianprops.len(), 0); - assert_eq!(boxes.boxprops.len(), 0); - assert_eq!(boxes.whiskerprops.len(), 0); + assert_eq!(boxes.median_props.len(), 0); + assert_eq!(boxes.box_props.len(), 0); + assert_eq!(boxes.whisker_props.len(), 0); assert_eq!(boxes.extra.len(), 0); assert_eq!(boxes.buffer.len(), 0); } diff --git a/src/contour.rs b/src/contour.rs index dfe0006..109806b 100644 --- a/src/contour.rs +++ b/src/contour.rs @@ -1,4 +1,5 @@ -use super::{matrix_to_array, vector_to_array, generate_list_quoted, AsMatrix, GraphMaker}; +use super::{generate_list_quoted, matrix_to_array, vector_to_array, AsMatrix, GraphMaker}; +use num_traits::Num; use std::fmt::Write; /// Generates a contour plot @@ -113,15 +114,10 @@ impl Contour { /// * `no_labels` -- skip adding labels to the lines contour (if enabled) /// * `no_colorbar` -- skip drawing a colorbar /// * `with_selected` -- draw a line contour with a selected level (e.g., 0.0) on top of everything - /// - /// # Notes - /// - /// * The type `U` of the input matrices must be a number. - /// pub fn draw<'a, T, U>(&mut self, x: &'a T, y: &'a T, z: &'a T) where T: AsMatrix<'a, U>, - U: 'a + std::fmt::Display, + U: 'a + std::fmt::Display + Num, { matrix_to_array(&mut self.buffer, "x", x); matrix_to_array(&mut self.buffer, "y", y); diff --git a/src/conversions.rs b/src/conversions.rs index eee22d0..c8923ff 100644 --- a/src/conversions.rs +++ b/src/conversions.rs @@ -1,10 +1,11 @@ use super::{AsMatrix, AsVector}; +use num_traits::Num; use std::fmt::Write; /// Generates a Python list pub(crate) fn generate_list(buf: &mut String, name: &str, data: &[T]) where - T: std::fmt::Display, + T: std::fmt::Display + Num, { write!(buf, "{}=[", name).unwrap(); for val in data.into_iter() { @@ -29,7 +30,7 @@ where pub(crate) fn vector_to_array<'a, T, U>(buf: &mut String, name: &str, vector: &'a T) where T: AsVector<'a, U>, - U: 'a + std::fmt::Display, + U: 'a + std::fmt::Display + Num, { write!(buf, "{}=np.array([", name).unwrap(); let m = vector.vec_size(); @@ -42,7 +43,7 @@ where /// Generates a nested Python list pub(crate) fn generate_nested_list(buf: &mut String, name: &str, data: &Vec>) where - T: std::fmt::Display, + T: std::fmt::Display + Num, { write!(buf, "{}=[", name).unwrap(); for row in data.into_iter() { @@ -59,7 +60,7 @@ where pub(crate) fn matrix_to_array<'a, T, U>(buf: &mut String, name: &str, matrix: &'a T) where T: AsMatrix<'a, U>, - U: 'a + std::fmt::Display, + U: 'a + std::fmt::Display + Num, { write!(buf, "{}=np.array([", name).unwrap(); let (m, n) = matrix.size(); diff --git a/src/curve.rs b/src/curve.rs index 6f0d044..8d9f647 100644 --- a/src/curve.rs +++ b/src/curve.rs @@ -1,5 +1,6 @@ use super::{vector_to_array, AsVector, GraphMaker}; use crate::quote_marker; +use num_traits::Num; use std::fmt::Write; /// Holds either the second point coordinates of a ray or the slope of the ray @@ -281,14 +282,10 @@ impl Curve { /// /// * `x` - abscissa values /// * `y` - ordinate values - /// - /// # Notes - /// - /// * The type `U` of the input array must be a number. pub fn draw<'a, T, U>(&mut self, x: &'a T, y: &'a T) where T: AsVector<'a, U>, - U: 'a + std::fmt::Display, + U: 'a + std::fmt::Display + Num, { vector_to_array(&mut self.buffer, "x", x); vector_to_array(&mut self.buffer, "y", y); @@ -299,14 +296,10 @@ impl Curve { /// Draws curve on a previously drawn figure with the same x /// /// * `y` - ordinate values on the right-hand side - /// - /// # Notes - /// - /// * The type `U` of the input array must be a number. pub fn draw_with_twin_x<'a, T, U>(&mut self, y: &'a T) where T: AsVector<'a, U>, - U: 'a + std::fmt::Display, + U: 'a + std::fmt::Display + Num, { vector_to_array(&mut self.buffer, "y2", y); let opt = self.options(); @@ -328,15 +321,10 @@ impl Curve { /// * `x` - x values /// * `y` - y values /// * `z` - z values - /// - /// # Notes - /// - /// * The type `U` of the input array must be a number. - /// pub fn draw_3d<'a, T, U>(&mut self, x: &'a T, y: &'a T, z: &'a T) where T: AsVector<'a, U>, - U: 'a + std::fmt::Display, + U: 'a + std::fmt::Display + Num, { vector_to_array(&mut self.buffer, "x", x); vector_to_array(&mut self.buffer, "y", y); diff --git a/src/histogram.rs b/src/histogram.rs index 06fe23a..9c4278e 100644 --- a/src/histogram.rs +++ b/src/histogram.rs @@ -1,4 +1,5 @@ use super::{generate_list_quoted, generate_nested_list, GraphMaker}; +use num_traits::Num; use std::fmt::Write; /// Generates a Histogram plot @@ -78,17 +79,11 @@ impl Histogram { /// /// # Input /// - /// * `values` - values - /// * `labels` - labels - /// - /// # Notes - /// - /// * The type `T` must be a number. - /// * The type `U` must be a String or &str. - /// + /// * `values` -- holds the values + /// * `labels` -- holds the labels pub fn draw(&mut self, values: &Vec>, labels: &[U]) where - T: std::fmt::Display, + T: std::fmt::Display + Num, U: std::fmt::Display, { let opt = self.options(); diff --git a/src/image.rs b/src/image.rs index 690be52..4e82385 100644 --- a/src/image.rs +++ b/src/image.rs @@ -1,4 +1,5 @@ use super::{matrix_to_array, AsMatrix, GraphMaker}; +use num_traits::Num; use std::fmt::Write; /// Generates an image plot (imshow) @@ -54,14 +55,10 @@ impl Image { } /// (imshow) Displays data as an image - /// - /// # Notes - /// - /// * The type `U` of the input array must be a number. pub fn draw<'a, T, U>(&mut self, data: &'a T) where T: AsMatrix<'a, U>, - U: 'a + std::fmt::Display, + U: 'a + std::fmt::Display + Num, { matrix_to_array(&mut self.buffer, "data", data); let opt = self.options(); diff --git a/src/plot.rs b/src/plot.rs index c95dc67..5d68d39 100644 --- a/src/plot.rs +++ b/src/plot.rs @@ -1,4 +1,5 @@ use super::{call_python3, generate_list_quoted, vector_to_array, AsVector, Legend, StrError, SuperTitleParams}; +use num_traits::Num; use std::ffi::OsStr; use std::fmt::Write; use std::fs::{self, File}; @@ -705,7 +706,7 @@ impl Plot { where S: std::fmt::Display, T: AsVector<'a, U>, - U: 'a + std::fmt::Display, + U: 'a + std::fmt::Display + Num, { assert_eq!(ticks.vec_size(), labels.len()); vector_to_array(&mut self.buffer, "tx", ticks); @@ -723,7 +724,7 @@ impl Plot { where S: std::fmt::Display, T: AsVector<'a, U>, - U: 'a + std::fmt::Display, + U: 'a + std::fmt::Display + Num, { assert_eq!(ticks.vec_size(), labels.len()); vector_to_array(&mut self.buffer, "ty", ticks); diff --git a/src/surface.rs b/src/surface.rs index cfc2810..f75538d 100644 --- a/src/surface.rs +++ b/src/surface.rs @@ -1,5 +1,6 @@ use super::{matrix_to_array, AsMatrix, GraphMaker, StrError}; use crate::quote_marker; +use num_traits::Num; use std::fmt::Write; /// Generates a 3D a surface (or wireframe, or both) @@ -115,15 +116,10 @@ impl Surface { /// /// * `surface` -- draws surface /// * `wireframe` -- draws wireframe - /// - /// # Notes - /// - /// * The type `U` of the input matrices must be a number. - /// pub fn draw<'a, T, U>(&mut self, x: &'a T, y: &'a T, z: &'a T) where T: AsMatrix<'a, U>, - U: 'a + std::fmt::Display, + U: 'a + std::fmt::Display + Num, { matrix_to_array(&mut self.buffer, "x", x); matrix_to_array(&mut self.buffer, "y", y);