Skip to main content

mdbook_plotly/code_handler/plot_obj_parser/
histogram_parser.rs

1use super::until::{Color, Map, must_translate};
2use crate::{translate, translate_enum};
3use anyhow::{Result, anyhow};
4use plotly::Histogram;
5
6pub fn parse_histogram_data(
7    hist_obj: &mut serde_json::Value,
8    map: &Map,
9) -> Result<Box<Histogram<f64>>> {
10    let has_x = hist_obj.get("x").is_some();
11    let has_y = hist_obj.get("y").is_some();
12    let hist = match (has_x, has_y) {
13        (true, true) => {
14            let x: Vec<f64> = must_translate(hist_obj, map, "x")?;
15            let y: Vec<f64> = must_translate(hist_obj, map, "y")?;
16            Histogram::new_xy(x, y)
17        }
18        (true, false) => {
19            let x: Vec<f64> = must_translate(hist_obj, map, "x")?;
20            Histogram::new(x)
21        }
22        (false, true) => {
23            let y: Vec<f64> = must_translate(hist_obj, map, "y")?;
24            Histogram::new_vertical(y)
25        }
26        (false, false) => {
27            return Err(anyhow!("histogram requires at least 'x' or 'y' data"));
28        }
29    };
30    let hist = translate! {
31        hist,
32        hist_obj,
33        map,
34        (name, String),
35        (show_legend, bool),
36        (legend_group, String),
37        (opacity, f64),
38        (text, String),
39        (text_array, Vec<String>),
40        (hover_text, String),
41        (hover_text_array, Vec<String>),
42        (hover_template, String),
43        (hover_template_array, Vec<String>),
44        (auto_bin_x, bool),
45        (n_bins_x, usize),
46        (auto_bin_y, bool),
47        (n_bins_y, usize),
48        (alignment_group, String),
49        (offset_group, String),
50        (bin_group, String),
51        (x_axis, String),
52        (y_axis, String),
53    }?;
54
55    use plotly::common::Orientation;
56    use plotly::histogram::{HistFunc, HistNorm};
57
58    let hist = translate_enum! {
59        hist,
60        hist_obj,
61        map,
62        (orientation, {
63            "v" => Orientation::Vertical,
64            "h" => Orientation::Horizontal,
65        }),
66        (hist_func, {
67            "count" => HistFunc::Count,
68            "sum"   => HistFunc::Sum,
69            "avg"   => HistFunc::Average,
70            "min"   => HistFunc::Minimum,
71            "max"   => HistFunc::Maximum,
72        }),
73        (hist_norm, {
74            "percent"             => HistNorm::Percent,
75            "probability"         => HistNorm::Probability,
76            "density"             => HistNorm::Density,
77            "probability density" => HistNorm::ProbabilityDensity,
78            ""                    => HistNorm::Default,
79        }),
80    }?;
81
82    let hist = if let Some(marker_obj) = hist_obj.get_mut("marker")
83        && marker_obj.is_object()
84    {
85        let marker = plotly::common::Marker::new();
86        let marker = translate! {
87            marker,
88            marker_obj,
89            map,
90            (color, Color),
91            (opacity, f64),
92            (size, usize),
93            (size_array, Vec<usize>),
94            (max_displayed, usize),
95            (size_ref, usize),
96            (size_min, usize),
97            (cauto, bool),
98            (cmax, f64),
99            (cmin, f64),
100            (cmid, f64),
101            (auto_color_scale, bool),
102            (reverse_scale, bool),
103            (show_scale, bool),
104            (outlier_color, Color)
105        }?;
106
107        use plotly::common::{MarkerSymbol, SizeMode};
108        let marker = translate_enum! {
109            marker,
110            marker_obj,
111            map,
112            (symbol, {
113                "circle" =>         MarkerSymbol::Circle,
114                "square" =>         MarkerSymbol::Square,
115                "diamond" =>        MarkerSymbol::Diamond,
116                "cross" =>          MarkerSymbol::Cross,
117                "x" =>              MarkerSymbol::X,
118                "triangle-up" =>    MarkerSymbol::TriangleUp,
119                "triangle-down" =>  MarkerSymbol::TriangleDown,
120                "triangle-left" =>  MarkerSymbol::TriangleLeft,
121                "triangle-right" => MarkerSymbol::TriangleRight,
122                "pentagon" =>       MarkerSymbol::Pentagon,
123                "hexagon" =>        MarkerSymbol::Hexagon,
124            }),
125            (size_mode, {
126                "area" => SizeMode::Area,
127                "diameter" => SizeMode::Diameter,
128            }),
129        }?;
130        hist.marker(marker)
131    } else {
132        hist
133    };
134
135    Ok(hist)
136}