plotly/traces/
density_mapbox.rs

1//! Density mapbox scatter plot
2
3use plotly_derive::FieldSetter;
4use serde::Serialize;
5
6use crate::common::{LegendGroupTitle, Line, PlotType, Visible};
7use crate::Trace;
8
9#[serde_with::skip_serializing_none]
10#[derive(Serialize, Clone, Debug, FieldSetter)]
11#[field_setter(box_self, kind = "trace")]
12pub struct DensityMapbox<Lat, Lon, Z>
13where
14    Lat: Serialize + Clone,
15    Lon: Serialize + Clone,
16    Z: Serialize + Clone,
17{
18    #[field_setter(default = "PlotType::DensityMapbox")]
19    r#type: PlotType,
20    /// Sets the trace name. The trace name appear as the legend item and on
21    /// hover.
22    name: Option<String>,
23    /// Determines whether or not this trace is visible. If
24    /// `Visible::LegendOnly`, the trace is not drawn, but can appear as a
25    /// legend item (provided that the legend itself is visible).
26    visible: Option<Visible>,
27
28    /// Determines whether or not an item corresponding to this trace is shown
29    /// in the legend.
30    #[serde(rename = "showlegend")]
31    show_legend: Option<bool>,
32
33    /// Sets the legend rank for this trace. Items and groups with smaller ranks
34    /// are presented on top/left side while with `"reversed"
35    /// `legend.trace_order` they are on bottom/right side. The default
36    /// legendrank is 1000, so that you can use ranks less than 1000 to
37    /// place certain items before all unranked items, and ranks greater
38    /// than 1000 to go after all unranked items.
39    #[serde(rename = "legendrank")]
40    legend_rank: Option<usize>,
41    /// Sets the legend group for this trace. Traces part of the same legend
42    /// group show/hide at the same time when toggling legend items.
43    #[serde(rename = "legendgroup")]
44    legend_group: Option<String>,
45    /// Set and style the title to appear for the legend group.
46    #[serde(rename = "legendgrouptitle")]
47    legend_group_title: Option<LegendGroupTitle>,
48
49    /// Line display properties.
50    line: Option<Line>,
51
52    lat: Option<Vec<Lat>>,
53    lon: Option<Vec<Lon>>,
54    z: Option<Vec<Z>>,
55
56    /// Sets the opacity of the trace.
57    opacity: Option<f64>,
58
59    /// Sets a reference between this trace's data coordinates and a mapbox
60    /// subplot. If "mapbox" (the default value), the data refer to
61    /// `layout.mapbox`. If "mapbox2", the data refer to `layout.mapbox2`, and
62    /// so on.
63    subplot: Option<String>,
64
65    /// Determines whether or not the color domain is computed
66    /// with respect to the input data (here in `z`) or the bounds set
67    /// in `zmin` and `zmax`. Defaults to false when `zmin` and `zmax` are
68    /// set by the user.
69    zauto: Option<bool>,
70
71    /// Sets the upper bound of the color domain. Value should have the
72    /// same units as in `z` and if set, `zmin` must be set as well.
73    zmax: Option<Z>,
74
75    zmid: Option<Z>,
76
77    zmin: Option<Z>,
78
79    zoom: Option<u8>,
80
81    radius: Option<u8>,
82    //color_continuous_scale: Option<HashMap<Z, NamedColor>>,
83    //color_continuous_midpoint: Option<ContinuousColorScale>,
84}
85
86impl<Lat, Lon, Z> DensityMapbox<Lat, Lon, Z>
87where
88    Lat: Serialize + Clone + std::default::Default, // TODO why is "+ Default" necessary?
89    Lon: Serialize + Clone + std::default::Default,
90    Z: Serialize + Clone + std::default::Default,
91{
92    pub fn new(lat: Vec<Lat>, lon: Vec<Lon>, z: Vec<Z>) -> Box<Self> {
93        Box::new(Self {
94            lat: Some(lat),
95            lon: Some(lon),
96            z: Some(z),
97            ..Default::default()
98        })
99    }
100}
101
102impl<Lat, Lon, Z> Trace for DensityMapbox<Lat, Lon, Z>
103where
104    Lat: Serialize + Clone,
105    Lon: Serialize + Clone,
106    Z: Serialize + Clone,
107{
108    fn to_json(&self) -> String {
109        serde_json::to_string(&self).unwrap()
110    }
111}
112
113#[cfg(test)]
114mod tests {
115    use serde_json::{json, to_value};
116
117    use super::*;
118
119    #[test]
120    fn serialize_density_mapbox() {
121        let density_mapbox = DensityMapbox::new(vec![45.5017], vec![-73.5673], vec![1.0])
122            .name("name")
123            .visible(Visible::True)
124            .show_legend(true)
125            .legend_rank(1000)
126            .legend_group("legend group")
127            .zoom(5)
128            .radius(20)
129            .opacity(0.5);
130        let expected = json!({
131            "type": "densitymapbox",
132            "lat": [45.5017],
133            "lon": [-73.5673],
134            "z": [1.0],
135            "name": "name",
136            "visible": true,
137            "showlegend": true,
138            "legendrank": 1000,
139            "legendgroup": "legend group",
140            "opacity": 0.5,
141            "zoom": 5,
142            "radius": 20,
143        });
144        assert_eq!(to_value(density_mapbox.clone()).unwrap(), expected);
145    }
146}