Skip to main content

mdbook_plotly/code_handler/plot_obj_parser/
histogram_parser.rs

1use super::common::parse_marker;
2use super::until::must_translate_from_context;
3use crate::code_handler::parse_context::ParseContext;
4use crate::{translate_enum_with_config, translate_with_config};
5use anyhow::{Result, anyhow};
6use plotly::{Histogram, Trace};
7
8pub fn parse_histogram_data(
9    hist_obj: &mut serde_json::Value,
10    context: &ParseContext<'_>,
11) -> Result<Box<Histogram<f64>>> {
12    let has_x = hist_obj.get("x").is_some();
13    let has_y = hist_obj.get("y").is_some();
14    let hist = match (has_x, has_y) {
15        (true, true) => {
16            let x: Vec<f64> = must_translate_from_context(hist_obj, context, "x")?;
17            let y: Vec<f64> = must_translate_from_context(hist_obj, context, "y")?;
18            Histogram::new_xy(x, y)
19        }
20        (true, false) => {
21            let x: Vec<f64> = must_translate_from_context(hist_obj, context, "x")?;
22            Histogram::new(x)
23        }
24        (false, true) => {
25            let y: Vec<f64> = must_translate_from_context(hist_obj, context, "y")?;
26            Histogram::new_vertical(y)
27        }
28        (false, false) => {
29            return Err(anyhow!("histogram requires at least 'x' or 'y' data"));
30        }
31    };
32    let hist = translate_with_config! {
33        hist,
34        hist_obj,
35        context.map(),
36        context.map_eval(),
37        (name, String),
38        (show_legend, bool),
39        (legend_group, String),
40        (opacity, f64),
41        (text, String),
42        (text_array, Vec<String>),
43        (hover_text, String),
44        (hover_text_array, Vec<String>),
45        (hover_template, String),
46        (hover_template_array, Vec<String>),
47        (auto_bin_x, bool),
48        (n_bins_x, usize),
49        (auto_bin_y, bool),
50        (n_bins_y, usize),
51        (alignment_group, String),
52        (offset_group, String),
53        (bin_group, String),
54        (x_axis, String),
55        (y_axis, String),
56    }?;
57
58    use plotly::common::Orientation;
59    use plotly::histogram::{HistFunc, HistNorm};
60
61    let hist = translate_enum_with_config! {
62        hist,
63        hist_obj,
64        context.map(),
65        context.map_eval(),
66        (orientation, {
67            "v" => Orientation::Vertical,
68            "h" => Orientation::Horizontal,
69        }),
70        (hist_func, {
71            "count" => HistFunc::Count,
72            "sum"   => HistFunc::Sum,
73            "avg"   => HistFunc::Average,
74            "min"   => HistFunc::Minimum,
75            "max"   => HistFunc::Maximum,
76        }),
77        (hist_norm, {
78            "percent"             => HistNorm::Percent,
79            "probability"         => HistNorm::Probability,
80            "density"             => HistNorm::Density,
81            "probability density" => HistNorm::ProbabilityDensity,
82            ""                    => HistNorm::Default,
83        }),
84    }?;
85
86    let hist = if let Some(marker_obj) = hist_obj.get_mut("marker")
87        && marker_obj.is_object()
88    {
89        let marker = parse_marker(marker_obj, context)?;
90        hist.marker(marker)
91    } else {
92        hist
93    };
94
95    Ok(hist)
96}
97
98pub fn parse_histogram_trace(
99    hist_obj: &mut serde_json::Value,
100    context: &ParseContext<'_>,
101) -> Result<Box<dyn Trace>> {
102    Ok(parse_histogram_data(hist_obj, context)?)
103}