Skip to content

Commit 0071831

Browse files
authored
Impl Color for f64 (+ f32, i64, i32, ...) (#155)
* added impl Color for number types + colorscale example * fixed colorscale in customized_scatter3d_plot
1 parent 8713ad2 commit 0071831

File tree

3 files changed

+99
-4
lines changed

3 files changed

+99
-4
lines changed

examples/3d_charts/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,4 +6,5 @@ edition = "2021"
66

77
[dependencies]
88
ndarray = "0.15.6"
9+
rand = "0.8.5"
910
plotly = { path = "../../plotly" }

examples/3d_charts/src/main.rs

Lines changed: 73 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,11 @@
33
use ndarray::Array;
44
use plotly::{
55
color::Rgb,
6-
common::{ColorScale, ColorScalePalette, Font, Marker, MarkerSymbol, Mode, Title},
6+
common::{ColorBar, ColorScale, ColorScalePalette, Font, Marker, MarkerSymbol, Mode, Title},
77
layout::{Axis, Camera, Layout, LayoutScene, Legend, Margin, ProjectionType},
88
Mesh3D, Plot, Scatter3D, Surface,
99
};
10+
use rand::Rng;
1011

1112
// 3D Scatter Plots
1213
fn simple_scatter3d_plot() {
@@ -41,10 +42,11 @@ fn customized_scatter3d_plot() {
4142
.map(|i| (i.abs() * 25f64) as usize)
4243
.collect(),
4344
)
44-
.color_scale(ColorScale::Palette(ColorScalePalette::Viridis)),
45+
.color_scale(ColorScale::Palette(ColorScalePalette::Viridis))
46+
.color_array(z.clone()),
4547
);
4648

47-
let trace2 = Scatter3D::new(t, z, y)
49+
let trace2 = Scatter3D::new(t, z.clone(), y)
4850
.name("Helix 2")
4951
.mode(Mode::Markers)
5052
.marker(
@@ -55,7 +57,8 @@ fn customized_scatter3d_plot() {
5557
.map(|i| (i.abs() * 25f64) as usize)
5658
.collect(),
5759
)
58-
.color_scale(ColorScale::Palette(ColorScalePalette::Viridis)),
60+
.color_scale(ColorScale::Palette(ColorScalePalette::Viridis))
61+
.color_array(z),
5962
);
6063

6164
let mut plot = Plot::new();
@@ -161,13 +164,79 @@ fn mesh_3d_plot() {
161164
plot.show();
162165
}
163166

167+
fn colorscale_plot() {
168+
let mut plot = Plot::new();
169+
170+
let x = (0..100)
171+
.map(|x| ((x - 50) as f64) / 100f64)
172+
.collect::<Vec<f64>>();
173+
174+
let y = x.clone();
175+
176+
let iproduct = |x: &[f64], y: &[f64]| -> Vec<(f64, f64)> {
177+
let mut result = Vec::new();
178+
for x in x {
179+
for y in y {
180+
result.push((*x, *y));
181+
}
182+
}
183+
result
184+
};
185+
186+
let ((x, y), z): ((Vec<f64>, Vec<f64>), Vec<f64>) = iproduct(&x, &y)
187+
.into_iter()
188+
.map(|(x, y)| ((x, y), -(x.powi(2) + y.powi(2)) + 0.5))
189+
.unzip();
190+
191+
let color: Vec<f32> = z.clone().into_iter().rev().map(|x| x as f32).collect();
192+
let _color: Vec<usize> = (0..z.len()).collect();
193+
let _color: Vec<u8> = (0..z.len()).map(|x| x as u8).collect();
194+
let _color: Vec<i16> = {
195+
let mut rng = rand::thread_rng();
196+
(0..z.len()).map(|_| rng.gen_range(0..100)).collect()
197+
};
198+
199+
let color_max = color.iter().fold(f64::MIN, |acc, x| acc.max(*x as f64));
200+
201+
let colorscale = ColorScalePalette::YlGnBu;
202+
203+
let marker = Marker::new()
204+
.color_array(color)
205+
.color_scale(plotly::common::ColorScale::Palette(colorscale.clone()))
206+
.cauto(false)
207+
.cmax(color_max * 1.5)
208+
.color_bar(ColorBar::new());
209+
210+
let scatter = Scatter3D::new(x, y, z).mode(Mode::Markers).marker(marker);
211+
212+
plot.add_trace(scatter);
213+
214+
let layout = Layout::new()
215+
.font(Font::new().size(18).family("Palatino-Linotype"))
216+
.title(format!("Colorscale: {colorscale:?}").as_str().into())
217+
.width(1200)
218+
.height(1000)
219+
.scene(
220+
LayoutScene::new()
221+
.aspect_mode(plotly::layout::AspectMode::Data)
222+
.x_axis(Axis::new().tick_format(".1f"))
223+
.y_axis(Axis::new().tick_format(".1f"))
224+
.z_axis(Axis::new().tick_format(".1f")),
225+
);
226+
227+
plot.set_layout(layout);
228+
229+
plot.show();
230+
}
231+
164232
fn main() {
165233
// Uncomment any of these lines to display the example.
166234

167235
// Scatter3D Plots
168236
// simple_scatter3d_plot();
169237
// simple_line3d_plot();
170238
// customized_scatter3d_plot();
239+
// colorscale_plot();
171240

172241
// Surface Plots
173242
// surface_plot();

plotly/src/common/color.rs

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,17 @@ impl Color for &'static str {}
3333
impl Color for String {}
3434
impl Color for Rgb {}
3535
impl Color for Rgba {}
36+
impl Color for f64 {}
37+
impl Color for f32 {}
38+
impl Color for u64 {}
39+
impl Color for u32 {}
40+
impl Color for u16 {}
41+
impl Color for u8 {}
42+
impl Color for i64 {}
43+
impl Color for i32 {}
44+
impl Color for i16 {}
45+
impl Color for i8 {}
46+
impl Color for usize {}
3647

3748
/// ColorArray is only used internally to provide a helper method for converting
3849
/// Vec<impl Color> to Vec<Box<dyn Color>>, as we would otherwise fall foul of
@@ -290,6 +301,20 @@ mod tests {
290301
assert_eq!(to_value(color).unwrap(), json!("any_arbitrary_string"));
291302
}
292303

304+
#[test]
305+
fn test_serialize_numbers() {
306+
assert_eq!(to_value(1f64).unwrap(), json!(1f64));
307+
assert_eq!(to_value(1f32).unwrap(), json!(1f32));
308+
assert_eq!(to_value(1i64).unwrap(), json!(1i64));
309+
assert_eq!(to_value(1i32).unwrap(), json!(1i32));
310+
assert_eq!(to_value(1i16).unwrap(), json!(1i16));
311+
assert_eq!(to_value(1i8).unwrap(), json!(1i8));
312+
assert_eq!(to_value(1u64).unwrap(), json!(1u64));
313+
assert_eq!(to_value(1u32).unwrap(), json!(1u32));
314+
assert_eq!(to_value(1u16).unwrap(), json!(1u16));
315+
assert_eq!(to_value(1u8).unwrap(), json!(1u8));
316+
}
317+
293318
#[test]
294319
#[rustfmt::skip]
295320
fn test_serialize_named_color() {

0 commit comments

Comments
 (0)