Skip to content

Commit 1d0e231

Browse files
Guillaume W. Bresgwbres
Guillaume W. Bres
authored andcommitted
Introducing DensityMapbox
Signed-off-by: Guillaume W. Bres <[email protected]>
1 parent 3a9f7ef commit 1d0e231

File tree

4 files changed

+177
-2
lines changed

4 files changed

+177
-2
lines changed

Diff for: plotly/src/common/mod.rs

+1
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,7 @@ pub enum PlotType {
201201
Ohlc,
202202
Sankey,
203203
Surface,
204+
DensityMapbox,
204205
}
205206

206207
#[derive(Serialize, Clone, Debug)]

Diff for: plotly/src/lib.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,8 @@ pub use plot::{ImageFormat, Plot, Trace};
3333
pub use traces::{box_plot, contour, histogram, image, mesh3d, sankey, scatter_mapbox, surface};
3434
// Bring the different trace types into the top-level scope
3535
pub use traces::{
36-
Bar, BoxPlot, Candlestick, Contour, HeatMap, Histogram, Image, Mesh3D, Ohlc, Sankey, Scatter,
37-
Scatter3D, ScatterMapbox, ScatterPolar, Surface,
36+
Bar, BoxPlot, Candlestick, Contour, DensityMapbox, HeatMap, Histogram, Image, MapboxCenter,
37+
Mesh3D, Ohlc, Sankey, Scatter, Scatter3D, ScatterMapbox, ScatterPolar, Surface,
3838
};
3939

4040
pub trait Restyle: serde::Serialize {}

Diff for: plotly/src/traces/density_mapbox.rs

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

Diff for: plotly/src/traces/mod.rs

+2
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ pub mod bar;
44
pub mod box_plot;
55
mod candlestick;
66
pub mod contour;
7+
mod density_mapbox;
78
mod heat_map;
89
pub mod histogram;
910
pub mod image;
@@ -20,6 +21,7 @@ pub use bar::Bar;
2021
pub use box_plot::BoxPlot;
2122
pub use candlestick::Candlestick;
2223
pub use contour::Contour;
24+
pub use density_mapbox::{DensityMapbox, MapboxCenter};
2325
pub use heat_map::HeatMap;
2426
pub use histogram::Histogram;
2527
pub use mesh3d::Mesh3D;

0 commit comments

Comments
 (0)