use super::{matrix_to_list, vector_to_strings, GraphMaker};
use std::fmt::Write;
pub struct Histogram {
colors: Vec<String>, line_width: f64, style: String, stacked: bool, no_fill: bool, number_bins: usize, 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,
buffer: String::new(),
}
}
pub fn draw<T, U>(&mut self, values: &Vec<Vec<T>>, labels: &[U])
where
T: std::fmt::Display,
U: std::fmt::Display,
{
let opt = self.options();
matrix_to_list(&mut self.buffer, "values", values);
vector_to_strings(&mut self.buffer, "labels", labels);
if self.colors.len() > 0 {
vector_to_strings(&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
}
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();
}
opt
}
}
impl GraphMaker for Histogram {
fn get_buffer<'a>(&'a self) -> &'a String {
&self.buffer
}
}
#[cfg(test)]
mod tests {
use super::Histogram;
#[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);
}
}