use super::{generate_list_quoted, generate_nested_list, GraphMaker};
use num_traits::Num;
use std::fmt::Write;
pub struct Histogram {
colors: Vec<String>, line_width: f64, style: String, stacked: bool, no_fill: bool, number_bins: usize, extra: String, buffer: String, }
impl Histogram {
pub fn new() -> Self {
Histogram {
colors: Vec::new(),
line_width: 0.0,
style: String::new(),
stacked: false,
no_fill: false,
number_bins: 0,
extra: String::new(),
buffer: String::new(),
}
}
pub fn draw<T, U>(&mut self, values: &Vec<Vec<T>>, labels: &[U])
where
T: std::fmt::Display + Num,
U: std::fmt::Display,
{
let opt = self.options();
generate_nested_list(&mut self.buffer, "values", values);
generate_list_quoted(&mut self.buffer, "labels", labels);
if self.colors.len() > 0 {
generate_list_quoted(&mut self.buffer, "colors", self.colors.as_slice());
}
write!(&mut self.buffer, "plt.hist(values,label=labels{})\n", &opt).unwrap();
}
pub fn set_colors(&mut self, colors: &[&str]) -> &mut Self {
self.colors = colors.iter().map(|color| color.to_string()).collect();
self
}
pub fn set_line_width(&mut self, width: f64) -> &mut Self {
self.line_width = width;
self
}
pub fn set_style(&mut self, style: &str) -> &mut Self {
self.style = String::from(style);
self
}
pub fn set_stacked(&mut self, flag: bool) -> &mut Self {
self.stacked = flag;
self
}
pub fn set_no_fill(&mut self, flag: bool) -> &mut Self {
self.no_fill = flag;
self
}
pub fn set_number_bins(&mut self, bins: usize) -> &mut Self {
self.number_bins = bins;
self
}
pub fn set_extra(&mut self, extra: &str) -> &mut Self {
self.extra = extra.to_string();
self
}
fn options(&self) -> String {
let mut opt = String::new();
if self.colors.len() > 0 {
write!(&mut opt, ",color=colors").unwrap();
}
if self.line_width > 0.0 {
write!(&mut opt, ",linewidth={}", self.line_width).unwrap();
}
if self.style != "" {
write!(&mut opt, ",histtype='{}'", self.style).unwrap();
}
if self.stacked {
write!(&mut opt, ",stacked=True").unwrap();
}
if self.no_fill {
write!(&mut opt, ",fill=False").unwrap();
}
if self.number_bins > 0 {
write!(&mut opt, ",bins={}", self.number_bins).unwrap();
}
if self.extra != "" {
write!(&mut opt, ",{}", self.extra).unwrap();
}
opt
}
}
impl GraphMaker for Histogram {
fn get_buffer<'a>(&'a self) -> &'a String {
&self.buffer
}
fn clear_buffer(&mut self) {
self.buffer.clear();
}
}
#[cfg(test)]
mod tests {
use super::Histogram;
use crate::GraphMaker;
#[test]
fn new_works() {
let histogram = Histogram::new();
assert_eq!(histogram.colors.len(), 0);
assert_eq!(histogram.line_width, 0.0);
assert_eq!(histogram.style.len(), 0);
assert_eq!(histogram.stacked, false);
assert_eq!(histogram.no_fill, false);
assert_eq!(histogram.number_bins, 0);
assert_eq!(histogram.buffer.len(), 0);
}
#[test]
fn options_works() {
let mut histogram = Histogram::new();
histogram
.set_colors(&vec!["red", "green"])
.set_line_width(10.0)
.set_style("step")
.set_stacked(true)
.set_no_fill(true)
.set_number_bins(8);
let opt = histogram.options();
assert_eq!(
opt,
",color=colors\
,linewidth=10\
,histtype='step'\
,stacked=True\
,fill=False\
,bins=8"
);
}
#[test]
fn draw_works() {
let values = vec![vec![1, 1, 1, 2, 2, 2, 2, 2, 3, 3], vec![5, 6, 7, 8]];
let labels = ["first", "second"];
let mut histogram = Histogram::new();
histogram.set_colors(&vec!["red", "green"]);
histogram.draw(&values, &labels);
let b: &str = "values=[[1,1,1,2,2,2,2,2,3,3,],[5,6,7,8,],]\n\
labels=['first','second',]\n\
colors=['red','green',]\n\
plt.hist(values,label=labels,color=colors)\n";
assert_eq!(histogram.buffer, b);
histogram.clear_buffer();
assert_eq!(histogram.buffer, "");
}
}