plotlib/repr/
boxplot.rs

1/*!
2
3Box plot
4
5# Examples
6
7```
8# use plotlib::repr::BoxPlot;
9# use plotlib::view::CategoricalView;
10let b1 = BoxPlot::from_slice(&[0., 2., 3., 4.]);
11let b2 = BoxPlot::from_vec(vec![0., 2., 3., 4.]);
12let v = CategoricalView::new().add(b1);
13```
14*/
15
16use std::f64;
17
18use svg;
19
20use crate::axis;
21use crate::repr::CategoricalRepresentation;
22use crate::style::BoxStyle;
23use crate::svg_render;
24use crate::utils;
25
26enum BoxData<'a> {
27    Owned(Vec<f64>),
28    Ref(&'a [f64]),
29}
30
31pub struct BoxPlot<'a> {
32    data: BoxData<'a>,
33    label: String,
34    style: BoxStyle,
35}
36
37impl<'a> BoxPlot<'a> {
38    pub fn from_slice(v: &'a [f64]) -> Self {
39        BoxPlot {
40            data: BoxData::Ref(v),
41            style: BoxStyle::new(),
42            label: String::new(),
43        }
44    }
45
46    pub fn from_vec(v: Vec<f64>) -> Self {
47        BoxPlot {
48            data: BoxData::Owned(v),
49            style: BoxStyle::new(),
50            label: String::new(),
51        }
52    }
53
54    pub fn style(mut self, style: &BoxStyle) -> Self {
55        self.style.overlay(style);
56        self
57    }
58
59    pub fn get_style(&self) -> &BoxStyle {
60        &self.style
61    }
62
63    pub fn label<T>(mut self, label: T) -> Self
64    where
65        T: Into<String>,
66    {
67        self.label = label.into();
68        self
69    }
70
71    pub fn get_label(&self) -> &String {
72        &self.label
73    }
74
75    fn get_data(&'a self) -> &'a [f64] {
76        match self.data {
77            BoxData::Owned(ref v) => v,
78            BoxData::Ref(v) => v,
79        }
80    }
81
82    fn range(&self) -> (f64, f64) {
83        match self.data {
84            BoxData::Owned(ref v) => utils::range(v),
85            BoxData::Ref(v) => utils::range(v),
86        }
87    }
88}
89
90impl<'a> CategoricalRepresentation for BoxPlot<'a> {
91    /// The maximum range. Used for auto-scaling axis
92    fn range(&self) -> (f64, f64) {
93        self.range()
94    }
95
96    /// The ticks that this representation covers. Used to collect all ticks for display
97    fn ticks(&self) -> Vec<String> {
98        vec![self.label.clone()]
99    }
100
101    fn to_svg(
102        &self,
103        x_axis: &axis::CategoricalAxis,
104        y_axis: &axis::ContinuousAxis,
105        face_width: f64,
106        face_height: f64,
107    ) -> svg::node::element::Group {
108        svg_render::draw_face_boxplot(
109            self.get_data(),
110            &self.label,
111            x_axis,
112            y_axis,
113            face_width,
114            face_height,
115            &self.style,
116        )
117    }
118
119    fn to_text(
120        &self,
121        _x_axis: &axis::CategoricalAxis,
122        _y_axis: &axis::ContinuousAxis,
123        _face_width: u32,
124        _face_height: u32,
125    ) -> String {
126        "".into()
127    }
128}