From 5112b85479adc66af948efa59b5aa9a912460b3b Mon Sep 17 00:00:00 2001 From: mjpauly Date: Thu, 27 Jul 2023 03:09:42 -0700 Subject: [PATCH 01/39] add colorbar orientation field (#152) --- plotly/src/common/mod.rs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/plotly/src/common/mod.rs b/plotly/src/common/mod.rs index fc98e6e9..44fece3a 100644 --- a/plotly/src/common/mod.rs +++ b/plotly/src/common/mod.rs @@ -750,6 +750,7 @@ pub struct ColorBar { len_mode: Option, #[serde(rename = "nticks")] n_ticks: Option, + orientation: Option, #[serde(rename = "outlinecolor")] outline_color: Option>, #[serde(rename = "outlinewidth")] @@ -852,6 +853,11 @@ impl ColorBar { self } + pub fn orientation(mut self, orientation: Orientation) -> Self { + self.orientation = Some(orientation); + self + } + pub fn outline_color(mut self, outline_color: C) -> Self { self.outline_color = Some(Box::new(outline_color)); self @@ -1662,6 +1668,7 @@ mod tests { .len(99) .len_mode(ThicknessMode::Pixels) .n_ticks(500) + .orientation(Orientation::Horizontal) .outline_color("#789456") .outline_width(7) .separate_thousands(true) @@ -1702,6 +1709,7 @@ mod tests { "len": 99, "lenmode": "pixels", "nticks": 500, + "orientation": "h", "outlinecolor": "#789456", "outlinewidth": 7, "separatethousands": true, From 3a9f7ef8f0a29b11afe1a6bb808d2568ad9b5d6f Mon Sep 17 00:00:00 2001 From: Tectin <94180412+tectin0@users.noreply.github.com> Date: Thu, 27 Jul 2023 11:09:30 +0000 Subject: [PATCH 02/39] Add `LayoutScene` (#153) * added AspectMode and LayoutScene * added Camera for LayoutScene with Eye, Up and Projection (Center is missing) * updated 3d_charts example * added layout_scene test + fixed layout_scene.drag_mode type * implemented CameraCenter + more methods + added documentation and tests * added DragMode3D because not all variants from DragMode are valid in 3D * expanded the customized scatter3d plot in the examples * updated imports in examples/3d_charts * Updated CHANGELOG.md Draft for CHANGELOG.md * fixed typo * default derive instead of manual implementation * appease clippy * update changelog * resolve TODOs --------- Co-authored-by: = <=> Co-authored-by: Michael Freeborn --- CHANGELOG.md | 4 + examples/3d_charts/src/main.rs | 72 ++++-- plotly/.gitignore | 1 + plotly/src/layout/mod.rs | 442 ++++++++++++++++++++++++++++++++- 4 files changed, 501 insertions(+), 18 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 58404853..e0a39420 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,10 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [0.8.5] - 2023-xx-xx +### Added +- [[#153](https://github.com/igiagkiozis/plotly/pull/153)] Added `LayoutScene` + ## [0.8.4] - 2023-07-09 ### Added - [[#143](https://github.com/igiagkiozis/plotly/pull/143)] Widen version range of `askama`. diff --git a/examples/3d_charts/src/main.rs b/examples/3d_charts/src/main.rs index d5bf785a..87653b57 100644 --- a/examples/3d_charts/src/main.rs +++ b/examples/3d_charts/src/main.rs @@ -2,8 +2,9 @@ use ndarray::Array; use plotly::{ - common::{ColorScale, ColorScalePalette, Marker, MarkerSymbol, Mode, Title}, - layout::{Axis, Layout}, + color::Rgb, + common::{ColorScale, ColorScalePalette, Font, Marker, MarkerSymbol, Mode, Title}, + layout::{Axis, Camera, Layout, LayoutScene, Legend, Margin, ProjectionType}, Mesh3D, Plot, Scatter3D, Surface, }; @@ -29,6 +30,7 @@ fn customized_scatter3d_plot() { let sizelookup = z.clone(); let trace = Scatter3D::new(t.clone(), y.clone(), z.iter().map(|i| -i).collect()) + .name("Helix 1") .mode(Mode::Markers) .marker( Marker::new() @@ -42,25 +44,65 @@ fn customized_scatter3d_plot() { .color_scale(ColorScale::Palette(ColorScalePalette::Viridis)), ); - let trace2 = Scatter3D::new(t, z, y).mode(Mode::Markers).marker( - Marker::new() - .size_array( - sizelookup - .iter() - .map(|i| (i.abs() * 25f64) as usize) - .collect(), - ) - .color_scale(ColorScale::Palette(ColorScalePalette::Viridis)), - ); + let trace2 = Scatter3D::new(t, z, y) + .name("Helix 2") + .mode(Mode::Markers) + .marker( + Marker::new() + .size_array( + sizelookup + .iter() + .map(|i| (i.abs() * 25f64) as usize) + .collect(), + ) + .color_scale(ColorScale::Palette(ColorScalePalette::Viridis)), + ); let mut plot = Plot::new(); plot.add_trace(trace); plot.add_trace(trace2); + + let background_color: Rgb = Rgb::new(70, 70, 70); + let front_color: Rgb = Rgb::new(255, 255, 255); + let layout = Layout::new() .title("Helix".into()) - .x_axis(Axis::new().title("x (A meaningful axis name goes here)".into())) - .y_axis(Axis::new().title(Title::new("This is the label of the Y axis"))) - .z_axis(Axis::new().title("z Axis".into())); + .legend(Legend::new().x(0.9).y(0.9)) + .font(Font::new().color(front_color)) + .paper_background_color(background_color) + .scene( + LayoutScene::new() + .x_axis( + Axis::new() + .title("x (A meaningful axis name goes here)".into()) + .tick_angle(0f64) + .grid_color(front_color) + .color(front_color), + ) + .y_axis( + Axis::new() + .title(Title::new("This is the label of the Y axis")) + .tick_format(".1f") + .grid_color(front_color) + .color(front_color), + ) + .z_axis(Axis::new().title("".into()).tick_values(vec![])) + .aspect_mode(plotly::layout::AspectMode::Manual) + .aspect_ratio((3.0, 1.0, 1.0).into()) + .camera( + Camera::new() + .projection(ProjectionType::Orthographic.into()) + .eye((0.0, 0.0, 1.0).into()) + .up((0.0, 1.0, 0.0).into()) + .center((0.0, 0.0, 0.0).into()), + ) + .drag_mode(plotly::layout::DragMode3D::Pan) + .hover_mode(plotly::layout::HoverMode::Closest) + .background_color(background_color), + ) + .margin(Margin::new().left(0).right(0).top(50).bottom(0)) + .width(1000) + .height(500); plot.set_layout(layout); plot.show(); diff --git a/plotly/.gitignore b/plotly/.gitignore index 68f62957..108a47cd 100644 --- a/plotly/.gitignore +++ b/plotly/.gitignore @@ -2,3 +2,4 @@ target/ .idea Cargo.lock gh-pages/ +.vscode diff --git a/plotly/src/layout/mod.rs b/plotly/src/layout/mod.rs index 2f77871b..6026e6ed 100644 --- a/plotly/src/layout/mod.rs +++ b/plotly/src/layout/mod.rs @@ -1283,6 +1283,31 @@ impl Serialize for DragMode { } } +#[derive(Debug, Clone)] +/// Determines the mode of drag interactions. +pub enum DragMode3D { + Zoom, + Pan, + Turntable, + Orbit, + False, +} + +impl Serialize for DragMode3D { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + match *self { + Self::Zoom => serializer.serialize_str("zoom"), + Self::Pan => serializer.serialize_str("pan"), + Self::Turntable => serializer.serialize_str("turntable"), + Self::Orbit => serializer.serialize_str("orbit"), + Self::False => serializer.serialize_bool(false), + } + } +} + #[derive(Serialize, Debug, Clone)] #[serde(rename_all = "lowercase")] pub enum SelectDirection { @@ -1360,6 +1385,236 @@ impl Mapbox { } } +#[derive(Serialize, Debug, Clone)] +/// If "cube", this scene's axes are drawn as a cube, regardless of the axes' +/// ranges. If "data", this scene's axes are drawn in proportion with the axes' +/// ranges. If "manual", this scene's axes are drawn in proportion with the +/// input of "aspectratio" (the default behavior if "aspectratio" is provided). +/// If "auto", this scene's axes are drawn using the results of "data" except +/// when one axis is more than four times the size of the two others, where in +/// that case the results of "cube" are used. +/// Default: "auto" +#[derive(Default)] +pub enum AspectMode { + #[serde(rename = "auto")] + #[default] + Auto, + #[serde(rename = "cube")] + Cube, + #[serde(rename = "data")] + Data, + #[serde(rename = "manual")] + Manual, +} + +#[serde_with::skip_serializing_none] +#[derive(Serialize, Debug, Clone, FieldSetter)] +/// Sets the (x, y, z) components of the 'eye' camera vector. This vector +/// determines the view point about the origin of this scene. +/// Default: {x: 1.25, y: 1.25, z: 1.25} +pub struct Eye { + x: Option, + y: Option, + z: Option, +} + +impl Eye { + pub fn new() -> Self { + Eye { + x: Some(1.25), + y: Some(1.25), + z: Some(1.25), + } + } +} + +impl From<(f64, f64, f64)> for Eye { + fn from((x, y, z): (f64, f64, f64)) -> Self { + Eye { + x: Some(x), + y: Some(y), + z: Some(z), + } + } +} + +#[serde_with::skip_serializing_none] +#[derive(Serialize, Debug, Clone, FieldSetter)] +/// Sets the (x, y, z) components of the 'up' camera vector. This vector +/// determines the up direction of this scene with respect to the page. The +/// Default: {x: 0, y: 0, z: 1} which means that the z axis points up. +pub struct Up { + x: Option, + y: Option, + z: Option, +} + +impl Up { + pub fn new() -> Self { + Up { + x: Some(0.0), + y: Some(0.0), + z: Some(1.0), + } + } +} + +impl From<(f64, f64, f64)> for Up { + fn from((x, y, z): (f64, f64, f64)) -> Self { + Up { + x: Some(x), + y: Some(y), + z: Some(z), + } + } +} + +#[derive(Default, Serialize, Debug, Clone)] +/// Sets the projection type. The projection type could be either "perspective" +/// or "orthographic". +/// Default: "perspective" +pub enum ProjectionType { + #[default] + #[serde(rename = "perspective")] + Perspective, + #[serde(rename = "orthographic")] + Orthographic, +} + +impl From for Projection { + fn from(projection_type: ProjectionType) -> Self { + Projection { + projection_type: Some(projection_type), + } + } +} + +#[serde_with::skip_serializing_none] +#[derive(Serialize, Debug, Clone, FieldSetter)] +/// Container for Projection options. +pub struct Projection { + #[serde(rename = "type")] + projection_type: Option, +} + +impl Projection { + pub fn new() -> Self { + Default::default() + } +} + +#[serde_with::skip_serializing_none] +#[derive(Serialize, Debug, Clone, FieldSetter)] +/// Sets the (x, y, z) components of the 'center' camera vector. This vector +/// determines the translation (x, y, z) space about the center of this scene. +/// Default: {x: 0, y: 0, z: 0} which means that the center of the scene is at +/// the origin. +pub struct CameraCenter { + x: Option, + y: Option, + z: Option, +} + +impl CameraCenter { + pub fn new() -> Self { + CameraCenter { + x: Some(0.0), + y: Some(0.0), + z: Some(0.0), + } + } +} + +impl From<(f64, f64, f64)> for CameraCenter { + fn from((x, y, z): (f64, f64, f64)) -> Self { + CameraCenter { + x: Some(x), + y: Some(y), + z: Some(z), + } + } +} + +#[serde_with::skip_serializing_none] +#[derive(Serialize, Debug, Clone, FieldSetter)] +/// Container for CameraCenter, Eye, Up, and Projection objects. The camera of a +/// 3D scene. +pub struct Camera { + center: Option, + eye: Option, + up: Option, + projection: Option, +} + +impl Camera { + pub fn new() -> Self { + Default::default() + } +} + +#[serde_with::skip_serializing_none] +#[derive(Serialize, Debug, Clone, FieldSetter)] +/// Sets this scene's axis aspectratio. +/// x, y, z must be positive. +/// Default: {x: 1, y: 1, z: 1} +pub struct AspectRatio { + x: Option, + y: Option, + z: Option, +} + +impl AspectRatio { + pub fn new() -> Self { + AspectRatio { + x: Some(1.0), + y: Some(1.0), + z: Some(1.0), + } + } +} + +impl From<(f64, f64, f64)> for AspectRatio { + fn from((x, y, z): (f64, f64, f64)) -> Self { + AspectRatio { + x: Some(x), + y: Some(y), + z: Some(z), + } + } +} + +#[serde_with::skip_serializing_none] +#[derive(Serialize, Debug, Clone, FieldSetter)] +/// 3D scene layout +pub struct LayoutScene { + #[serde(rename = "bgcolor")] + background_color: Option>, + camera: Option, + #[serde(rename = "aspectmode")] + aspect_mode: Option, + #[serde(rename = "aspectratio")] + aspect_ratio: Option, + #[serde(rename = "xaxis")] + x_axis: Option, + #[serde(rename = "yaxis")] + y_axis: Option, + #[serde(rename = "zaxis")] + z_axis: Option, + #[serde(rename = "dragmode")] + drag_mode: Option, + #[serde(rename = "hovermode")] + hover_mode: Option, + annotations: Option>, + // domain: Domain, + // uirevision: Uirevision, +} + +impl LayoutScene { + pub fn new() -> Self { + Default::default() + } +} + #[serde_with::skip_serializing_none] #[derive(Serialize, Debug, Clone, FieldSetter)] pub struct Template { @@ -1481,7 +1736,7 @@ pub struct LayoutTemplate { y_axis8: Option>, // ternary: Option, - // scene: Option, + scene: Option, // polar: Option, annotations: Option>, shapes: Option>, @@ -1665,7 +1920,7 @@ pub struct Layout { z_axis8: Option>, // ternary: Option, - // scene: Option, + scene: Option, // polar: Option, annotations: Option>, shapes: Option>, @@ -2908,7 +3163,8 @@ mod tests { .extend_pie_colors(true) .sunburst_colorway(vec!["#654654"]) .extend_sunburst_colors(false) - .z_axis(Axis::new()); + .z_axis(Axis::new()) + .scene(LayoutScene::new()); let expected = json!({ "title": {"text": "Title"}, @@ -2975,8 +3231,188 @@ mod tests { "sunburstcolorway": ["#654654"], "extendsunburstcolors": false, "zaxis": {}, + "scene": {} + }); + + assert_eq!(to_value(layout).unwrap(), expected); + } + + #[test] + fn test_serialize_layout_scene() { + let layout = Layout::new().scene( + LayoutScene::new() + .x_axis(Axis::new()) + .y_axis(Axis::new()) + .z_axis(Axis::new()) + .camera(Camera::new()) + .aspect_mode(AspectMode::Auto) + .hover_mode(HoverMode::Closest) + .drag_mode(DragMode3D::Turntable) + .background_color("#FFFFFF") + .annotations(vec![Annotation::new()]), + ); + + let expected = json!({ + "scene": { + "xaxis": {}, + "yaxis": {}, + "zaxis": {}, + "camera": {}, + "aspectmode": "auto", + "hovermode": "closest", + "dragmode": "turntable", + "bgcolor": "#FFFFFF", + "annotations": [{}], + } }); assert_eq!(to_value(layout).unwrap(), expected); } + + #[test] + fn test_serialize_eye() { + let eye = Eye::new(); + + assert_eq!( + to_value(eye).unwrap(), + json!({ + "x": 1.25, + "y": 1.25, + "z": 1.25, + }) + ); + + let eye = Eye::new().x(1f64).y(2f64).z(3f64); + + let expected = json!({ + "x": 1.0, + "y": 2.0, + "z": 3.0, + }); + + assert_eq!(to_value(eye).unwrap(), expected); + + let eye: Eye = (1f64, 2f64, 3f64).into(); + + assert_eq!(to_value(eye).unwrap(), expected); + } + + #[test] + fn test_serialize_projection() { + let projection = Projection::new().projection_type(ProjectionType::default()); + + let expected = json!({ + "type": "perspective", + }); + + assert_eq!(to_value(projection).unwrap(), expected); + + let projection = Projection::new().projection_type(ProjectionType::Orthographic); + + let expected = json!({ + "type": "orthographic", + }); + + assert_eq!(to_value(projection).unwrap(), expected); + + let projection: Projection = ProjectionType::Orthographic.into(); + + assert_eq!(to_value(projection).unwrap(), expected); + } + + #[test] + fn test_serialize_camera_center() { + let camera_center = CameraCenter::new(); + + let expected = json!({ + "x": 0.0, + "y": 0.0, + "z": 0.0, + }); + + assert_eq!(to_value(camera_center).unwrap(), expected); + + let camera_center = CameraCenter::new().x(1f64).y(2f64).z(3f64); + + let expected = json!({ + "x": 1.0, + "y": 2.0, + "z": 3.0, + }); + + assert_eq!(to_value(camera_center).unwrap(), expected); + + let camera_center: CameraCenter = (1f64, 2f64, 3f64).into(); + + assert_eq!(to_value(camera_center).unwrap(), expected); + } + + #[test] + fn test_serialize_aspect_ratio() { + let aspect_ratio = AspectRatio::new(); + + let expected = json!({ + "x": 1.0, + "y": 1.0, + "z": 1.0, + }); + + assert_eq!(to_value(aspect_ratio).unwrap(), expected); + + let aspect_ratio = AspectRatio::new().x(1f64).y(2f64).z(3f64); + + let expected = json!({ + "x": 1.0, + "y": 2.0, + "z": 3.0, + }); + + assert_eq!(to_value(aspect_ratio).unwrap(), expected); + + let aspect_ratio: AspectRatio = (1f64, 2f64, 3f64).into(); + + assert_eq!(to_value(aspect_ratio).unwrap(), expected); + } + + #[test] + fn test_serialize_aspect_mode() { + let aspect_mode = AspectMode::default(); + + assert_eq!(to_value(aspect_mode).unwrap(), json!("auto")); + + let aspect_mode = AspectMode::Data; + + assert_eq!(to_value(aspect_mode).unwrap(), json!("data")); + + let aspect_mode = AspectMode::Cube; + + assert_eq!(to_value(aspect_mode).unwrap(), json!("cube")); + } + + #[test] + fn test_serialize_up() { + let up = Up::new(); + + let expected = json!({ + "x": 0.0, + "y": 0.0, + "z": 1.0, + }); + + assert_eq!(to_value(up).unwrap(), expected); + + let up = Up::new().x(1f64).y(2f64).z(3f64); + + let expected = json!({ + "x": 1.0, + "y": 2.0, + "z": 3.0, + }); + + assert_eq!(to_value(up).unwrap(), expected); + + let up: Up = (1f64, 2f64, 3f64).into(); + + assert_eq!(to_value(up).unwrap(), expected); + } } From cdaa092fee262733ac6bbae34095caf7278bad66 Mon Sep 17 00:00:00 2001 From: Shaun Jackman Date: Wed, 24 Apr 2024 04:23:55 -0700 Subject: [PATCH 03/39] Enable Dependabot (#168) --- .github/dependabot.yml | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 .github/dependabot.yml diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 00000000..83bcd989 --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,7 @@ +version: 2 + +updates: + - package-ecosystem: cargo + directory: / + schedule: + interval: daily From 4eb50ae3eb8fea494941f8c599a43d238c65ecd4 Mon Sep 17 00:00:00 2001 From: Adrian Reber Date: Mon, 29 Apr 2024 10:17:46 +0200 Subject: [PATCH 04/39] Automatically install kaleido binaries also on Linux aarch64 (#191) Signed-off-by: Adrian Reber --- plotly_kaleido/build.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/plotly_kaleido/build.rs b/plotly_kaleido/build.rs index 5a4342c5..cf47e82d 100644 --- a/plotly_kaleido/build.rs +++ b/plotly_kaleido/build.rs @@ -10,10 +10,14 @@ use std::process::Command; use directories::ProjectDirs; -#[cfg(target_os = "linux")] +#[cfg(all(target_arch = "x86_64", target_os = "linux"))] const KALEIDO_URL: &str = "https://github.com/plotly/Kaleido/releases/download/v0.2.1/kaleido_linux_x64.zip"; +#[cfg(all(target_arch = "aarch64", target_os = "linux"))] +const KALEIDO_URL: &str = + "https://github.com/plotly/Kaleido/releases/download/v0.2.1/kaleido_linux_arm64.zip"; + #[cfg(target_os = "windows")] const KALEIDO_URL: &str = "https://github.com/plotly/Kaleido/releases/download/v0.2.1/kaleido_win_x64.zip"; From 9ff00e60dbe00ea682627e61e5f1f95490f4f264 Mon Sep 17 00:00:00 2001 From: Andrei Gherghescu <8067229+andrei-ng@users.noreply.github.com> Date: Thu, 25 Apr 2024 08:14:59 +0200 Subject: [PATCH 05/39] fix CI workflow branch name to main Signed-off-by: Andrei Gherghescu <8067229+andrei-ng@users.noreply.github.com> --- .github/workflows/ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index a3c24480..45cb0cdc 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -3,9 +3,9 @@ name: CI on: workflow_dispatch: pull_request: - branches: [ master ] + branches: [ main ] push: - branches: [ master ] + branches: [ main ] # Cancel any in-flight jobs for the same PR/branch so there's only one active # at a time From 3008e648b49ced6ae0581ac0fb32004b7ac12cf3 Mon Sep 17 00:00:00 2001 From: Andrei Gherghescu <8067229+andrei-ng@users.noreply.github.com> Date: Thu, 25 Apr 2024 10:36:14 +0200 Subject: [PATCH 06/39] make clippy happy Signed-off-by: Andrei Gherghescu <8067229+andrei-ng@users.noreply.github.com> --- examples/statistical_charts/src/main.rs | 2 +- plotly_kaleido/src/lib.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/statistical_charts/src/main.rs b/examples/statistical_charts/src/main.rs index 5d2a7190..b8c83d34 100644 --- a/examples/statistical_charts/src/main.rs +++ b/examples/statistical_charts/src/main.rs @@ -345,7 +345,7 @@ fn fully_styled_box_plot() { v }; - let x_data = vec![ + let x_data = [ "Carmelo
Anthony", "Dwyane
Wade", "Deron
Williams", diff --git a/plotly_kaleido/src/lib.rs b/plotly_kaleido/src/lib.rs index ce0d67cc..41f6ff7e 100644 --- a/plotly_kaleido/src/lib.rs +++ b/plotly_kaleido/src/lib.rs @@ -163,7 +163,7 @@ impl Kaleido { } let output_lines = BufReader::new(process.stdout.unwrap()).lines(); - for line in output_lines.flatten() { + for line in output_lines.map_while(Result::ok) { let res = KaleidoResult::from(line.as_str()); if let Some(image_data) = res.result { let data: Vec = match format { From 203b152adc6aca394a43fea1f5036f70dbdc902a Mon Sep 17 00:00:00 2001 From: Andrei Gherghescu <8067229+andrei-ng@users.noreply.github.com> Date: Thu, 25 Apr 2024 10:44:09 +0200 Subject: [PATCH 07/39] ci: disable a few kaleido tests as Windows runner fails - for some reason generating pdf and webp Kaleido files on Windows CI no longer works - disabling for now until finding a proper fix Signed-off-by: Andrei Gherghescu <8067229+andrei-ng@users.noreply.github.com> --- .github/workflows/ci.yml | 10 ++++++---- plotly/src/plot.rs | 8 +++++++- plotly_kaleido/src/lib.rs | 6 ++++++ 3 files changed, 19 insertions(+), 5 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 45cb0cdc..cc5c3c65 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -27,7 +27,7 @@ jobs: components: rustfmt - run: cargo fmt --all -- --check - run: cd ${{ github.workspace }}/examples && cargo fmt --all -- --check - + clippy: name: Clippy runs-on: ubuntu-latest @@ -57,7 +57,9 @@ jobs: - uses: actions/checkout@v3 - uses: dtolnay/rust-toolchain@stable - run: cargo test --features plotly_ndarray,plotly_image,kaleido - + - if: ${{ matrix.os == 'windows-latest' }} + run: gci -recurse -filter "*example*" + code-coverage: name: Code Coverage runs-on: ubuntu-latest @@ -70,7 +72,7 @@ jobs: # we are skipping anything to do with wasm here - run: cargo llvm-cov --workspace --features plotly_ndarray,plotly_image,kaleido --lcov --output-path lcov.info - uses: codecov/codecov-action@v3 - + build_examples: name: Build Examples strategy: @@ -94,7 +96,7 @@ jobs: - uses: actions/checkout@v3 - uses: dtolnay/rust-toolchain@stable - run: cd ${{ github.workspace }}/examples/${{ matrix.example }} && cargo build - + build_wasm_examples: name: Build Wasm Examples strategy: diff --git a/plotly/src/plot.rs b/plotly/src/plot.rs index ac80af65..6b5ab6b8 100644 --- a/plotly/src/plot.rs +++ b/plotly/src/plot.rs @@ -162,7 +162,7 @@ impl Traces { /// /// let layout = Layout::new().title("Line and Scatter Plot".into()); /// plot.set_layout(layout); -/// +/// /// # if false { // We don't actually want to try and display the plot in a browser when running a doctest. /// plot.show(); /// # } @@ -650,6 +650,7 @@ mod tests { assert!(!dst.exists()); } + #[cfg(not(target_os = "windows"))] #[test] #[cfg(feature = "kaleido")] fn test_save_to_png() { @@ -661,6 +662,7 @@ mod tests { assert!(!dst.exists()); } + #[cfg(not(target_os = "windows"))] #[test] #[cfg(feature = "kaleido")] fn test_save_to_jpeg() { @@ -672,6 +674,7 @@ mod tests { assert!(!dst.exists()); } + #[cfg(not(target_os = "windows"))] #[test] #[cfg(feature = "kaleido")] fn test_save_to_svg() { @@ -683,6 +686,7 @@ mod tests { assert!(!dst.exists()); } + #[cfg(not(target_os = "windows"))] #[test] #[ignore] // This seems to fail unpredictably on MacOs. #[cfg(feature = "kaleido")] @@ -695,6 +699,7 @@ mod tests { assert!(!dst.exists()); } + #[cfg(not(target_os = "windows"))] #[test] #[cfg(feature = "kaleido")] fn test_save_to_pdf() { @@ -706,6 +711,7 @@ mod tests { assert!(!dst.exists()); } + #[cfg(not(target_os = "windows"))] #[test] #[cfg(feature = "kaleido")] fn test_save_to_webp() { diff --git a/plotly_kaleido/src/lib.rs b/plotly_kaleido/src/lib.rs index 41f6ff7e..73d5d9b8 100644 --- a/plotly_kaleido/src/lib.rs +++ b/plotly_kaleido/src/lib.rs @@ -237,6 +237,7 @@ mod tests { assert_eq!(to_value(kaleido_data).unwrap(), expected); } + #[cfg(not(target_os = "windows"))] #[test] fn test_save_png() { let test_plot = create_test_plot(); @@ -247,6 +248,7 @@ mod tests { assert!(std::fs::remove_file(dst.as_path()).is_ok()); } + #[cfg(not(target_os = "windows"))] #[test] fn test_save_jpeg() { let test_plot = create_test_plot(); @@ -257,6 +259,7 @@ mod tests { assert!(std::fs::remove_file(dst.as_path()).is_ok()); } + #[cfg(not(target_os = "windows"))] #[test] fn test_save_webp() { let test_plot = create_test_plot(); @@ -267,6 +270,7 @@ mod tests { assert!(std::fs::remove_file(dst.as_path()).is_ok()); } + #[cfg(not(target_os = "windows"))] #[test] fn test_save_svg() { let test_plot = create_test_plot(); @@ -277,6 +281,7 @@ mod tests { assert!(std::fs::remove_file(dst.as_path()).is_ok()); } + #[cfg(not(target_os = "windows"))] #[test] fn test_save_pdf() { let test_plot = create_test_plot(); @@ -287,6 +292,7 @@ mod tests { assert!(std::fs::remove_file(dst.as_path()).is_ok()); } + #[cfg(not(target_os = "windows"))] #[test] #[ignore] fn test_save_eps() { From ec082c6014a5911a800c6388352269ee79939262 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 30 Apr 2024 21:52:18 +0200 Subject: [PATCH 08/39] Update directories requirement from 4.0.1 to 5.0.1 (#185) * Update directories requirement from 4.0.1 to 5.0.1 --- updated-dependencies: - dependency-name: directories dependency-type: direct:production ... Signed-off-by: dependabot[bot] Signed-off-by: Andrei Gherghescu <8067229+andrei-ng@users.noreply.github.com> * allow multiple versions of directories crate - as suggested by @sjackman Signed-off-by: Andrei Gherghescu <8067229+andrei-ng@users.noreply.github.com> --------- Signed-off-by: dependabot[bot] Signed-off-by: Andrei Gherghescu <8067229+andrei-ng@users.noreply.github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Andrei Gherghescu <8067229+andrei-ng@users.noreply.github.com> --- plotly_kaleido/Cargo.toml | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/plotly_kaleido/Cargo.toml b/plotly_kaleido/Cargo.toml index c05b3aa5..4e67127f 100644 --- a/plotly_kaleido/Cargo.toml +++ b/plotly_kaleido/Cargo.toml @@ -19,12 +19,11 @@ serde = { version = "1.0.132", features = ["derive"] } serde_json = "1.0.73" base64 = "0.13.0" dunce = "1.0.2" -directories = "4.0.1" +directories = ">=4, <6" [dev-dependencies] zip = "0.5.13" [build-dependencies] zip = "0.5.13" -directories = "4.0.1" - +directories = ">=4, <6" From 2dc0cb5a6340f899ad95cba93298bc4d7a304e29 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 30 Apr 2024 22:07:26 +0200 Subject: [PATCH 09/39] Update itertools requirement from 0.10.3 to 0.12.1 (#186) * Update itertools requirement from 0.10.3 to 0.12.1 Updates the requirements on [itertools](https://github.com/rust-itertools/itertools) to permit the latest version. - [Changelog](https://github.com/rust-itertools/itertools/blob/master/CHANGELOG.md) - [Commits](https://github.com/rust-itertools/itertools/compare/v0.10.3...v0.12.1) --- updated-dependencies: - dependency-name: itertools dependency-type: direct:production ... Signed-off-by: dependabot[bot] Signed-off-by: Andrei Gherghescu <8067229+andrei-ng@users.noreply.github.com> * permit itertools versions 0.10, 0.11, or 0.12. Co-authored-by: Shaun Jackman Signed-off-by: Andrei Gherghescu <8067229+andrei-ng@users.noreply.github.com> --------- Signed-off-by: dependabot[bot] Signed-off-by: Andrei Gherghescu <8067229+andrei-ng@users.noreply.github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Andrei <8067229+andrei-ng@users.noreply.github.com> Co-authored-by: Shaun Jackman --- plotly/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plotly/Cargo.toml b/plotly/Cargo.toml index bd6ba120..aca9ee72 100644 --- a/plotly/Cargo.toml +++ b/plotly/Cargo.toml @@ -41,7 +41,7 @@ wasm-bindgen-futures = { version = "0.4", optional = true } [dev-dependencies] csv = "1.1.6" image = "0.24.4" -itertools = "0.10.3" +itertools = ">=0.10, <0.13" itertools-num = "0.1.3" ndarray = "0.15.4" plotly_kaleido = { version = "0.8.4", path = "../plotly_kaleido" } From d22e25f08ab83aac0cc39e2b787d0133a833b44e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 30 Apr 2024 22:28:19 +0200 Subject: [PATCH 10/39] Update zip requirement from 0.5.13 to 1.1.3 (#196) * Update zip requirement from 0.5.13 to 1.1.3 --- updated-dependencies: - dependency-name: zip dependency-type: direct:production ... Signed-off-by: dependabot[bot] Signed-off-by: Andrei Gherghescu <8067229+andrei-ng@users.noreply.github.com> * remove zip from dev-dependencies Signed-off-by: Andrei Gherghescu <8067229+andrei-ng@users.noreply.github.com> * make zip version requirement independent of patch Signed-off-by: Andrei Gherghescu <8067229+andrei-ng@users.noreply.github.com> --------- Signed-off-by: dependabot[bot] Signed-off-by: Andrei Gherghescu <8067229+andrei-ng@users.noreply.github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Andrei Gherghescu <8067229+andrei-ng@users.noreply.github.com> --- plotly_kaleido/Cargo.toml | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/plotly_kaleido/Cargo.toml b/plotly_kaleido/Cargo.toml index 4e67127f..cba5ca6f 100644 --- a/plotly_kaleido/Cargo.toml +++ b/plotly_kaleido/Cargo.toml @@ -21,9 +21,6 @@ base64 = "0.13.0" dunce = "1.0.2" directories = ">=4, <6" -[dev-dependencies] -zip = "0.5.13" - [build-dependencies] -zip = "0.5.13" +zip = "1.1" directories = ">=4, <6" From ea061f26e6e4ed14044fc1b91ac7ce1803083e6a Mon Sep 17 00:00:00 2001 From: Shaun Jackman Date: Tue, 30 Apr 2024 13:53:19 -0700 Subject: [PATCH 11/39] build(deps): Depend on serde_with version 2 or 3 (#169) Signed-off-by: Andrei Gherghescu <8067229+andrei-ng@users.noreply.github.com> Co-authored-by: Andrei Gherghescu <8067229+andrei-ng@users.noreply.github.com> --- plotly/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plotly/Cargo.toml b/plotly/Cargo.toml index aca9ee72..c9cf8049 100644 --- a/plotly/Cargo.toml +++ b/plotly/Cargo.toml @@ -33,7 +33,7 @@ once_cell = "1" serde = { version = "1.0.132", features = ["derive"] } serde_json = "1.0.73" serde_repr = "0.1" -serde_with = "2" +serde_with = ">=2, <4" rand = "0.8" wasm-bindgen = { version = "0.2", optional = true } wasm-bindgen-futures = { version = "0.4", optional = true } From 62719981b7ba0da0b7df2923ced4e130a51b11df Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 30 Apr 2024 23:00:29 +0200 Subject: [PATCH 12/39] Update erased-serde requirement from 0.3 to 0.4 (#195) Updates the requirements on [erased-serde](https://github.com/dtolnay/erased-serde) to permit the latest version. - [Release notes](https://github.com/dtolnay/erased-serde/releases) - [Commits](https://github.com/dtolnay/erased-serde/compare/0.3.0...0.4.4) --- updated-dependencies: - dependency-name: erased-serde dependency-type: direct:production ... Signed-off-by: dependabot[bot] Signed-off-by: Andrei Gherghescu <8067229+andrei-ng@users.noreply.github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- plotly/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plotly/Cargo.toml b/plotly/Cargo.toml index c9cf8049..fdef4822 100644 --- a/plotly/Cargo.toml +++ b/plotly/Cargo.toml @@ -22,7 +22,7 @@ wasm = ["getrandom", "js-sys", "wasm-bindgen", "wasm-bindgen-futures"] [dependencies] askama = { version = ">=0.11.0, <0.13.0", features = ["serde-json"] } dyn-clone = "1" -erased-serde = "0.3" +erased-serde = "0.4" getrandom = { version = "0.2", features = ["js"], optional = true } image = { version = "0.24.2", optional = true } js-sys = { version = "0.3", optional = true } From e01b234430b4c2ac06e90603a6a4e44cfb46265f Mon Sep 17 00:00:00 2001 From: Shaun Jackman Date: Tue, 30 Apr 2024 14:12:13 -0700 Subject: [PATCH 13/39] build(deps): Bump syn to 2 and darling to 0.20 (#167) - Bump syn from 1 to 2 - Bump darling from 0.14 to 0.20 Signed-off-by: Andrei Gherghescu <8067229+andrei-ng@users.noreply.github.com> Co-authored-by: Andrei Gherghescu <8067229+andrei-ng@users.noreply.github.com> --- plotly_derive/Cargo.toml | 8 ++++---- plotly_derive/src/field_setter.rs | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/plotly_derive/Cargo.toml b/plotly_derive/Cargo.toml index 34be9693..809347b3 100644 --- a/plotly_derive/Cargo.toml +++ b/plotly_derive/Cargo.toml @@ -11,10 +11,10 @@ edition = "2018" keywords = ["plot", "chart", "plotly"] [dependencies] -quote = "1.0" -syn = "1.0" -proc-macro2 = "1.0" -darling = "0.14.1" +quote = "1" +syn = "2" +proc-macro2 = "1" +darling = "0.20" [lib] proc-macro = true diff --git a/plotly_derive/src/field_setter.rs b/plotly_derive/src/field_setter.rs index a1642989..f330be21 100644 --- a/plotly_derive/src/field_setter.rs +++ b/plotly_derive/src/field_setter.rs @@ -492,7 +492,7 @@ impl FieldReceiver { self.attrs .iter() .filter(|attr| { - attr.path + attr.path() .segments .first() .map_or(false, |p| p.ident == name) From 14dc885a196cd0b5c6bf163199f3ee655fef4cfd Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 30 Apr 2024 23:30:42 +0200 Subject: [PATCH 14/39] Bump image requirement from 0.24.2 to whole range 0.24 (#189) Signed-off-by: Andrei Gherghescu <8067229+andrei-ng@users.noreply.github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Shaun Jackman --- plotly/Cargo.toml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plotly/Cargo.toml b/plotly/Cargo.toml index fdef4822..5252fe5b 100644 --- a/plotly/Cargo.toml +++ b/plotly/Cargo.toml @@ -24,7 +24,7 @@ askama = { version = ">=0.11.0, <0.13.0", features = ["serde-json"] } dyn-clone = "1" erased-serde = "0.4" getrandom = { version = "0.2", features = ["js"], optional = true } -image = { version = "0.24.2", optional = true } +image = { version = "0.24", optional = true } js-sys = { version = "0.3", optional = true } plotly_derive = { version = "0.8.4", path = "../plotly_derive" } plotly_kaleido = { version = "0.8.4", path = "../plotly_kaleido", optional = true } @@ -40,7 +40,7 @@ wasm-bindgen-futures = { version = "0.4", optional = true } [dev-dependencies] csv = "1.1.6" -image = "0.24.4" +image = "0.24" itertools = ">=0.10, <0.13" itertools-num = "0.1.3" ndarray = "0.15.4" From 1ce30f0c54e7c0b5fd59aaf1cd95d6c33f0a130c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 1 May 2024 11:18:45 +0200 Subject: [PATCH 15/39] Update base64 requirement from 0.13.0 to 0.22.1 (#198) * Update base64 requirement from 0.13.0 to 0.22.1 Updates the requirements on [base64](https://github.com/marshallpierce/rust-base64) to permit the latest version. - [Changelog](https://github.com/marshallpierce/rust-base64/blob/master/RELEASE-NOTES.md) - [Commits](https://github.com/marshallpierce/rust-base64/compare/v0.13.0...v0.22.1) --- updated-dependencies: - dependency-name: base64 dependency-type: direct:production ... Signed-off-by: dependabot[bot] Signed-off-by: Andrei Gherghescu <8067229+andrei-ng@users.noreply.github.com> * update implementation to work with new base64 crate version Signed-off-by: Andrei Gherghescu <8067229+andrei-ng@users.noreply.github.com> * don't pin down patch version for base64 crate Signed-off-by: Andrei Gherghescu <8067229+andrei-ng@users.noreply.github.com> * remove conditional compilation for already ignored test Signed-off-by: Andrei Gherghescu <8067229+andrei-ng@users.noreply.github.com> --------- Signed-off-by: dependabot[bot] Signed-off-by: Andrei Gherghescu <8067229+andrei-ng@users.noreply.github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Andrei Gherghescu <8067229+andrei-ng@users.noreply.github.com> --- plotly/src/plot.rs | 1 - plotly_kaleido/Cargo.toml | 2 +- plotly_kaleido/src/lib.rs | 4 ++-- 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/plotly/src/plot.rs b/plotly/src/plot.rs index 6b5ab6b8..a7d175ea 100644 --- a/plotly/src/plot.rs +++ b/plotly/src/plot.rs @@ -686,7 +686,6 @@ mod tests { assert!(!dst.exists()); } - #[cfg(not(target_os = "windows"))] #[test] #[ignore] // This seems to fail unpredictably on MacOs. #[cfg(feature = "kaleido")] diff --git a/plotly_kaleido/Cargo.toml b/plotly_kaleido/Cargo.toml index cba5ca6f..8bed49b6 100644 --- a/plotly_kaleido/Cargo.toml +++ b/plotly_kaleido/Cargo.toml @@ -17,7 +17,7 @@ exclude = ["target/*", "kaleido/*", "examples/*"] [dependencies] serde = { version = "1.0.132", features = ["derive"] } serde_json = "1.0.73" -base64 = "0.13.0" +base64 = "0.22" dunce = "1.0.2" directories = ">=4, <6" diff --git a/plotly_kaleido/src/lib.rs b/plotly_kaleido/src/lib.rs index 73d5d9b8..c3292c40 100644 --- a/plotly_kaleido/src/lib.rs +++ b/plotly_kaleido/src/lib.rs @@ -16,6 +16,7 @@ use std::io::BufReader; use std::path::{Path, PathBuf}; use std::process::{Command, Stdio}; +use base64::{engine::general_purpose, Engine as _}; use directories::ProjectDirs; use serde::{Deserialize, Serialize}; use serde_json::Value; @@ -168,7 +169,7 @@ impl Kaleido { if let Some(image_data) = res.result { let data: Vec = match format { "svg" | "eps" => image_data.as_bytes().to_vec(), - _ => base64::decode(image_data).unwrap(), + _ => general_purpose::STANDARD.decode(image_data).unwrap(), }; let mut file = File::create(dst.as_path())?; file.write_all(&data)?; @@ -292,7 +293,6 @@ mod tests { assert!(std::fs::remove_file(dst.as_path()).is_ok()); } - #[cfg(not(target_os = "windows"))] #[test] #[ignore] fn test_save_eps() { From 852ed2e7b68cef66da371b78dd915a1d19480711 Mon Sep 17 00:00:00 2001 From: gwbres Date: Fri, 10 May 2024 12:15:11 +0200 Subject: [PATCH 16/39] Introducing DensityMapbox (#163) * Introducing DensityMapbox Signed-off-by: Guillaume W. Bres * reference PR in CHANGELOG Signed-off-by: Andrei Gherghescu <8067229+andrei-ng@users.noreply.github.com> * apply cargo fmt Signed-off-by: Andrei Gherghescu <8067229+andrei-ng@users.noreply.github.com> * fix clippy warnings Signed-off-by: Andrei Gherghescu <8067229+andrei-ng@users.noreply.github.com> * fix clippy warning on unsued type - apply target configuration to StaticPlotTemplate Signed-off-by: Andrei Gherghescu <8067229+andrei-ng@users.noreply.github.com> --------- Signed-off-by: Guillaume W. Bres Signed-off-by: Andrei Gherghescu <8067229+andrei-ng@users.noreply.github.com> Co-authored-by: Guillaume W. Bres Co-authored-by: Andrei Gherghescu <8067229+andrei-ng@users.noreply.github.com> --- CHANGELOG.md | 7 +- examples/maps/src/main.rs | 23 ++++- plotly/src/common/mod.rs | 1 + plotly/src/layout/update_menu.rs | 2 +- plotly/src/lib.rs | 4 +- plotly/src/plot.rs | 1 + plotly/src/traces/density_mapbox.rs | 146 ++++++++++++++++++++++++++++ plotly/src/traces/mod.rs | 2 + 8 files changed, 179 insertions(+), 7 deletions(-) create mode 100644 plotly/src/traces/density_mapbox.rs diff --git a/CHANGELOG.md b/CHANGELOG.md index e0a39420..38f0d83b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,9 +3,10 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). -## [0.8.5] - 2023-xx-xx +## [0.8.5] - 2024-xx-xx ### Added -- [[#153](https://github.com/igiagkiozis/plotly/pull/153)] Added `LayoutScene` +- [[#163](https://github.com/plotly/plotly.rs/pull/163)] Added `DensityMapbox`. +- [[#153](https://github.com/igiagkiozis/plotly/pull/153)] Added `LayoutScene`. ## [0.8.4] - 2023-07-09 ### Added @@ -46,7 +47,7 @@ Version 0.8.0 represents a significant release which refactors a lot of the code - Support for `Sankey` diagrams - Support for `Plot3D` - 3D plots for scatter, line and surface data ### Changed -- Improve implementation of `private::NumOrString` to support more primitive types ([Issue +- Improve implementation of `private::NumOrString` to support more primitive types ([Issue #47](https://github.com/igiagkiozis/plotly/issues/47)) - Remove `private::TruthyEnum` in favour of a more robust way of serializing to `String` or `bool` - Refactor `Color` module diff --git a/examples/maps/src/main.rs b/examples/maps/src/main.rs index 10312ced..1258e6ae 100644 --- a/examples/maps/src/main.rs +++ b/examples/maps/src/main.rs @@ -3,7 +3,7 @@ use plotly::{ common::Marker, layout::{Center, DragMode, Mapbox, MapboxStyle, Margin}, - Layout, Plot, ScatterMapbox, + DensityMapbox, Layout, Plot, ScatterMapbox, }; fn scatter_mapbox() { @@ -27,8 +27,29 @@ fn scatter_mapbox() { plot.show(); } +fn density_mapbox() { + let trace = DensityMapbox::new(vec![45.5017], vec![-73.5673], vec![0.75]).zauto(true); + + let layout = Layout::new() + .drag_mode(DragMode::Zoom) + .margin(Margin::new().top(0).left(0).bottom(0).right(0)) + .mapbox( + Mapbox::new() + .style(MapboxStyle::OpenStreetMap) + .center(Center::new(45.5017, -73.5673)) + .zoom(5), + ); + + let mut plot = Plot::new(); + plot.add_trace(trace); + plot.set_layout(layout); + + plot.show(); +} + fn main() { // Uncomment any of these lines to display the example. // scatter_mapbox(); + // density_mapbox(); } diff --git a/plotly/src/common/mod.rs b/plotly/src/common/mod.rs index 44fece3a..d6cc3082 100644 --- a/plotly/src/common/mod.rs +++ b/plotly/src/common/mod.rs @@ -201,6 +201,7 @@ pub enum PlotType { Ohlc, Sankey, Surface, + DensityMapbox, } #[derive(Serialize, Clone, Debug)] diff --git a/plotly/src/layout/update_menu.rs b/plotly/src/layout/update_menu.rs index 4823385e..eea463f0 100644 --- a/plotly/src/layout/update_menu.rs +++ b/plotly/src/layout/update_menu.rs @@ -100,7 +100,7 @@ impl ButtonBuilder { pub fn new() -> Self { Default::default() } - pub fn push_restyle(mut self, restyle: impl Restyle + Serialize) -> Self { + pub fn push_restyle(mut self, restyle: impl Restyle) -> Self { let restyle = serde_json::to_value(&restyle).unwrap(); for (k, v) in restyle.as_object().unwrap() { self.restyles.insert(k.clone(), v.clone()); diff --git a/plotly/src/lib.rs b/plotly/src/lib.rs index 2d0a1e15..729e0a9d 100644 --- a/plotly/src/lib.rs +++ b/plotly/src/lib.rs @@ -33,8 +33,8 @@ pub use plot::{ImageFormat, Plot, Trace}; pub use traces::{box_plot, contour, histogram, image, mesh3d, sankey, scatter_mapbox, surface}; // Bring the different trace types into the top-level scope pub use traces::{ - Bar, BoxPlot, Candlestick, Contour, HeatMap, Histogram, Image, Mesh3D, Ohlc, Sankey, Scatter, - Scatter3D, ScatterMapbox, ScatterPolar, Surface, + Bar, BoxPlot, Candlestick, Contour, DensityMapbox, HeatMap, Histogram, Image, Mesh3D, Ohlc, + Sankey, Scatter, Scatter3D, ScatterMapbox, ScatterPolar, Surface, }; pub trait Restyle: serde::Serialize {} diff --git a/plotly/src/plot.rs b/plotly/src/plot.rs index a7d175ea..a2dab216 100644 --- a/plotly/src/plot.rs +++ b/plotly/src/plot.rs @@ -20,6 +20,7 @@ struct PlotTemplate<'a> { #[derive(Template)] #[template(path = "static_plot.html", escape = "none")] +#[cfg(not(target_family = "wasm"))] struct StaticPlotTemplate<'a> { plot: &'a Plot, format: ImageFormat, diff --git a/plotly/src/traces/density_mapbox.rs b/plotly/src/traces/density_mapbox.rs new file mode 100644 index 00000000..dd66ce67 --- /dev/null +++ b/plotly/src/traces/density_mapbox.rs @@ -0,0 +1,146 @@ +//! Density mapbox scatter plot + +use plotly_derive::FieldSetter; +use serde::Serialize; + +use crate::common::{LegendGroupTitle, Line, PlotType, Visible}; +use crate::Trace; + +#[serde_with::skip_serializing_none] +#[derive(Serialize, Clone, Debug, FieldSetter)] +#[field_setter(box_self, kind = "trace")] +pub struct DensityMapbox +where + Lat: Serialize + Clone, + Lon: Serialize + Clone, + Z: Serialize + Clone, +{ + #[field_setter(default = "PlotType::DensityMapbox")] + r#type: PlotType, + /// Sets the trace name. The trace name appear as the legend item and on + /// hover. + name: Option, + /// Determines whether or not this trace is visible. If + /// `Visible::LegendOnly`, the trace is not drawn, but can appear as a + /// legend item (provided that the legend itself is visible). + visible: Option, + + /// Determines whether or not an item corresponding to this trace is shown + /// in the legend. + #[serde(rename = "showlegend")] + show_legend: Option, + + /// Sets the legend rank for this trace. Items and groups with smaller ranks + /// are presented on top/left side while with `"reversed" + /// `legend.trace_order` they are on bottom/right side. The default + /// legendrank is 1000, so that you can use ranks less than 1000 to + /// place certain items before all unranked items, and ranks greater + /// than 1000 to go after all unranked items. + #[serde(rename = "legendrank")] + legend_rank: Option, + /// Sets the legend group for this trace. Traces part of the same legend + /// group show/hide at the same time when toggling legend items. + #[serde(rename = "legendgroup")] + legend_group: Option, + /// Set and style the title to appear for the legend group. + #[serde(rename = "legendgrouptitle")] + legend_group_title: Option, + + /// Line display properties. + line: Option, + + lat: Option>, + lon: Option>, + z: Option>, + + /// Sets the opacity of the trace. + opacity: Option, + + /// Sets a reference between this trace's data coordinates and a mapbox + /// subplot. If "mapbox" (the default value), the data refer to + /// `layout.mapbox`. If "mapbox2", the data refer to `layout.mapbox2`, and + /// so on. + subplot: Option, + + /// Determines whether or not the color domain is computed + /// with respect to the input data (here in `z`) or the bounds set + /// in `zmin` and `zmax`. Defaults to false when `zmin` and `zmax` are + /// set by the user. + zauto: Option, + + /// Sets the upper bound of the color domain. Value should have the + /// same units as in `z` and if set, `zmin` must be set as well. + zmax: Option, + + zmid: Option, + + zmin: Option, + + zoom: Option, + + radius: Option, + //color_continuous_scale: Option>, + //color_continuous_midpoint: Option, +} + +impl DensityMapbox +where + Lat: Serialize + Clone + std::default::Default, // TODO why is "+ Default" necessary? + Lon: Serialize + Clone + std::default::Default, + Z: Serialize + Clone + std::default::Default, +{ + pub fn new(lat: Vec, lon: Vec, z: Vec) -> Box { + Box::new(Self { + lat: Some(lat), + lon: Some(lon), + z: Some(z), + ..Default::default() + }) + } +} + +impl Trace for DensityMapbox +where + Lat: Serialize + Clone, + Lon: Serialize + Clone, + Z: Serialize + Clone, +{ + fn to_json(&self) -> String { + serde_json::to_string(&self).unwrap() + } +} + +#[cfg(test)] +mod tests { + use serde_json::{json, to_value}; + + use super::*; + + #[test] + fn test_serialize_density_mapbox() { + let density_mapbox = DensityMapbox::new(vec![45.5017], vec![-73.5673], vec![1.0]) + .name("name") + .visible(Visible::True) + .show_legend(true) + .legend_rank(1000) + .legend_group("legend group") + .zoom(5) + .radius(20) + .opacity(0.5); + let expected = json!({ + "type": "densitymapbox", + "lat": [45.5017], + "lon": [-73.5673], + "z": [1.0], + "name": "name", + "visible": true, + "showlegend": true, + "legendrank": 1000, + "legendgroup": "legend group", + "opacity": 0.5, + "zoom": 5, + "radius": 20, + }); + assert_eq!(to_value(density_mapbox.clone()).unwrap(), expected); + } +} diff --git a/plotly/src/traces/mod.rs b/plotly/src/traces/mod.rs index 28f6079e..e6ca3179 100644 --- a/plotly/src/traces/mod.rs +++ b/plotly/src/traces/mod.rs @@ -4,6 +4,7 @@ pub mod bar; pub mod box_plot; mod candlestick; pub mod contour; +mod density_mapbox; mod heat_map; pub mod histogram; pub mod image; @@ -20,6 +21,7 @@ pub use bar::Bar; pub use box_plot::BoxPlot; pub use candlestick::Candlestick; pub use contour::Contour; +pub use density_mapbox::DensityMapbox; pub use heat_map::HeatMap; pub use histogram::Histogram; pub use mesh3d::Mesh3D; From ba867e0fc2bd1db521e610dc4fe07f90dbcee59d Mon Sep 17 00:00:00 2001 From: Louis Dureuil Date: Fri, 10 May 2024 12:45:38 +0200 Subject: [PATCH 17/39] Add "with-axum" feature to allow compilation when other dependencies use axum (#181) * Add "with_axum" feature that brings the required dependencies * Update CHANGELOG --------- Signed-off-by: Andrei Gherghescu <8067229+andrei-ng@users.noreply.github.com> Co-authored-by: Andrei Gherghescu <8067229+andrei-ng@users.noreply.github.com> --- CHANGELOG.md | 4 ++-- plotly/Cargo.toml | 2 ++ 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 38f0d83b..bbc3a1de 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,7 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) a ## [0.8.5] - 2024-xx-xx ### Added +- [[#181](https://github.com/igiagkiozis/plotly/pull/181)] Fix compilation error when mixing the crate with `askama/with-axum` by adding `with-axum` feature. - [[#163](https://github.com/plotly/plotly.rs/pull/163)] Added `DensityMapbox`. - [[#153](https://github.com/igiagkiozis/plotly/pull/153)] Added `LayoutScene`. @@ -47,8 +48,7 @@ Version 0.8.0 represents a significant release which refactors a lot of the code - Support for `Sankey` diagrams - Support for `Plot3D` - 3D plots for scatter, line and surface data ### Changed -- Improve implementation of `private::NumOrString` to support more primitive types ([Issue -#47](https://github.com/igiagkiozis/plotly/issues/47)) +- Improve implementation of `private::NumOrString` to support more primitive types ([Issue #47](https://github.com/igiagkiozis/plotly/issues/47)) - Remove `private::TruthyEnum` in favour of a more robust way of serializing to `String` or `bool` - Refactor `Color` module - Refactored HTML templates with cleaner Javascript code diff --git a/plotly/Cargo.toml b/plotly/Cargo.toml index 5252fe5b..11b7880d 100644 --- a/plotly/Cargo.toml +++ b/plotly/Cargo.toml @@ -18,9 +18,11 @@ kaleido = ["plotly_kaleido"] plotly_ndarray = ["ndarray"] plotly_image = ["image"] wasm = ["getrandom", "js-sys", "wasm-bindgen", "wasm-bindgen-futures"] +with-axum = ["askama/with-axum", "askama_axum"] [dependencies] askama = { version = ">=0.11.0, <0.13.0", features = ["serde-json"] } +askama_axum = { version = "0.4.0", optional = true } dyn-clone = "1" erased-serde = "0.4" getrandom = { version = "0.2", features = ["js"], optional = true } From eef27cd9f004e92c003bfd3386e3668c380afc0e Mon Sep 17 00:00:00 2001 From: "Seb. V" Date: Fri, 10 May 2024 12:57:38 +0200 Subject: [PATCH 18/39] Add setter for Mapbox::domain (#180) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Add setter for Mapbox::domain * apply cargo fmt Signed-off-by: Andrei Gherghescu <8067229+andrei-ng@users.noreply.github.com> * update CHANGELOG Signed-off-by: Andrei Gherghescu <8067229+andrei-ng@users.noreply.github.com> --------- Signed-off-by: Andrei Gherghescu <8067229+andrei-ng@users.noreply.github.com> Co-authored-by: Sébastien Vauclair Co-authored-by: Andrei Gherghescu <8067229+andrei-ng@users.noreply.github.com> --- CHANGELOG.md | 1 + plotly/src/layout/mod.rs | 3 +++ 2 files changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index bbc3a1de..cbdca818 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,7 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) a ## [0.8.5] - 2024-xx-xx ### Added - [[#181](https://github.com/igiagkiozis/plotly/pull/181)] Fix compilation error when mixing the crate with `askama/with-axum` by adding `with-axum` feature. +- [[#180](https://github.com/igiagkiozis/plotly/pull/180)] Add setter for `Mapbox::domain`. - [[#163](https://github.com/plotly/plotly.rs/pull/163)] Added `DensityMapbox`. - [[#153](https://github.com/igiagkiozis/plotly/pull/153)] Added `LayoutScene`. diff --git a/plotly/src/layout/mod.rs b/plotly/src/layout/mod.rs index 6026e6ed..55e2dfd8 100644 --- a/plotly/src/layout/mod.rs +++ b/plotly/src/layout/mod.rs @@ -7,6 +7,7 @@ use plotly_derive::FieldSetter; use serde::{Serialize, Serializer}; use update_menu::UpdateMenu; +use crate::common::Domain; use crate::{ color::Color, common::{ @@ -1370,6 +1371,8 @@ pub struct Mapbox { bearing: Option, /// Sets the latitude and longitude of the center of the map. center: Option
, + /// Sets the domain within which the mapbox will be drawn. + domain: Option, /// Sets the pitch angle of the map in degrees, where `0` means /// perpendicular to the surface of the map. pitch: Option, From a00ab93290bd4a8e2406ef885453f9aa71dd206e Mon Sep 17 00:00:00 2001 From: Andrei <8067229+andrei-ng@users.noreply.github.com> Date: Tue, 14 May 2024 22:28:43 +0200 Subject: [PATCH 19/39] fix references to point to new repo url and main branch (#193) - change url links to plotly/plotly.rs and from master to main - fix refs in mdbook and in README - fix shields.io links Signed-off-by: Andrei Gherghescu <8067229+andrei-ng@users.noreply.github.com> Co-authored-by: Andrei N.G --- CHANGELOG.md | 38 +++++++++---------- CONTRIBUTING.md | 6 +-- README.md | 28 +++++++------- docs/book/src/fundamentals.md | 10 ++--- docs/book/src/fundamentals/jupyter_support.md | 16 ++++---- docs/book/src/fundamentals/ndarray_support.md | 10 ++--- docs/book/src/getting_started.md | 28 +++++++------- docs/book/src/plotly_rs.md | 14 +++---- docs/book/src/recipes.md | 10 ++--- docs/book/src/recipes/3dcharts.md | 2 +- docs/book/src/recipes/basic_charts.md | 2 +- docs/book/src/recipes/financial_charts.md | 2 +- docs/book/src/recipes/scientific_charts.md | 2 +- docs/book/src/recipes/statistical_charts.md | 2 +- docs/book/src/recipes/subplots.md | 2 +- plotly/Cargo.toml | 4 +- plotly/src/plot.rs | 2 +- plotly_derive/Cargo.toml | 4 +- plotly_derive/README.md | 2 +- plotly_kaleido/Cargo.toml | 4 +- plotly_kaleido/README.md | 8 ++-- plotly_kaleido/src/lib.rs | 2 +- 22 files changed, 99 insertions(+), 99 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index cbdca818..5b5a0819 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,36 +5,36 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) a ## [0.8.5] - 2024-xx-xx ### Added -- [[#181](https://github.com/igiagkiozis/plotly/pull/181)] Fix compilation error when mixing the crate with `askama/with-axum` by adding `with-axum` feature. -- [[#180](https://github.com/igiagkiozis/plotly/pull/180)] Add setter for `Mapbox::domain`. +- [[#181](https://github.com/plotly/plotly,rs/pull/181)] Fix compilation error when mixing the crate with `askama/with-axum` by adding `with-axum` feature. +- [[#180](https://github.com/plotly/plotly.rs/pull/180)] Add setter for `Mapbox::domain`. - [[#163](https://github.com/plotly/plotly.rs/pull/163)] Added `DensityMapbox`. -- [[#153](https://github.com/igiagkiozis/plotly/pull/153)] Added `LayoutScene`. +- [[#153](https://github.com/plotly/plotly.rs/pull/153)] Added `LayoutScene`. ## [0.8.4] - 2023-07-09 ### Added -- [[#143](https://github.com/igiagkiozis/plotly/pull/143)] Widen version range of `askama`. +- [[#143](https://github.com/plotly/plotly.rs/pull/143)] Widen version range of `askama`. ### Fixed -- [[#129](https://github.com/igiagkiozis/plotly/pull/129)] Fix issue for plots not showing in browser in Windows. Thanks to [@juanespj](https://github.com/juanespj) and [@M-NK-Y](https://github.com/M-NK-Y) for the PRs. -- [[#147](https://github.com/igiagkiozis/plotly/pull/147)] Update documentation for `jupyter notebook` example. +- [[#129](https://github.com/plotly/plotly.rs/pull/129)] Fix issue for plots not showing in browser in Windows. Thanks to [@juanespj](https://github.com/juanespj) and [@M-NK-Y](https://github.com/M-NK-Y) for the PRs. +- [[#147](https://github.com/plotly/plotly.rs/pull/147)] Update documentation for `jupyter notebook` example. ## [0.8.3] - 2022-11-04 ### Fixed -- [[#122](https://github.com/igiagkiozis/plotly/pull/122)] Compilation error for the `wasm` feature. -- [[#123](https://github.com/igiagkiozis/plotly/pull/123)] Compilation error for the `plotly_kaleido` feature. +- [[#122](https://github.com/plotly/plotly.rs/pull/122)] Compilation error for the `wasm` feature. +- [[#123](https://github.com/plotly/plotly.rs/pull/123)] Compilation error for the `plotly_kaleido` feature. ## [0.8.2] - 2022-11-03 ### Added -- [[#110](https://github.com/igiagkiozis/plotly/pull/110)] `LegendGroupTitle` to existing traces. -- [[#88](https://github.com/igiagkiozis/plotly/pull/88)] `Mesh3D`, `Image`, `ScatterMapbox` traces. +- [[#110](https://github.com/plotly/plotly.rs/pull/110)] `LegendGroupTitle` to existing traces. +- [[#88](https://github.com/plotly/plotly.rs/pull/88)] `Mesh3D`, `Image`, `ScatterMapbox` traces. ### Changed -- [[#113](https://github.com/igiagkiozis/plotly/pull/113)] Refactored the structure of the examples to make them more accessible, whilst adding more examples e.g. for `wasm`. -- [[#115](https://github.com/igiagkiozis/plotly/pull/115)] Simplify the function signature of Plot.to_inline_html() so that it just takes `Option<&str>` as an argument. +- [[#113](https://github.com/plotly/plotly.rs/pull/113)] Refactored the structure of the examples to make them more accessible, whilst adding more examples e.g. for `wasm`. +- [[#115](https://github.com/plotly/plotly.rs/pull/115)] Simplify the function signature of Plot.to_inline_html() so that it just takes `Option<&str>` as an argument. ## [0.8.1] - 2022-09-25 ### Added -- Button support (i.e. [updatemenus](https://plotly.com/javascript/reference/layout/updatemenus/)) contibuted by [@sreenathkrishnan](https://github.com/sreenathkrishnan). Details and examples in this well written PR [#99](https://github.com/igiagkiozis/plotly/pull/99). +- Button support (i.e. [updatemenus](https://plotly.com/javascript/reference/layout/updatemenus/)) contibuted by [@sreenathkrishnan](https://github.com/sreenathkrishnan). Details and examples in this well written PR [#99](https://github.com/plotly/plotly.rs/pull/99). - Internally, there is now a `plotly-derive` crate which defines a `FieldSetter` procedural macro. This massively cuts down the amount of code duplication by generating the setter methods based on the struct fields. Again thanks to @sreenathkrishnan for this effort. ## [0.8.0] - 2022-08-26 @@ -49,7 +49,7 @@ Version 0.8.0 represents a significant release which refactors a lot of the code - Support for `Sankey` diagrams - Support for `Plot3D` - 3D plots for scatter, line and surface data ### Changed -- Improve implementation of `private::NumOrString` to support more primitive types ([Issue #47](https://github.com/igiagkiozis/plotly/issues/47)) +- Improve implementation of `private::NumOrString` to support more primitive types ([Issue #47](https://github.com/plotly/plotly.rs/issues/47)) - Remove `private::TruthyEnum` in favour of a more robust way of serializing to `String` or `bool` - Refactor `Color` module - Refactored HTML templates with cleaner Javascript code @@ -59,7 +59,7 @@ Version 0.8.0 represents a significant release which refactors a lot of the code - `Plot::to_html()` now has similar behaviour to `Plot::to_inline_html()` and just returns a `String` ### Fixed - Typos in `CONTRIBUTING.md` -- Serialization of `plotly_kaleido::PlotData` ([Issue #50](https://github.com/igiagkiozis/plotly/issues/50)) +- Serialization of `plotly_kaleido::PlotData` ([Issue #50](https://github.com/plotly/plotly.rs/issues/50)) ### Updated - `ndarray` to `0.15.4`. - `serde` to `1.0.132`. @@ -87,11 +87,11 @@ Version 0.8.0 represents a significant release which refactors a lot of the code ## [0.6.0] - 2020-07-25 ### Added -- Shapes support ([documentation](https://igiagkiozis.github.io/plotly/content/fundamentals/shapes.html)). +- Shapes support ([documentation](https://plotly.github.io/plotly.rs/content/fundamentals/shapes.html)). - Annotations support. - Docstrings to `Scatter`. -- `ndarray` support ([documentation](https://igiagkiozis.github.io/plotly/content/fundamentals/ndarray_support.html)). -- Jupyter lab and notebook support ([documentation](https://igiagkiozis.github.io/plotly/content/fundamentals/jupyter_support.html)). +- `ndarray` support ([documentation](https://plotly.github.io/plotly.rs/content/fundamentals/ndarray_support.html)). +- Jupyter lab and notebook support ([documentation](https://plotly.github.io/plotly.rs/content/fundamentals/jupyter_support.html)). ### Changed - Removed `num` dependence. - Removed `plotly_orca` and the `orca` feature. Use the `kaleido` feature for static image generation. @@ -109,7 +109,7 @@ Version 0.8.0 represents a significant release which refactors a lot of the code ## [0.5.0] - 2020-07-12 ### Added -- [Plotly.rs Book](https://igiagkiozis.github.io/plotly/). +- [Plotly.rs Book](https://plotly.github.io/plotly.rs/). - Using plotly.js from the official CDN is now the default. To use the local version use the `Plot::use_local_plotly` method. - Plot rasterization to `png`, `jpg`, `eps`, `pdf`, `webp` and `svg` using [plotly/Kaleido](https://github.com/plotly/Kaleido), enabled using the `kaleido` feature. - Multi-axis support and examples. diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 50818248..0364fc57 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -12,11 +12,11 @@ When making a feature request, please make it clear what problem you intend to s ## Pull Requests -Before spending time and effort in making changes to the library, it's a good idea to discuss it first on the issue tracker to see whether your change is likely to be accepted. +Before spending time and effort in making changes to the library, it's a good idea to discuss it first on the issue tracker to see whether your change is likely to be accepted. -Fork [plotly](https://igiagkiozis.github.io/plotly/) to your own account and create a new branch for your feature. Remember to update the [changelog](CHANGELOG.md) - use previous entries as a template. +Fork [plotly](https://github.com/plotly/plotly.rs.git) to your own account and create a new branch for your feature. Remember to update the [changelog](CHANGELOG.md) - use previous entries as a template. -When your contribution is ready for review, make a pull request with your changes directly to the `master` branch. One of the maintainers will have a look at what you've done, suggest any necessary changes and, when everyone is happy, merge the pull request. +When your contribution is ready for review, make a pull request with your changes directly to the `main` branch. One of the maintainers will have a look at what you've done, suggest any necessary changes and, when everyone is happy, merge the pull request. ## Code of Conduct diff --git a/README.md b/README.md index 76ea74f9..50518376 100644 --- a/README.md +++ b/README.md @@ -2,8 +2,8 @@

Plotly.rs

Plotly for Rust

- - Build status + + Build status Crates.io @@ -14,18 +14,18 @@ Documentation - + Code coverage

- Getting Started + Getting Started | - Recipes + Recipes | API Docs | - Changelog + Changelog

@@ -44,10 +44,10 @@ A plotting library for Rust powered by [Plotly.js](https://plot.ly/javascript/). -Documentation and numerous interactive examples are available in the [Plotly.rs Book](https://igiagkiozis.github.io/plotly/content/getting_started.html), the [examples/](https://github.com/igiagkiozis/plotly/tree/master/examples) directory and [docs.rs](https://docs.rs/crate/plotly). +Documentation and numerous interactive examples are available in the [Plotly.rs Book](https://plotly.github.io/plotly.rs/content/getting_started.html), the [examples/](https://github.com/plotly/plotly.rs/tree/main/examples) directory and [docs.rs](https://docs.rs/crate/plotly). -For changes since the last version, please consult the [changelog](https://github.com/igiagkiozis/plotly/blob/master/CHANGELOG.md). +For changes since the last version, please consult the [changelog](https://github.com/plotly/plotly.rs/tree/main/CHANGELOG.md). # Basic Usage @@ -163,13 +163,13 @@ pub fn plot_component() -> Html { } }); - + use_effect_with_deps(move |_| { p.run(); || () }, (), ); - + html! {
@@ -177,7 +177,7 @@ pub fn plot_component() -> Html { } ``` -More detailed standalone examples can be found in the [examples/](https://github.com/igiagkiozis/plotly/tree/master/examples) directory. +More detailed standalone examples can be found in the [examples/](https://github.com/plotly/plotly.rs/tree/main/examples) directory. # Crate Feature Flags @@ -201,12 +201,12 @@ Enables compilation for the `wasm32-unknown-unknown` target and provides access # Contributing -* If you've spotted a bug or would like to see a new feature, please submit an issue on the [issue tracker](https://github.com/igiagkiozis/plotly/issues). +* If you've spotted a bug or would like to see a new feature, please submit an issue on the [issue tracker](https://github.com/plotly/plotly.rs/issues). -* Pull requests are welcome, see the [contributing guide](https://github.com/igiagkiozis/plotly/blob/master/CONTRIBUTING.md) for more information. +* Pull requests are welcome, see the [contributing guide](https://github.com/plotly/plotly.rs/tree/main/CONTRIBUTING.md) for more information. # License `Plotly.rs` is distributed under the terms of the MIT license. -See [LICENSE-MIT](https://github.com/igiagkiozis/plotly/blob/master/LICENSE-MIT), and [COPYRIGHT](https://github.com/igiagkiozis/plotly/blob/master/COPYRIGHT) for details. +See [LICENSE-MIT](https://github.com/plotly/plotly.rs/tree/main/LICENSE-MIT), and [COPYRIGHT](https://github.com/plotly/plotly.rs/tree/main/COPYRIGHT) for details. diff --git a/docs/book/src/fundamentals.md b/docs/book/src/fundamentals.md index 6ef36d87..9fea76a1 100644 --- a/docs/book/src/fundamentals.md +++ b/docs/book/src/fundamentals.md @@ -1,9 +1,9 @@
- - build status + + build status - - build status + + Build status Crates.io @@ -18,4 +18,4 @@ # Fundamentals -Functionality that applies to the library as a whole is described in the next sections. \ No newline at end of file +Functionality that applies to the library as a whole is described in the next sections. \ No newline at end of file diff --git a/docs/book/src/fundamentals/jupyter_support.md b/docs/book/src/fundamentals/jupyter_support.md index 2576aa91..b329ef30 100644 --- a/docs/book/src/fundamentals/jupyter_support.md +++ b/docs/book/src/fundamentals/jupyter_support.md @@ -1,12 +1,12 @@ # Jupyter Support -As of version `0.7.0`, [Plotly.rs](https://github.com/igiagkiozis/plotly) has native support for the [EvCxR Jupyter Kernel](https://github.com/google/evcxr/tree/master/evcxr_jupyter). +As of version `0.7.0`, [Plotly.rs](https://github.com/plotly/plotly.rs) has native support for the [EvCxR Jupyter Kernel](https://github.com/google/evcxr/tree/master/evcxr_jupyter). Once you've installed the required packages you'll be able to run all the examples shown here as well as all [the recipes](../recipes.md) in Jupyter Lab! ## Installation -It is assumed that an installation of the [Anaconda](https://www.anaconda.com/products/individual) Python distribution is already present in the system. If that is not the case you can follow these [instructions](https://www.anaconda.com/products/individual) to get up and running with `Anaconda`. +It is assumed that an installation of the [Anaconda](https://www.anaconda.com/products/individual) Python distribution is already present in the system. If that is not the case you can follow these [instructions](https://www.anaconda.com/products/individual) to get up and running with `Anaconda`. ```shell script conda install -c plotly plotly=4.9.0 @@ -20,17 +20,17 @@ conda install notebook Although there are alternative methods to enable support for the [EvCxR Jupyter Kernel](https://github.com/google/evcxr/tree/master/evcxr_jupyter), we have elected to keep the requirements consistent with what those of other languages, e.g. Julia, Python and R. This way users know what to expect; and also the folks at [Plotly](https://plotly.com/python/getting-started/#jupyter-notebook-support) have done already most of the heavy lifting to create an extension for Jupyter Lab that works very well. -Run the following to install the Plotly Jupyter Lab extension: +Run the following to install the Plotly Jupyter Lab extension: ```shell script jupyter labextension install jupyterlab-plotly@4.9.0 ``` -Once this step is complete to make sure the installation so far was successful, run the following command: +Once this step is complete to make sure the installation so far was successful, run the following command: ```shell script jupyter lab ``` -Open a `Python 3` kernel copy/paste the following code in a cell and run it: +Open a `Python 3` kernel copy/paste the following code in a cell and run it: ```python import plotly.graph_objects as go fig = go.Figure(data=go.Bar(x=['a', 'b', 'c'], y=[11, 22, 33])) @@ -62,7 +62,7 @@ If you're not familiar with the EvCxR kernel it would be good that you at least ## Usage -Launch Jupyter Lab: +Launch Jupyter Lab: ```shell script jupyter lab ``` @@ -104,6 +104,6 @@ plot.set_layout(layout); plot.lab_display(); format!("EVCXR_BEGIN_CONTENT application/vnd.plotly.v1+json\n{}\nEVCXR_END_CONTENT", plot.to_json()) ``` -For Jupyter Lab there are two ways to display a plot in the `EvCxR` kernel, either have the plot object be in the last line without a semicolon or directly invoke the `Plot::lab_display` method on it; both have the same result. You can also find an example notebook [here](https://github.com/igiagkiozis/plotly/blob/master/examples/jupyter/jupyter_lab.ipynb) that will periodically be updated with examples. +For Jupyter Lab there are two ways to display a plot in the `EvCxR` kernel, either have the plot object be in the last line without a semicolon or directly invoke the `Plot::lab_display` method on it; both have the same result. You can also find an example notebook [here](https://github.com/plotly/plotly.rs/tree/main/examples/jupyter/jupyter_lab.ipynb) that will periodically be updated with examples. -The process for Jupyter Notebook is very much the same with one exception; the `Plot::notebook_display` method must be used to display the plot. You can find an example notebook [here](https://github.com/igiagkiozis/plotly/blob/master/examples/jupyter/jupyter_notebook.ipynb) +The process for Jupyter Notebook is very much the same with one exception; the `Plot::notebook_display` method must be used to display the plot. You can find an example notebook [here](https://github.com/plotly/plotly.rs/tree/main/examples/jupyter/jupyter_notebook.ipynb) diff --git a/docs/book/src/fundamentals/ndarray_support.md b/docs/book/src/fundamentals/ndarray_support.md index b1048dda..c708a635 100644 --- a/docs/book/src/fundamentals/ndarray_support.md +++ b/docs/book/src/fundamentals/ndarray_support.md @@ -1,16 +1,16 @@ -# `ndarray` Support +# `ndarray` Support -To enable [ndarray](https://github.com/rust-ndarray/ndarray) support in [Plotly.rs](https://github.com/igiagkiozis/plotly) add the following feature to your `Cargo.toml` file: +To enable [ndarray](https://github.com/rust-ndarray/ndarray) support in [Plotly.rs](https://github.com/plotly/plotly.rs) add the following feature to your `Cargo.toml` file: ```toml [dependencies] plotly = { version = ">=0.7.0", features = ["plotly_ndarray"] } ``` -This extends the [Plotly.rs](https://github.com/igiagkiozis/plotly) API in two ways: +This extends the [Plotly.rs](https://github.com/plotly/plotly.rs) API in two ways: * `Scatter` traces can now be created using the `Scatter::from_ndarray` constructor, * and also multiple traces can be created with the `Scatter::to_traces` method. -The full source code for the examples below can be found [here](https://github.com/igiagkiozis/plotly/blob/master/plotly/examples/ndarray_support.rs). +The full source code for the examples below can be found [here](https://github.com/plotly/plotly.rs/tree/main/examples/ndarray_support). ## `ndarray` Traces @@ -55,7 +55,7 @@ var layout = {}; ### Multiple Traces -To display a `2D` array (`Array<_, Ix2>`) you can use the `Scatter::to_traces` method. The first argument of the method represents the common axis for the traces (`x` axis) whilst the second argument contains a collection of traces. At this point it should be noted that there is some ambiguity when passing a `2D` array; namely are the traces arranged along the columns or the rows of the matrix? This ambiguity is resolved by the third argument of the `Scatter::to_traces` method. If that argument is set to `ArrayTraces::OverColumns` then the library assumes that every column represents an individual trace, alternatively if this is set to `ArrayTraces::OverRows` the assumption is that every row represents a trace. +To display a `2D` array (`Array<_, Ix2>`) you can use the `Scatter::to_traces` method. The first argument of the method represents the common axis for the traces (`x` axis) whilst the second argument contains a collection of traces. At this point it should be noted that there is some ambiguity when passing a `2D` array; namely are the traces arranged along the columns or the rows of the matrix? This ambiguity is resolved by the third argument of the `Scatter::to_traces` method. If that argument is set to `ArrayTraces::OverColumns` then the library assumes that every column represents an individual trace, alternatively if this is set to `ArrayTraces::OverRows` the assumption is that every row represents a trace. To illustrate this distinction consider the following examples: ```rust diff --git a/docs/book/src/getting_started.md b/docs/book/src/getting_started.md index 47dc5cc5..e0a83086 100644 --- a/docs/book/src/getting_started.md +++ b/docs/book/src/getting_started.md @@ -1,9 +1,9 @@
- - build status + + build status - - build status + + Build status Crates.io @@ -18,26 +18,26 @@ # Getting Started -To start using [plotly.rs](https://github.com/igiagkiozis/plotly) in your project add the following to your `Cargo.toml`: +To start using [plotly.rs](https://github.com/plotly/plotly.rs) in your project add the following to your `Cargo.toml`: ```toml [dependencies] plotly = "0.8.4" ``` -[Plotly.rs](https://github.com/igiagkiozis/plotly) is ultimately a thin wrapper around the `plotly.js` library. The main job of this library is to provide `structs` and `enums` which get serialized to `json` and passed to the `plotly.js` library to actually do the heavy lifting. As such, if you are familiar with `plotly.js` or its derivatives (e.g. the equivalent Python library), then you should find [`plotly.rs`](https://github.com/igiagkiozis/plotly) intuitive to use. +[Plotly.rs](https://github.com/plotly/plotly.rs) is ultimately a thin wrapper around the `plotly.js` library. The main job of this library is to provide `structs` and `enums` which get serialized to `json` and passed to the `plotly.js` library to actually do the heavy lifting. As such, if you are familiar with `plotly.js` or its derivatives (e.g. the equivalent Python library), then you should find [`plotly.rs`](https://github.com/plotly/plotly.rs) intuitive to use. A `Plot` struct contains one or more `Trace` objects which describe the structure of data to be displayed. Optional `Layout` and `Configuration` structs can be used to specify the layout and config of the plot, respectively. The builder pattern is used extensively throughout the library, which means you only need to specify the attributes and details you desire. Any attributes that are not set will fall back to the default value used by `plotly.js`. -All available traces (e.g. `Scatter`, `Bar`, `Histogram`, etc), the `Layout`, `Configuration` and `Plot` have been hoisted in the `plotly` namespace so that they can be imported simply using the following: +All available traces (e.g. `Scatter`, `Bar`, `Histogram`, etc), the `Layout`, `Configuration` and `Plot` have been hoisted in the `plotly` namespace so that they can be imported simply using the following: ```rust use plotly::{Plot, Layout, Scatter}; ``` -The aforementioned components can be combined to produce as simple plot as follows: +The aforementioned components can be combined to produce as simple plot as follows: ```rust use plotly::common::Mode; @@ -65,17 +65,17 @@ fn main() -> std::io::Result<()> { } ``` -which results in the following figure (displayed here as a static png file): +which results in the following figure (displayed here as a static png file): ![line_and_scatter_plot](img/line_and_scatter_plot.png) -The above code will generate an interactive `html` page of the `Plot` and display it in the default browser. The `html` for the plot is stored in the platform specific temporary directory. To save the `html` result, you can do so quite simply: +The above code will generate an interactive `html` page of the `Plot` and display it in the default browser. The `html` for the plot is stored in the platform specific temporary directory. To save the `html` result, you can do so quite simply: ```rust plot.write_html("/home/user/line_and_scatter_plot.html"); ``` -It is often the case that plots are produced to be included in a document and a different format for the plot is desirable (e.g. png, jpeg, etc). Given that the `html` version of the plot is composed of vector graphics, the display when converted to a non-vector format (e.g. png) is not guaranteed to be identical to the one displayed in `html`. This means that some fine tuning may be required to get to the desired output. To support that iterative workflow, `Plot` has a `show_image()` method which will display the rasterised output to the target format, for example: +It is often the case that plots are produced to be included in a document and a different format for the plot is desirable (e.g. png, jpeg, etc). Given that the `html` version of the plot is composed of vector graphics, the display when converted to a non-vector format (e.g. png) is not guaranteed to be identical to the one displayed in `html`. This means that some fine tuning may be required to get to the desired output. To support that iterative workflow, `Plot` has a `show_image()` method which will display the rasterised output to the target format, for example: ```rust plot.show_image(ImageFormat::PNG, 1280, 900); @@ -83,7 +83,7 @@ plot.show_image(ImageFormat::PNG, 1280, 900); will display in the browser the rasterised plot; 1280 pixels wide and 900 pixels tall, in png format. -Once a satisfactory result is achieved, and assuming the [`kaleido`](getting_started#saving-plots) feature is enabled, the plot can be saved using the following: +Once a satisfactory result is achieved, and assuming the [`kaleido`](getting_started#saving-plots) feature is enabled, the plot can be saved using the following: ```rust plot.write_image("/home/user/plot_name.ext", ImageFormat::PNG, 1280, 900, 1.0); @@ -93,7 +93,7 @@ The extension in the file-name path is optional as the appropriate extension (`I ## Saving Plots -To add the ability to save plots in the following formats: png, jpeg, webp, svg, pdf and eps, you can use the `kaleido` feature. This feature depends on [plotly/Kaleido](https://github.com/plotly/Kaleido): a cross-platform open source library for generating static images. All the necessary binaries have been included with `plotly_kaleido` for `Linux`, `Windows` and `MacOS`. Previous versions of [plotly.rs](https://github.com/igiagkiozis/plotly) used the `orca` feature, however, this has been deprecated as it provided the same functionality but required additional installation steps. To enable the `kaleido` feature add the following to your `Cargo.toml`: +To add the ability to save plots in the following formats: png, jpeg, webp, svg, pdf and eps, you can use the `kaleido` feature. This feature depends on [plotly/Kaleido](https://github.com/plotly/Kaleido): a cross-platform open source library for generating static images. All the necessary binaries have been included with `plotly_kaleido` for `Linux`, `Windows` and `MacOS`. Previous versions of [plotly.rs](https://github.com/plotly/plotly.rs) used the `orca` feature, however, this has been deprecated as it provided the same functionality but required additional installation steps. To enable the `kaleido` feature add the following to your `Cargo.toml`: ```toml [dependencies] @@ -102,7 +102,7 @@ plotly = { version = "0.8.4", features = ["kaleido"] } ## WebAssembly Support -As of v0.8.0, [plotly.rs](https://github.com/igiagkiozis/plotly) can now be used in a `Wasm` environment by enabling the `wasm` feature in your `Cargo.toml`: +As of v0.8.0, [plotly.rs](https://github.com/plotly/plotly.rs) can now be used in a `Wasm` environment by enabling the `wasm` feature in your `Cargo.toml`: ```toml [dependencies] diff --git a/docs/book/src/plotly_rs.md b/docs/book/src/plotly_rs.md index 19af18d6..24bdf51c 100644 --- a/docs/book/src/plotly_rs.md +++ b/docs/book/src/plotly_rs.md @@ -1,9 +1,9 @@
- - build status + + build status - - build status + + Build status Crates.io @@ -20,17 +20,17 @@ Plotly.rs is a plotting library powered by [Plotly.js](https://plot.ly/javascript/). The aim is to bring over to Rust all the functionality that `Python` users have come to rely on with the added benefit of type safety and speed. -Plotly.rs is free and open source. You can find the source on [GitHub](https://github.com/igiagkiozis/plotly). Issues and feature requests can be posted on the [issue tracker](https://github.com/igiagkiozis/plotly/issues). +Plotly.rs is free and open source. You can find the source on [GitHub](https://github.com/plotly/plotly.rs). Issues and feature requests can be posted on the [issue tracker](https://github.com/plotly/plotly.rs/issues). ## API Docs This book is intended to be a recipe index, which closely follows the [plotly.js examples](https://plotly.com/javascript/), and is complemented by the [API documentation](https://docs.rs/plotly). ## Contributing -Contributions are always welcomed, no matter how large or small. Refer to the [contributing guidelines](https://github.com/igiagkiozis/plotly/blob/master/CONTRIBUTING.md) for further pointers, and, if in doubt, [open an issue](https://github.com/igiagkiozis/plotly/issues). +Contributions are always welcomed, no matter how large or small. Refer to the [contributing guidelines](https://github.com/plotly/plotly.rs/tree/main/CONTRIBUTING.md) for further pointers, and, if in doubt, [open an issue](https://github.com/plotly/plotly.rs/issues). ## License Plotly.rs is distributed under the terms of the MIT license. -See [LICENSE-MIT](https://github.com/igiagkiozis/plotly/blob/master/LICENSE-MIT), and [COPYRIGHT](https://github.com/igiagkiozis/plotly/blob/master/COPYRIGHT) for details. \ No newline at end of file +See [LICENSE-MIT](https://github.com/plotly/plotly.rs/tree/main/LICENSE-MIT), and [COPYRIGHT](https://github.com/plotly/plotly.rs/tree/main/COPYRIGHT) for details. \ No newline at end of file diff --git a/docs/book/src/recipes.md b/docs/book/src/recipes.md index 870a45a2..5c27ecf2 100644 --- a/docs/book/src/recipes.md +++ b/docs/book/src/recipes.md @@ -1,9 +1,9 @@
- - build status + + build status - - build status + + Build status Crates.io @@ -18,4 +18,4 @@ # Recipes -Most of the recipes presented here have been adapted from the official documentation for [plotly.js](https://plotly.com/javascript/) and [plotly.py](https://plotly.com/python/). Contributions of interesting plots that showcase the capabilities of the library are most welcome. For more information on the process please see [the contributing guidelines](https://github.com/igiagkiozis/plotly/blob/master/CONTRIBUTING.md). +Most of the recipes presented here have been adapted from the official documentation for [plotly.js](https://plotly.com/javascript/) and [plotly.py](https://plotly.com/python/). Contributions of interesting plots that showcase the capabilities of the library are most welcome. For more information on the process please see [the contributing guidelines](https://github.com/plotly/plotly.rs/tree/main/CONTRIBUTING.md). diff --git a/docs/book/src/recipes/3dcharts.md b/docs/book/src/recipes/3dcharts.md index 35731c94..852337bb 100644 --- a/docs/book/src/recipes/3dcharts.md +++ b/docs/book/src/recipes/3dcharts.md @@ -1,6 +1,6 @@ # 3D Charts -The complete source code for the following examples can also be found [here](https://github.com/igiagkiozis/plotly/blob/master/plotly/examples/plot3d.rs). +The complete source code for the following examples can also be found [here](https://github.com/plotly/plotly.rs/tree/main/examples/plot3d). Kind | Link :---|:----: diff --git a/docs/book/src/recipes/basic_charts.md b/docs/book/src/recipes/basic_charts.md index 24e0e5df..c8e3a77f 100644 --- a/docs/book/src/recipes/basic_charts.md +++ b/docs/book/src/recipes/basic_charts.md @@ -1,6 +1,6 @@ # Basic Charts -The source code for the following examples can also be found [here](https://github.com/igiagkiozis/plotly/blob/master/plotly/examples/basic_charts.rs). +The source code for the following examples can also be found [here](https://github.com/plotly/plotly.rs/tree/main/examples/basic_charts). Kind | Link :---|:----: diff --git a/docs/book/src/recipes/financial_charts.md b/docs/book/src/recipes/financial_charts.md index 4cca705a..6a811d9a 100644 --- a/docs/book/src/recipes/financial_charts.md +++ b/docs/book/src/recipes/financial_charts.md @@ -1,6 +1,6 @@ # Financial Charts -The source code for the following examples can also be found [here](https://github.com/igiagkiozis/plotly/blob/master/plotly/examples/financial_charts.rs). +The source code for the following examples can also be found [here](https://github.com/plotly/plotly.rs/tree/main/examples/financial_charts). Kind | Link :---|:----: diff --git a/docs/book/src/recipes/scientific_charts.md b/docs/book/src/recipes/scientific_charts.md index 2b18ea47..36549951 100644 --- a/docs/book/src/recipes/scientific_charts.md +++ b/docs/book/src/recipes/scientific_charts.md @@ -1,6 +1,6 @@ # Scientific Charts -The source code for the following examples can also be found [here](https://github.com/igiagkiozis/plotly/blob/master/plotly/examples/scientific_charts.rs). +The source code for the following examples can also be found [here](https://github.com/plotly/plotly.rs/tree/main/examples/scientific_charts). Kind | Link :---|:----: diff --git a/docs/book/src/recipes/statistical_charts.md b/docs/book/src/recipes/statistical_charts.md index adef8b98..4f446d1d 100644 --- a/docs/book/src/recipes/statistical_charts.md +++ b/docs/book/src/recipes/statistical_charts.md @@ -1,6 +1,6 @@ # Statistical Charts -The complete source code for the following examples can also be found [here](https://github.com/igiagkiozis/plotly/blob/master/plotly/examples/statistical_charts.rs). +The complete source code for the following examples can also be found [here](https://github.com/plotly/plotly.rs/tree/main/examples/statistical_charts). Kind | Link :---|:----: diff --git a/docs/book/src/recipes/subplots.md b/docs/book/src/recipes/subplots.md index 0f40e075..490ead55 100644 --- a/docs/book/src/recipes/subplots.md +++ b/docs/book/src/recipes/subplots.md @@ -1,6 +1,6 @@ # Subplots -The complete source code for the following examples can also be found [here](https://github.com/igiagkiozis/plotly/blob/master/plotly/examples/subplots.rs). +The complete source code for the following examples can also be found [here](https://github.com/plotly/plotly.rs/tree/main/examples/subplots). Kind | Link :---|:----: diff --git a/plotly/Cargo.toml b/plotly/Cargo.toml index 11b7880d..cca04f21 100644 --- a/plotly/Cargo.toml +++ b/plotly/Cargo.toml @@ -5,9 +5,9 @@ description = "A plotting library powered by Plotly.js" authors = ["Ioannis Giagkiozis "] license = "MIT" readme = "../README.md" -homepage = "https://github.com/igiagkiozis/plotly" +homepage = "https://github.com/plotly/plotly.rs" documentation = "https://docs.rs/plotly" -repository = "https://github.com/igiagkiozis/plotly" +repository = "https://github.com/plotly/plotly.rs" edition = "2018" keywords = ["plot", "chart", "plotly"] diff --git a/plotly/src/plot.rs b/plotly/src/plot.rs index a2dab216..03fe4ae0 100644 --- a/plotly/src/plot.rs +++ b/plotly/src/plot.rs @@ -62,7 +62,7 @@ let height = 680; let scale = 1.0; plot.write_image("filename", ImageFormat::PNG, width, height, scale); -See https://igiagkiozis.github.io/plotly/content/getting_started.html for further details. +See https://plotly.github.io/plotly.rs/content/getting_started.html for further details. "#; /// Image format for static image export. diff --git a/plotly_derive/Cargo.toml b/plotly_derive/Cargo.toml index 809347b3..5cd66285 100644 --- a/plotly_derive/Cargo.toml +++ b/plotly_derive/Cargo.toml @@ -4,9 +4,9 @@ version = "0.8.4" description = "Internal proc macro crate for Plotly-rs." authors = ["Ioannis Giagkiozis "] license = "MIT" -homepage = "https://github.com/igiagkiozis/plotly" +homepage = "https://github.com/plotly/plotly.rs" documentation = "https://docs.rs/plotly" -repository = "https://github.com/igiagkiozis/plotly" +repository = "https://github.com/plotly/plotly.rs" edition = "2018" keywords = ["plot", "chart", "plotly"] diff --git a/plotly_derive/README.md b/plotly_derive/README.md index 868ba5c3..6c2b83d6 100644 --- a/plotly_derive/README.md +++ b/plotly_derive/README.md @@ -1,3 +1,3 @@ # plotly_derive -This is an internal crate defining procedural macros for [Plotly.rs](https://github.com/igiagkiozis/plotly). \ No newline at end of file +This is an internal crate defining procedural macros for [Plotly.rs](https://github.com/plotly/plotly.rs). \ No newline at end of file diff --git a/plotly_kaleido/Cargo.toml b/plotly_kaleido/Cargo.toml index 8bed49b6..5714193d 100644 --- a/plotly_kaleido/Cargo.toml +++ b/plotly_kaleido/Cargo.toml @@ -6,9 +6,9 @@ authors = ["Ioannis Giagkiozis "] license = "MIT" readme = "README.md" workspace = ".." -homepage = "https://github.com/igiagkiozis/plotly" +homepage = "https://github.com/plotly/plotly.rs" documentation = "https://docs.rs/plotly_kaleido" -repository = "https://github.com/igiagkiozis/plotly" +repository = "https://github.com/plotly/plotly.rs" edition = "2018" keywords = ["plot", "chart", "plotly", "ndarray"] diff --git a/plotly_kaleido/README.md b/plotly_kaleido/README.md index f38830d4..0d0eae99 100644 --- a/plotly_kaleido/README.md +++ b/plotly_kaleido/README.md @@ -1,7 +1,7 @@ # plotly_kaleido -This is an internal crate which implements the `kaleido` feature for [Plotly.rs](https://github.com/igiagkiozis/plotly). - -The `kaleido` feature enables `Plot` conversion to the following output formats: `png`, `jpeg`, `webp`, `svg`, `pdf` and `eps`. +This is an internal crate which implements the `kaleido` feature for [Plotly.rs](https://github.com/plotly/plotly.rs). -See [examples/](https://github.com/igiagkiozis/plotly/tree/master/examples/kaleido) for usage demonstrations. \ No newline at end of file +The `kaleido` feature enables `Plot` conversion to the following output formats: `png`, `jpeg`, `webp`, `svg`, `pdf` and `eps`. + +See [examples/](https://github.com/plotly/plotly.rs/tree/main/examples/kaleido) for usage demonstrations. \ No newline at end of file diff --git a/plotly_kaleido/src/lib.rs b/plotly_kaleido/src/lib.rs index c3292c40..8fbfebe7 100644 --- a/plotly_kaleido/src/lib.rs +++ b/plotly_kaleido/src/lib.rs @@ -1,5 +1,5 @@ //! # Plotly Kaleido -//! Plotly Kaleido implements the `kaleido` feature for [Plotly.rs](https://github.com/igiagkiozis/plotly) +//! Plotly Kaleido implements the `kaleido` feature for [Plotly.rs](https://github.com/plotly/plotly.rs) //! //! The `kaleido` feature enables `Plot` conversion to the following output //! formats: png, jpeg, webp, svg, pdf and eps. It has the added benefit over From 328ccb89f7fae00ea21a1351cc114cafe58b18fb Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 24 May 2024 07:37:02 +0200 Subject: [PATCH 20/39] Update itertools requirement from >=0.10, <0.13 to >=0.10, <0.14 (#202) Updates the requirements on [itertools](https://github.com/rust-itertools/itertools) to permit the latest version. - [Changelog](https://github.com/rust-itertools/itertools/blob/master/CHANGELOG.md) - [Commits](https://github.com/rust-itertools/itertools/compare/v0.10.0...v0.13.0) --- updated-dependencies: - dependency-name: itertools dependency-type: direct:production ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- plotly/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plotly/Cargo.toml b/plotly/Cargo.toml index cca04f21..bea70ac3 100644 --- a/plotly/Cargo.toml +++ b/plotly/Cargo.toml @@ -43,7 +43,7 @@ wasm-bindgen-futures = { version = "0.4", optional = true } [dev-dependencies] csv = "1.1.6" image = "0.24" -itertools = ">=0.10, <0.13" +itertools = ">=0.10, <0.14" itertools-num = "0.1.3" ndarray = "0.15.4" plotly_kaleido = { version = "0.8.4", path = "../plotly_kaleido" } From 5e03d0fda1372dcd6d2419b87e66956f42051dbc Mon Sep 17 00:00:00 2001 From: "young.day" Date: Sun, 26 May 2024 21:44:07 +0800 Subject: [PATCH 21/39] wasm-yew-minimal deps yew to 0..21.0 (#203) * wasm-yew-minimal deps yew to 0..21.0 * Update examples/wasm-yew-minimal requirement yew from 0.19.0 to 0.21.0, hook from 0.1.56 to 0.3.2 --- examples/wasm-yew-minimal/Cargo.toml | 4 ++-- examples/wasm-yew-minimal/src/main.rs | 14 +++++--------- 2 files changed, 7 insertions(+), 11 deletions(-) diff --git a/examples/wasm-yew-minimal/Cargo.toml b/examples/wasm-yew-minimal/Cargo.toml index ea8d220d..86b11c3e 100644 --- a/examples/wasm-yew-minimal/Cargo.toml +++ b/examples/wasm-yew-minimal/Cargo.toml @@ -6,7 +6,7 @@ edition = "2021" [dependencies] plotly = { path = "../../plotly", features = ["wasm"] } -yew = "0.19.0" -yew-hooks = "0.1.56" +yew = "0.21.0" +yew-hooks = "0.3.2" log = "0.4.6" wasm-logger = "0.2" \ No newline at end of file diff --git a/examples/wasm-yew-minimal/src/main.rs b/examples/wasm-yew-minimal/src/main.rs index 8649c03c..f38ab848 100644 --- a/examples/wasm-yew-minimal/src/main.rs +++ b/examples/wasm-yew-minimal/src/main.rs @@ -18,14 +18,10 @@ pub fn plot_component() -> Html { Ok(()) } }); - - use_effect_with_deps( - move |_| { - p.run(); - || () - }, - (), - ); + // Only on first render + use_effect_with((), move |_| { + p.run(); + }); html! {
@@ -34,5 +30,5 @@ pub fn plot_component() -> Html { fn main() { wasm_logger::init(wasm_logger::Config::default()); - yew::start_app::(); + yew::Renderer::::new().render(); } From 702d945bf9af522a5b5cb1ea740594a20343f99a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 27 May 2024 08:56:23 +0200 Subject: [PATCH 22/39] Update zip requirement from 1.1 to 2.1 (#205) Updates the requirements on [zip](https://github.com/zip-rs/zip2) to permit the latest version. - [Release notes](https://github.com/zip-rs/zip2/releases) - [Changelog](https://github.com/zip-rs/zip2/blob/master/CHANGELOG.md) - [Commits](https://github.com/zip-rs/zip2/compare/1.1.0...v2.1.0) --- updated-dependencies: - dependency-name: zip dependency-type: direct:production ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- plotly_kaleido/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plotly_kaleido/Cargo.toml b/plotly_kaleido/Cargo.toml index 5714193d..73b873cb 100644 --- a/plotly_kaleido/Cargo.toml +++ b/plotly_kaleido/Cargo.toml @@ -22,5 +22,5 @@ dunce = "1.0.2" directories = ">=4, <6" [build-dependencies] -zip = "1.1" +zip = "2.1" directories = ">=4, <6" From d0476139b1430854f5714b5797346b39623e0ea2 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 12 Jun 2024 11:47:30 +0200 Subject: [PATCH 23/39] Update image requirement from 0.24 to 0.25 (#197) * Update image requirement from 0.24 to 0.25 Updates the requirements on [image](https://github.com/image-rs/image) to permit the latest version. - [Changelog](https://github.com/image-rs/image/blob/main/CHANGES.md) - [Commits](https://github.com/image-rs/image/compare/v0.24.0...v0.25.1) --- updated-dependencies: - dependency-name: image dependency-type: direct:production ... Signed-off-by: dependabot[bot] * update image crate version in examples dir Signed-off-by: Andrei Gherghescu <8067229+andrei-ng@users.noreply.github.com> --------- Signed-off-by: dependabot[bot] Signed-off-by: Andrei Gherghescu <8067229+andrei-ng@users.noreply.github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Andrei Gherghescu <8067229+andrei-ng@users.noreply.github.com> --- examples/images/Cargo.toml | 2 +- plotly/Cargo.toml | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/examples/images/Cargo.toml b/examples/images/Cargo.toml index 144ac7a4..59a3bc34 100644 --- a/examples/images/Cargo.toml +++ b/examples/images/Cargo.toml @@ -5,6 +5,6 @@ authors = ["Michael Freeborn "] edition = "2021" [dependencies] -image = "0.24.4" +image = "0.25" ndarray = "0.15.6" plotly = { path = "../../plotly", features = ["plotly_image", "plotly_ndarray"] } diff --git a/plotly/Cargo.toml b/plotly/Cargo.toml index bea70ac3..55df4e53 100644 --- a/plotly/Cargo.toml +++ b/plotly/Cargo.toml @@ -26,7 +26,7 @@ askama_axum = { version = "0.4.0", optional = true } dyn-clone = "1" erased-serde = "0.4" getrandom = { version = "0.2", features = ["js"], optional = true } -image = { version = "0.24", optional = true } +image = { version = "0.25", optional = true } js-sys = { version = "0.3", optional = true } plotly_derive = { version = "0.8.4", path = "../plotly_derive" } plotly_kaleido = { version = "0.8.4", path = "../plotly_kaleido", optional = true } @@ -42,7 +42,7 @@ wasm-bindgen-futures = { version = "0.4", optional = true } [dev-dependencies] csv = "1.1.6" -image = "0.24" +image = "0.25" itertools = ">=0.10, <0.14" itertools-num = "0.1.3" ndarray = "0.15.4" From 3130f5a43d1f9febb890fa48c50b35b03ca1050c Mon Sep 17 00:00:00 2001 From: Andrei <8067229+andrei-ng@users.noreply.github.com> Date: Wed, 12 Jun 2024 11:55:29 +0200 Subject: [PATCH 24/39] Add semver github action check (#206) * bump up ci's checkout action to v4 * add semver check github action Signed-off-by: Andrei Gherghescu <8067229+andrei-ng@users.noreply.github.com> --- .github/workflows/ci.yml | 26 ++++++++++++++++++++------ .github/workflows/release.yml | 2 +- 2 files changed, 21 insertions(+), 7 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index cc5c3c65..261d3677 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -21,7 +21,7 @@ jobs: name: Rustfmt runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - uses: dtolnay/rust-toolchain@nightly with: components: rustfmt @@ -32,7 +32,7 @@ jobs: name: Clippy runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - uses: dtolnay/rust-toolchain@stable with: components: clippy @@ -46,6 +46,20 @@ jobs: # lint the wasm examples - run: cd ${{ github.workspace }}/examples && cargo clippy --target wasm32-unknown-unknown --package "wasm*" + semver: + name: semver + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - name: Check semver + uses: obi1kenobi/cargo-semver-checks-action@v2 + with: + package: plotly + feature-group: only-explicit-features + features: kaleido + rust-toolchain: stable + release-type: minor + test: name: Tests strategy: @@ -54,7 +68,7 @@ jobs: os: [ubuntu-latest, windows-latest, macos-latest] runs-on: ${{ matrix.os }} steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - uses: dtolnay/rust-toolchain@stable - run: cargo test --features plotly_ndarray,plotly_image,kaleido - if: ${{ matrix.os == 'windows-latest' }} @@ -64,7 +78,7 @@ jobs: name: Code Coverage runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - uses: dtolnay/rust-toolchain@stable with: components: llvm-tools-preview @@ -93,7 +107,7 @@ jobs: ] runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - uses: dtolnay/rust-toolchain@stable - run: cd ${{ github.workspace }}/examples/${{ matrix.example }} && cargo build @@ -105,7 +119,7 @@ jobs: example: [wasm-yew-minimal] runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - uses: dtolnay/rust-toolchain@stable with: targets: wasm32-unknown-unknown diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 88c3d407..e64c3a6e 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -10,7 +10,7 @@ jobs: name: Deploy to crates.io runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - uses: dtolnay/rust-toolchain@stable - run: cargo login ${{ env.CRATES_IO_TOKEN }} env: From e14193c5f90de6f56b1ffae34e9105f45bbb4490 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aur=C3=A9lie=20Grebe?= Date: Wed, 12 Jun 2024 06:22:14 -0400 Subject: [PATCH 25/39] Make heat_map module public to expose Smoothing enum. (#159) * Make heat_map module public to expose Smoothing enum. Signed-off-by: Andrei Gherghescu <8067229+andrei-ng@users.noreply.github.com> --------- Signed-off-by: Andrei Gherghescu <8067229+andrei-ng@users.noreply.github.com> Co-authored-by: Andrei Gherghescu <8067229+andrei-ng@users.noreply.github.com> --- plotly/src/lib.rs | 4 +++- plotly/src/traces/mod.rs | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/plotly/src/lib.rs b/plotly/src/lib.rs index 729e0a9d..72dbbc34 100644 --- a/plotly/src/lib.rs +++ b/plotly/src/lib.rs @@ -30,7 +30,9 @@ pub use configuration::Configuration; pub use layout::Layout; pub use plot::{ImageFormat, Plot, Trace}; // Also provide easy access to modules which contain additional trace-specific types -pub use traces::{box_plot, contour, histogram, image, mesh3d, sankey, scatter_mapbox, surface}; +pub use traces::{ + box_plot, contour, heat_map, histogram, image, mesh3d, sankey, scatter_mapbox, surface, +}; // Bring the different trace types into the top-level scope pub use traces::{ Bar, BoxPlot, Candlestick, Contour, DensityMapbox, HeatMap, Histogram, Image, Mesh3D, Ohlc, diff --git a/plotly/src/traces/mod.rs b/plotly/src/traces/mod.rs index e6ca3179..27f55f89 100644 --- a/plotly/src/traces/mod.rs +++ b/plotly/src/traces/mod.rs @@ -5,7 +5,7 @@ pub mod box_plot; mod candlestick; pub mod contour; mod density_mapbox; -mod heat_map; +pub mod heat_map; pub mod histogram; pub mod image; pub mod mesh3d; From c642253d4f430273c3e2c0adf2bc20e925f22cda Mon Sep 17 00:00:00 2001 From: Pontus <36114799+prokie@users.noreply.github.com> Date: Wed, 12 Jun 2024 16:37:11 +0200 Subject: [PATCH 26/39] Added subplot example with multiple titles (#166) * Added example with multiple titles Signed-off-by: Andrei Gherghescu <8067229+andrei-ng@users.noreply.github.com> --------- Signed-off-by: Andrei Gherghescu <8067229+andrei-ng@users.noreply.github.com> Co-authored-by: Andrei <8067229+andrei-ng@users.noreply.github.com> --- examples/subplots/src/main.rs | 49 ++++++++++++++++++++++++++++++++--- 1 file changed, 46 insertions(+), 3 deletions(-) diff --git a/examples/subplots/src/main.rs b/examples/subplots/src/main.rs index 88af0dcb..18aee5ac 100644 --- a/examples/subplots/src/main.rs +++ b/examples/subplots/src/main.rs @@ -1,9 +1,11 @@ #![allow(dead_code)] -use plotly::common::{AxisSide, Font, Title}; -use plotly::layout::{Axis, GridPattern, Layout, LayoutGrid, Legend, RowOrder, TraceOrder}; +use plotly::common::{Anchor, AxisSide, Font, Title}; +use plotly::layout::{ + Annotation, Axis, GridPattern, Layout, LayoutGrid, Legend, RowOrder, TraceOrder, +}; +use plotly::Configuration; use plotly::{color::Rgb, Plot, Scatter}; - // Subplots fn simple_subplot() { let trace1 = Scatter::new(vec![1, 2, 3], vec![4, 5, 6]).name("trace1"); @@ -242,6 +244,46 @@ fn multiple_axes() { plot.show(); } +fn many_subplots_with_titles() { + let trace1 = Scatter::new(vec![1, 2], vec![4, 5]); + + let number_of_plots = 10; + + let mut plot = Plot::new(); + let mut layout = Layout::new() + .grid( + LayoutGrid::new() + .rows(number_of_plots / 2) + .columns(2) + .pattern(GridPattern::Independent), + ) + .height(number_of_plots * 200); + + for i in 1..number_of_plots + 1 { + plot.add_trace( + trace1 + .clone() + .y_axis(format!("y{}", i)) + .x_axis(format!("x{}", i)), + ); + layout.add_annotation( + Annotation::new() + .y_ref(format!("y{} domain", i)) + .y_anchor(Anchor::Bottom) + .y(1) + .text(format!("Title {}", i)) + .x_ref(format!("x{} domain", i)) + .x_anchor(Anchor::Center) + .x(0.5) + .show_arrow(false), + ) + } + + plot.set_layout(layout); + plot.set_configuration(Configuration::new().responsive(true)); + plot.show(); +} + fn main() { // Uncomment any of these lines to display the example. @@ -252,6 +294,7 @@ fn main() { // stacked_subplots(); // stacked_subplots_with_shared_x_axis(); // multiple_custom_sized_subplots(); + // many_subplots_with_titles(); // Multiple Axes // two_y_axes(); From a6fd29b733fbadf3abbea7a1bb589173e48b15ef Mon Sep 17 00:00:00 2001 From: Tristan Kobusch Date: Wed, 12 Jun 2024 22:12:31 +0200 Subject: [PATCH 27/39] add scalenchor (#161) * add scalenchor * fix kaleido crash on windows by taking ownership of stdin/stdout --------- Signed-off-by: Andrei Gherghescu <8067229+andrei-ng@users.noreply.github.com> Co-authored-by: Tristan Kobusch Co-authored-by: Andrei Gherghescu <8067229+andrei-ng@users.noreply.github.com> --- plotly/src/layout/mod.rs | 3 +++ plotly_kaleido/src/lib.rs | 7 ++++--- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/plotly/src/layout/mod.rs b/plotly/src/layout/mod.rs index 55e2dfd8..6ea1e16f 100644 --- a/plotly/src/layout/mod.rs +++ b/plotly/src/layout/mod.rs @@ -441,6 +441,9 @@ pub struct Axis { #[serde(rename = "nticks")] n_ticks: Option, + #[serde(rename = "scaleanchor")] + scale_anchor: Option, + tick0: Option, dtick: Option, diff --git a/plotly_kaleido/src/lib.rs b/plotly_kaleido/src/lib.rs index 8fbfebe7..199c77fe 100644 --- a/plotly_kaleido/src/lib.rs +++ b/plotly_kaleido/src/lib.rs @@ -138,7 +138,7 @@ impl Kaleido { let p = p.to_str().unwrap(); let p = String::from(p); - let process = Command::new(p.as_str()) + let mut process = Command::new(p.as_str()) .current_dir(self.cmd_path.parent().unwrap()) .args([ "plotly", @@ -146,6 +146,7 @@ impl Kaleido { "--allow-file-access-from-files", "--disable-breakpad", "--disable-dev-shm-usage", + "--disable-software-rasterizer", "--single-process", ]) .stdin(Stdio::piped()) @@ -156,14 +157,14 @@ impl Kaleido { { let plot_data = PlotData::new(plotly_data, format, width, height, scale).to_json(); - let mut process_stdin = process.stdin.unwrap(); + let mut process_stdin = process.stdin.take().unwrap(); process_stdin .write_all(plot_data.as_bytes()) .expect("couldn't write to Kaleido stdin"); process_stdin.flush()?; } - let output_lines = BufReader::new(process.stdout.unwrap()).lines(); + let output_lines = BufReader::new(process.stdout.take().unwrap()).lines(); for line in output_lines.map_while(Result::ok) { let res = KaleidoResult::from(line.as_str()); if let Some(image_data) = res.result { From 99ba4ffcae3820cd33287d4469718336ed6b6728 Mon Sep 17 00:00:00 2001 From: Yuichi Nakamura <153576294+yunaka354@users.noreply.github.com> Date: Tue, 18 Jun 2024 20:57:35 +0900 Subject: [PATCH 28/39] #173 update example for Yew (#174) Signed-off-by: Andrei Gherghescu <8067229+andrei-ng@users.noreply.github.com> Co-authored-by: Andrei Gherghescu <8067229+andrei-ng@users.noreply.github.com> --- examples/wasm-yew-minimal/Cargo.toml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/wasm-yew-minimal/Cargo.toml b/examples/wasm-yew-minimal/Cargo.toml index 86b11c3e..cef3d180 100644 --- a/examples/wasm-yew-minimal/Cargo.toml +++ b/examples/wasm-yew-minimal/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "wasm-yew-minimal" version = "0.1.0" -authors = ["Michael Freeborn "] +authors = ["Michael Freeborn ", "Yuichi Nakamura "] edition = "2021" [dependencies] @@ -9,4 +9,4 @@ plotly = { path = "../../plotly", features = ["wasm"] } yew = "0.21.0" yew-hooks = "0.3.2" log = "0.4.6" -wasm-logger = "0.2" \ No newline at end of file +wasm-logger = "0.2" From df6bdb628ac0c344bbfe6a6bc9319c823ac8c5b9 Mon Sep 17 00:00:00 2001 From: Andrei <8067229+andrei-ng@users.noreply.github.com> Date: Tue, 18 Jun 2024 14:54:42 +0200 Subject: [PATCH 29/39] silence new clippy warning in autogenerated code in Rust 1.79 (#209) Signed-off-by: Andrei Gherghescu <8067229+andrei-ng@users.noreply.github.com> --- .github/workflows/ci.yml | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 261d3677..39f77550 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -38,13 +38,15 @@ jobs: components: clippy targets: wasm32-unknown-unknown # lint the main library workspace excluding the wasm feature - - run: cargo clippy --features plotly_ndarray,plotly_image,kaleido -- -D warnings + # Rust 1.79 generates a new lint in autogenrated code: + # Added clippy allow at the command line until it is fixed. See: https://github.com/rust-lang/rust-clippy/issues/12643 and https://github.com/TedDriggs/darling/issues/293 + - run: cargo clippy --features plotly_ndarray,plotly_image,kaleido -- -D warnings -Aclippy::manual_unwrap_or_default # lint the plotly library with wasm enabled - - run: cargo clippy --package plotly --features wasm --target wasm32-unknown-unknown -- -D warnings + - run: cargo clippy --package plotly --features wasm --target wasm32-unknown-unknown -- -D warnings -Aclippy::manual_unwrap_or_default # lint the non-wasm examples - - run: cd ${{ github.workspace }}/examples && cargo clippy --workspace --exclude "wasm*" -- -D warnings + - run: cd ${{ github.workspace }}/examples && cargo clippy --workspace --exclude "wasm*" -- -D warnings -Aclippy::manual_unwrap_or_default # lint the wasm examples - - run: cd ${{ github.workspace }}/examples && cargo clippy --target wasm32-unknown-unknown --package "wasm*" + - run: cd ${{ github.workspace }}/examples && cargo clippy --target wasm32-unknown-unknown --package "wasm*" -- -Aclippy::manual_unwrap_or_default semver: name: semver From f1e4a36bdab9f192006ac73237bce27bd3a59921 Mon Sep 17 00:00:00 2001 From: Greg Wilson Date: Tue, 18 Jun 2024 11:41:16 -0400 Subject: [PATCH 30/39] Update README.md with "community maintained" badge --- README.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/README.md b/README.md index 50518376..1909419e 100644 --- a/README.md +++ b/README.md @@ -29,6 +29,12 @@
+ + # Table of Contents * [Introduction](#introduction) From e12737465c6e1b1f01bcd5947bd7c170097a6638 Mon Sep 17 00:00:00 2001 From: Nathan Date: Tue, 18 Jun 2024 12:58:40 -0400 Subject: [PATCH 31/39] Update license to match other Plotly projects --- COPYRIGHT | 8 -------- LICENSE | 21 +++++++++++++++++++++ LICENSE-MIT | 25 ------------------------- 3 files changed, 21 insertions(+), 33 deletions(-) delete mode 100644 COPYRIGHT create mode 100644 LICENSE delete mode 100644 LICENSE-MIT diff --git a/COPYRIGHT b/COPYRIGHT deleted file mode 100644 index 2593be82..00000000 --- a/COPYRIGHT +++ /dev/null @@ -1,8 +0,0 @@ -Copyrights in the Plotly.rs project are retained by their contributors. No -copyright assignment is required to contribute to the Plotly.rs project. - -For full authorship information, see the version control history. - -Except as otherwise noted (below and/or in individual files), Plotly.rs -licensed under the MIT license - or . diff --git a/LICENSE b/LICENSE new file mode 100644 index 00000000..d7ee7c8a --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2024 Plotly, Inc + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. \ No newline at end of file diff --git a/LICENSE-MIT b/LICENSE-MIT deleted file mode 100644 index 3893863b..00000000 --- a/LICENSE-MIT +++ /dev/null @@ -1,25 +0,0 @@ -Copyright (c) 2020-2022 Ioannis Giagkiozis - -Permission is hereby granted, free of charge, to any -person obtaining a copy of this software and associated -documentation files (the "Software"), to deal in the -Software without restriction, including without -limitation the rights to use, copy, modify, merge, -publish, distribute, sublicense, and/or sell copies of -the Software, and to permit persons to whom the Software -is furnished to do so, subject to the following -conditions: - -The above copyright notice and this permission notice -shall be included in all copies or substantial portions -of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF -ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED -TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A -PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY -CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR -IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -DEALINGS IN THE SOFTWARE. \ No newline at end of file From 9bdee2a7fbe82e050313bcd6f1285fa1d8ba09b7 Mon Sep 17 00:00:00 2001 From: Nathan Date: Tue, 18 Jun 2024 13:00:55 -0400 Subject: [PATCH 32/39] Update CHANGELOG.md --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5b5a0819..8924c10b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) a - [[#180](https://github.com/plotly/plotly.rs/pull/180)] Add setter for `Mapbox::domain`. - [[#163](https://github.com/plotly/plotly.rs/pull/163)] Added `DensityMapbox`. - [[#153](https://github.com/plotly/plotly.rs/pull/153)] Added `LayoutScene`. +- [[#212](https://github.com/plotly/plotly.rs/pull/212)] Update LICENSE ## [0.8.4] - 2023-07-09 ### Added From 5d32eb34bbbec7ab5cc126134c6c5a0670b6dcc3 Mon Sep 17 00:00:00 2001 From: Andrei <8067229+andrei-ng@users.noreply.github.com> Date: Wed, 19 Jun 2024 07:22:16 +0200 Subject: [PATCH 33/39] update changelog (#208) Signed-off-by: Andrei Gherghescu <8067229+andrei-ng@users.noreply.github.com> --- .github/workflows/ci.yml | 2 +- CHANGELOG.md | 5 ++++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 39f77550..4d3cfb70 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -38,7 +38,7 @@ jobs: components: clippy targets: wasm32-unknown-unknown # lint the main library workspace excluding the wasm feature - # Rust 1.79 generates a new lint in autogenrated code: + # Rust 1.79 generates a new lint in autogenerated code: # Added clippy allow at the command line until it is fixed. See: https://github.com/rust-lang/rust-clippy/issues/12643 and https://github.com/TedDriggs/darling/issues/293 - run: cargo clippy --features plotly_ndarray,plotly_image,kaleido -- -D warnings -Aclippy::manual_unwrap_or_default # lint the plotly library with wasm enabled diff --git a/CHANGELOG.md b/CHANGELOG.md index 5b5a0819..a64ee54b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,11 +3,14 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). -## [0.8.5] - 2024-xx-xx +## [0.9.0] - 2024-xx-xx ### Added - [[#181](https://github.com/plotly/plotly,rs/pull/181)] Fix compilation error when mixing the crate with `askama/with-axum` by adding `with-axum` feature. - [[#180](https://github.com/plotly/plotly.rs/pull/180)] Add setter for `Mapbox::domain`. +- [[#166](https://github.com/plotly/plotly.rs/pull/166)] Added subplot example with multiple titles. - [[#163](https://github.com/plotly/plotly.rs/pull/163)] Added `DensityMapbox`. +- [[#161](https://github.com/plotly/plotly.rs/pull/161)] Added `Axis` `scaleanchor` settter. +- [[#159](https://github.com/plotly/plotly.rs/pull/159)] Make `heat_map` module public to expose `Smoothing enum`. - [[#153](https://github.com/plotly/plotly.rs/pull/153)] Added `LayoutScene`. ## [0.8.4] - 2023-07-09 From 4815df72ff78739aff5e1c6fddb5a3e83c816da4 Mon Sep 17 00:00:00 2001 From: "Seb. V" Date: Wed, 19 Jun 2024 09:33:19 +0200 Subject: [PATCH 34/39] Fix setter for Axis::matches to take string arg (#178) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Make layout axis matches take string as argument - follow similar implemnetation as python plotly fixes #156 Signed-off-by: Andrei Gherghescu <8067229+andrei-ng@users.noreply.github.com> --------- Signed-off-by: Andrei Gherghescu <8067229+andrei-ng@users.noreply.github.com> Co-authored-by: Sébastien Vauclair Co-authored-by: Andrei <8067229+andrei-ng@users.noreply.github.com> --- examples/subplots/src/main.rs | 46 +++++++++++++++++++++++++++++++++++ plotly/src/layout/mod.rs | 8 +++--- 2 files changed, 49 insertions(+), 5 deletions(-) diff --git a/examples/subplots/src/main.rs b/examples/subplots/src/main.rs index 18aee5ac..d96616a0 100644 --- a/examples/subplots/src/main.rs +++ b/examples/subplots/src/main.rs @@ -29,6 +29,50 @@ fn simple_subplot() { plot.show(); } +fn simple_subplot_matches_x_axis() { + let trace1 = Scatter::new(vec![1, 2, 3], vec![4, 5, 6]).name("trace1"); + let trace2 = Scatter::new(vec![20, 30, 40], vec![50, 60, 70]) + .name("trace2") + .x_axis("x2") + .y_axis("y2"); + + let mut plot = Plot::new(); + plot.add_trace(trace1); + plot.add_trace(trace2); + + let layout = Layout::new().x_axis(Axis::new().matches("x2")).grid( + LayoutGrid::new() + .rows(1) + .columns(2) + .pattern(GridPattern::Independent), + ); + plot.set_layout(layout); + + plot.show(); +} + +fn simple_subplot_matches_y_axis() { + let trace1 = Scatter::new(vec![1, 2, 3], vec![4, 5, 6]).name("trace1"); + let trace2 = Scatter::new(vec![20, 30, 40], vec![50, 60, 70]) + .name("trace2") + .x_axis("x2") + .y_axis("y2"); + + let mut plot = Plot::new(); + plot.add_trace(trace1); + plot.add_trace(trace2); + + let layout = Layout::new().y_axis(Axis::new().matches("y2")).grid( + LayoutGrid::new() + .rows(1) + .columns(2) + .pattern(GridPattern::Independent), + ); + plot.set_layout(layout); + + plot.show(); +} + fn custom_sized_subplot() { let trace1 = Scatter::new(vec![1, 2, 3], vec![4, 5, 6]).name("trace1"); let trace2 = Scatter::new(vec![20, 30, 40], vec![50, 60, 70]) @@ -289,6 +333,8 @@ fn main() { // Subplots // simple_subplot(); + // simple_subplot_matches_x_axis(); + // simple_subplot_matches_y_axis(); // custom_sized_subplot(); // multiple_subplots(); // stacked_subplots(); diff --git a/plotly/src/layout/mod.rs b/plotly/src/layout/mod.rs index 6ea1e16f..d0d53f8d 100644 --- a/plotly/src/layout/mod.rs +++ b/plotly/src/layout/mod.rs @@ -546,10 +546,8 @@ impl Axis { Default::default() } - pub fn matches(mut self, matches: bool) -> Self { - if matches { - self.matches = Some(String::from("x")); - } + pub fn matches(mut self, matches: &str) -> Self { + self.matches = Some(matches.to_string()); self } @@ -2444,7 +2442,7 @@ mod tests { .n_ticks(600) .tick0(5.0) .dtick(10.0) - .matches(true) + .matches("x") .tick_values(vec![1.0, 2.0]) .tick_text(vec!["one".to_string(), "two".to_string()]) .ticks(TicksDirection::Inside) From 8713ad2b343ff68261d2c043b31af2343c06f8c6 Mon Sep 17 00:00:00 2001 From: naijim Date: Wed, 19 Jun 2024 15:47:02 +0800 Subject: [PATCH 35/39] Add Table trace (#207) * Add `Table` trace * update changelog --------- Signed-off-by: Andrei Gherghescu <8067229+andrei-ng@users.noreply.github.com> Co-authored-by: Andrei Gherghescu <8067229+andrei-ng@users.noreply.github.com> Co-authored-by: baiguoname Co-authored-by: kylemello --- CHANGELOG.md | 2 + examples/basic_charts/src/main.rs | 14 ++- plotly/src/common/mod.rs | 1 + plotly/src/lib.rs | 2 +- plotly/src/traces/mod.rs | 2 + plotly/src/traces/table.rs | 177 ++++++++++++++++++++++++++++++ 6 files changed, 196 insertions(+), 2 deletions(-) create mode 100644 plotly/src/traces/table.rs diff --git a/CHANGELOG.md b/CHANGELOG.md index a64ee54b..eab1cfc5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,8 +5,10 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) a ## [0.9.0] - 2024-xx-xx ### Added +- [[#207](https://github.com/plotly/plotly,rs/pull/207)] Add `Table` trace. - [[#181](https://github.com/plotly/plotly,rs/pull/181)] Fix compilation error when mixing the crate with `askama/with-axum` by adding `with-axum` feature. - [[#180](https://github.com/plotly/plotly.rs/pull/180)] Add setter for `Mapbox::domain`. +- [[#178](https://github.com/plotly/plotly.rs/pull/178)] Fix setter for `Axis::matches` to take string arg. - [[#166](https://github.com/plotly/plotly.rs/pull/166)] Added subplot example with multiple titles. - [[#163](https://github.com/plotly/plotly.rs/pull/163)] Added `DensityMapbox`. - [[#161](https://github.com/plotly/plotly.rs/pull/161)] Added `Axis` `scaleanchor` settter. diff --git a/examples/basic_charts/src/main.rs b/examples/basic_charts/src/main.rs index 65518e2f..9408c755 100644 --- a/examples/basic_charts/src/main.rs +++ b/examples/basic_charts/src/main.rs @@ -9,7 +9,8 @@ use plotly::{ }, layout::{Axis, BarMode, Layout, Legend, TicksDirection, TraceOrder}, sankey::{Line as SankeyLine, Link, Node}, - Bar, Plot, Sankey, Scatter, ScatterPolar, + traces::table::{Cells, Header}, + Bar, Plot, Sankey, Scatter, ScatterPolar, Table, }; use rand_distr::{Distribution, Normal, Uniform}; @@ -604,6 +605,16 @@ fn basic_sankey_diagram() { plot.show(); } +fn table_chart() { + let trace = Table::new( + Header::new(vec![String::from("col1"), String::from("col2")]), + Cells::new(vec![vec![1, 2], vec![2, 3]]), + ); + let mut plot = Plot::new(); + plot.add_trace(trace); + plot.show(); +} + fn main() { // Uncomment any of these lines to display the example. @@ -629,6 +640,7 @@ fn main() { // basic_bar_chart(); // grouped_bar_chart(); // stacked_bar_chart(); + // table_chart(); // Sankey Diagrams // basic_sankey_diagram(); diff --git a/plotly/src/common/mod.rs b/plotly/src/common/mod.rs index d6cc3082..4777afb5 100644 --- a/plotly/src/common/mod.rs +++ b/plotly/src/common/mod.rs @@ -202,6 +202,7 @@ pub enum PlotType { Sankey, Surface, DensityMapbox, + Table, } #[derive(Serialize, Clone, Debug)] diff --git a/plotly/src/lib.rs b/plotly/src/lib.rs index 72dbbc34..c5337680 100644 --- a/plotly/src/lib.rs +++ b/plotly/src/lib.rs @@ -36,7 +36,7 @@ pub use traces::{ // Bring the different trace types into the top-level scope pub use traces::{ Bar, BoxPlot, Candlestick, Contour, DensityMapbox, HeatMap, Histogram, Image, Mesh3D, Ohlc, - Sankey, Scatter, Scatter3D, ScatterMapbox, ScatterPolar, Surface, + Sankey, Scatter, Scatter3D, ScatterMapbox, ScatterPolar, Surface, Table, }; pub trait Restyle: serde::Serialize {} diff --git a/plotly/src/traces/mod.rs b/plotly/src/traces/mod.rs index 27f55f89..f12305c3 100644 --- a/plotly/src/traces/mod.rs +++ b/plotly/src/traces/mod.rs @@ -16,6 +16,7 @@ mod scatter3d; pub mod scatter_mapbox; mod scatter_polar; pub mod surface; +pub mod table; pub use bar::Bar; pub use box_plot::BoxPlot; @@ -32,5 +33,6 @@ pub use scatter3d::Scatter3D; pub use scatter_mapbox::ScatterMapbox; pub use scatter_polar::ScatterPolar; pub use surface::Surface; +pub use table::Table; pub use self::image::Image; diff --git a/plotly/src/traces/table.rs b/plotly/src/traces/table.rs new file mode 100644 index 00000000..58545a57 --- /dev/null +++ b/plotly/src/traces/table.rs @@ -0,0 +1,177 @@ +//! Table trace + +use plotly_derive::FieldSetter; +use serde::Serialize; + +use crate::{ + color::Color, + common::{Font, Line, PlotType, Visible}, + Trace, +}; + +#[serde_with::skip_serializing_none] +#[derive(Serialize, Clone, Debug, FieldSetter)] +#[field_setter(box_self, kind = "trace")] +pub struct Table +where + T: Serialize + Clone + 'static, + N: Serialize + Clone + 'static, +{ + #[field_setter(default = "PlotType::Table")] + r#type: PlotType, + /// Sets the trace name. The trace name appear as the legend item and on + /// hover. + name: Option, + #[serde(rename = "columnorder")] + /// Determines whether or not this trace is visible. If + /// `Visible::LegendOnly`, the trace is not drawn, but can appear as a + /// legend item (provided that the legend itself is visible). + visible: Option, + ///Specifies the rendered order of the data columns; for example, a value + /// `2` at position `0`, means that column index `0` in the data will be + /// rendered as the, third column, as columns have an index base of + /// zero. + column_order: Option>, + #[serde(rename = "columnwidth")] + ///The width of columns expressed as a ratio. Columns fill the available + /// width, in proportion of their specified column widths. + column_width: Option, + ///Header cell values. `values[m][n]` represents the value of the `n`th + /// point in column `m`,, therefore the `values[m]` vector length for + /// all columns must be the same (longer vectors, will be truncated). + /// Each value must be a finite number or a string. + header: Option>, + ///Cell values. `values[m][n]` represents the value of the `n`th point in + /// column `m`,, therefore the `values[m]` vector length for all columns + /// must be the same (longer vectors, will be truncated). Each value + /// must be a finite number or a string. + cells: Option>, +} + +impl Table +where + T: Serialize + Clone + Default + 'static, + N: Serialize + Clone + Default + 'static, +{ + pub fn new(header: Header, cells: Cells) -> Box { + Box::new(Table { + header: Some(header), + cells: Some(cells), + ..Default::default() + }) + } +} + +impl Trace for Table +where + T: Serialize + Clone + 'static, + N: Serialize + Clone + 'static, +{ + fn to_json(&self) -> String { + serde_json::to_string(self).unwrap() + } +} + +#[serde_with::skip_serializing_none] +#[derive(Serialize, Clone, Debug, FieldSetter)] +pub struct Cells { + ///Cell values. `values[m][n]` represents the value of the `n`th point in + /// column `m`, therefore the `values[m]` vector length for all columns + /// must be the same (longer vectors, will be truncated). Each value + /// must be a finite number or a string + values: Option>>, + ///Prefix for cell values. + prefix: Option, + ///Suffix for cell values. + suffix: Option, + height: Option, + align: Option, + line: Option, + ///Sets the cell fill color. It accepts either a specific color, + ///or an array of colors or a 2D array of colors + fill: Option, + font: Option, +} + +impl Cells +where + N: Serialize + Clone + Default + 'static, +{ + pub fn new(values: Vec>) -> Self { + Cells { + values: Some(values), + ..Default::default() + } + } +} + +#[serde_with::skip_serializing_none] +#[derive(Serialize, Clone, Debug, FieldSetter)] +pub struct Header { + ///Header cell values. `values[m][n]` represents the value of the `n`th + /// point in column `m`, therefore the `values[m]` vector length for all + /// columns must be the same (longer vectors, will be truncated). Each + /// value must be a finite number or a string. + values: Option>, + ///Prefix for cell values. + prefix: Option, + ///Suffix for cell values. + suffix: Option, + height: Option, + align: Option, + line: Option, + ///Sets the cell fill color. It accepts either a specific color, + ///or an array of colors or a 2D array of colors + fill: Option, + font: Option, +} + +impl Header +where + T: Serialize + Clone + Default + 'static, +{ + pub fn new(values: Vec) -> Self { + Header { + values: Some(values), + ..Default::default() + } + } +} + +#[serde_with::skip_serializing_none] +#[derive(Serialize, Clone, Debug, FieldSetter)] +pub struct Fill { + color: Option>, +} + +impl Fill { + pub fn new() -> Self { + Default::default() + } +} + +#[cfg(test)] +mod tests { + use serde_json::{json, to_value}; + + use super::*; + + #[test] + fn test_serialize_table() { + let columns = Header::new(vec![String::from("col1"), String::from("col2")]); + let values = Cells::new(vec![vec![1, 2], vec![2, 3]]); + let trace = Table::new(columns, values); + + let expected = json!({ + "type": "table", + "cells": { + "values": [[1, 2], [2, 3]], + }, + "header": { + "values": ["col1", "col2"], + }, + }); + + assert_eq!(to_value(trace).unwrap(), expected); + } +} From 00718312003ed70f22a10bfd2ad4c343ffbca8ba Mon Sep 17 00:00:00 2001 From: Tectin <94180412+tectin0@users.noreply.github.com> Date: Wed, 19 Jun 2024 14:28:04 +0000 Subject: [PATCH 36/39] Impl Color for f64 (+ f32, i64, i32, ...) (#155) * added impl Color for number types + colorscale example * fixed colorscale in customized_scatter3d_plot --- examples/3d_charts/Cargo.toml | 1 + examples/3d_charts/src/main.rs | 77 ++++++++++++++++++++++++++++++++-- plotly/src/common/color.rs | 25 +++++++++++ 3 files changed, 99 insertions(+), 4 deletions(-) diff --git a/examples/3d_charts/Cargo.toml b/examples/3d_charts/Cargo.toml index 21a4f1ce..48058077 100644 --- a/examples/3d_charts/Cargo.toml +++ b/examples/3d_charts/Cargo.toml @@ -6,4 +6,5 @@ edition = "2021" [dependencies] ndarray = "0.15.6" +rand = "0.8.5" plotly = { path = "../../plotly" } diff --git a/examples/3d_charts/src/main.rs b/examples/3d_charts/src/main.rs index 87653b57..e575daf1 100644 --- a/examples/3d_charts/src/main.rs +++ b/examples/3d_charts/src/main.rs @@ -3,10 +3,11 @@ use ndarray::Array; use plotly::{ color::Rgb, - common::{ColorScale, ColorScalePalette, Font, Marker, MarkerSymbol, Mode, Title}, + common::{ColorBar, ColorScale, ColorScalePalette, Font, Marker, MarkerSymbol, Mode, Title}, layout::{Axis, Camera, Layout, LayoutScene, Legend, Margin, ProjectionType}, Mesh3D, Plot, Scatter3D, Surface, }; +use rand::Rng; // 3D Scatter Plots fn simple_scatter3d_plot() { @@ -41,10 +42,11 @@ fn customized_scatter3d_plot() { .map(|i| (i.abs() * 25f64) as usize) .collect(), ) - .color_scale(ColorScale::Palette(ColorScalePalette::Viridis)), + .color_scale(ColorScale::Palette(ColorScalePalette::Viridis)) + .color_array(z.clone()), ); - let trace2 = Scatter3D::new(t, z, y) + let trace2 = Scatter3D::new(t, z.clone(), y) .name("Helix 2") .mode(Mode::Markers) .marker( @@ -55,7 +57,8 @@ fn customized_scatter3d_plot() { .map(|i| (i.abs() * 25f64) as usize) .collect(), ) - .color_scale(ColorScale::Palette(ColorScalePalette::Viridis)), + .color_scale(ColorScale::Palette(ColorScalePalette::Viridis)) + .color_array(z), ); let mut plot = Plot::new(); @@ -161,6 +164,71 @@ fn mesh_3d_plot() { plot.show(); } +fn colorscale_plot() { + let mut plot = Plot::new(); + + let x = (0..100) + .map(|x| ((x - 50) as f64) / 100f64) + .collect::>(); + + let y = x.clone(); + + let iproduct = |x: &[f64], y: &[f64]| -> Vec<(f64, f64)> { + let mut result = Vec::new(); + for x in x { + for y in y { + result.push((*x, *y)); + } + } + result + }; + + let ((x, y), z): ((Vec, Vec), Vec) = iproduct(&x, &y) + .into_iter() + .map(|(x, y)| ((x, y), -(x.powi(2) + y.powi(2)) + 0.5)) + .unzip(); + + let color: Vec = z.clone().into_iter().rev().map(|x| x as f32).collect(); + let _color: Vec = (0..z.len()).collect(); + let _color: Vec = (0..z.len()).map(|x| x as u8).collect(); + let _color: Vec = { + let mut rng = rand::thread_rng(); + (0..z.len()).map(|_| rng.gen_range(0..100)).collect() + }; + + let color_max = color.iter().fold(f64::MIN, |acc, x| acc.max(*x as f64)); + + let colorscale = ColorScalePalette::YlGnBu; + + let marker = Marker::new() + .color_array(color) + .color_scale(plotly::common::ColorScale::Palette(colorscale.clone())) + .cauto(false) + .cmax(color_max * 1.5) + .color_bar(ColorBar::new()); + + let scatter = Scatter3D::new(x, y, z).mode(Mode::Markers).marker(marker); + + plot.add_trace(scatter); + + let layout = Layout::new() + .font(Font::new().size(18).family("Palatino-Linotype")) + .title(format!("Colorscale: {colorscale:?}").as_str().into()) + .width(1200) + .height(1000) + .scene( + LayoutScene::new() + .aspect_mode(plotly::layout::AspectMode::Data) + .x_axis(Axis::new().tick_format(".1f")) + .y_axis(Axis::new().tick_format(".1f")) + .z_axis(Axis::new().tick_format(".1f")), + ); + + plot.set_layout(layout); + + plot.show(); +} + fn main() { // Uncomment any of these lines to display the example. @@ -168,6 +236,7 @@ fn main() { // simple_scatter3d_plot(); // simple_line3d_plot(); // customized_scatter3d_plot(); + // colorscale_plot(); // Surface Plots // surface_plot(); diff --git a/plotly/src/common/color.rs b/plotly/src/common/color.rs index 06121ef8..1d7a03af 100644 --- a/plotly/src/common/color.rs +++ b/plotly/src/common/color.rs @@ -33,6 +33,17 @@ impl Color for &'static str {} impl Color for String {} impl Color for Rgb {} impl Color for Rgba {} +impl Color for f64 {} +impl Color for f32 {} +impl Color for u64 {} +impl Color for u32 {} +impl Color for u16 {} +impl Color for u8 {} +impl Color for i64 {} +impl Color for i32 {} +impl Color for i16 {} +impl Color for i8 {} +impl Color for usize {} /// ColorArray is only used internally to provide a helper method for converting /// Vec to Vec>, as we would otherwise fall foul of @@ -290,6 +301,20 @@ mod tests { assert_eq!(to_value(color).unwrap(), json!("any_arbitrary_string")); } + #[test] + fn test_serialize_numbers() { + assert_eq!(to_value(1f64).unwrap(), json!(1f64)); + assert_eq!(to_value(1f32).unwrap(), json!(1f32)); + assert_eq!(to_value(1i64).unwrap(), json!(1i64)); + assert_eq!(to_value(1i32).unwrap(), json!(1i32)); + assert_eq!(to_value(1i16).unwrap(), json!(1i16)); + assert_eq!(to_value(1i8).unwrap(), json!(1i8)); + assert_eq!(to_value(1u64).unwrap(), json!(1u64)); + assert_eq!(to_value(1u32).unwrap(), json!(1u32)); + assert_eq!(to_value(1u16).unwrap(), json!(1u16)); + assert_eq!(to_value(1u8).unwrap(), json!(1u8)); + } + #[test] #[rustfmt::skip] fn test_serialize_named_color() { From a6302eac42b93fad89ee74a714ea6d3bea4b4603 Mon Sep 17 00:00:00 2001 From: Tectin <94180412+tectin0@users.noreply.github.com> Date: Thu, 20 Jun 2024 11:06:36 +0200 Subject: [PATCH 37/39] changed the expected type for `HeatMap.z` from `Option>` to `Option>>` (#157) * changed the HeatMap `zmin, zmax` and `zmid` setters to take `f64` arguments - with `Vec>` as an input for `HeatMap.z` it infers that `Z` has the type `Vec` which breaks the setter for `zmin`, `zmax` and `zmid` . The take scalar types and should be inferred as `T` * added `customized_heat_map` function to showcase the working `zmin` and `zmax` * updated tests and example Signed-off-by: Andrei Gherghescu <8067229+andrei-ng@users.noreply.github.com> --------- Signed-off-by: Andrei Gherghescu <8067229+andrei-ng@users.noreply.github.com> Co-authored-by: Andrei Gherghescu <8067229+andrei-ng@users.noreply.github.com> --- examples/scientific_charts/src/main.rs | 52 ++++++++++++++--- plotly/src/traces/heat_map.rs | 78 ++++++++++++++------------ 2 files changed, 86 insertions(+), 44 deletions(-) diff --git a/examples/scientific_charts/src/main.rs b/examples/scientific_charts/src/main.rs index 20d98a94..34ace161 100644 --- a/examples/scientific_charts/src/main.rs +++ b/examples/scientific_charts/src/main.rs @@ -2,7 +2,7 @@ use std::f64::consts::PI; -use plotly::common::{ColorScale, ColorScalePalette, Title}; +use plotly::common::{ColorScale, ColorScalePalette, Font, Title}; use plotly::contour::Contours; use plotly::{Contour, HeatMap, Layout, Plot}; @@ -102,22 +102,60 @@ fn customizing_spacing_between_x_and_y_ticks() { // Heatmaps fn basic_heat_map() { let z = vec![vec![1, 20, 30], vec![20, 1, 60], vec![30, 60, 1]]; - let trace = HeatMap::new_z(z); + let trace = HeatMap::new_z(z).zmin(1.0).zmax(60.0); let mut plot = Plot::new(); plot.add_trace(trace); plot.show(); } +fn customized_heat_map() { + let x = (0..100).map(|x| x as f64).collect::>(); + let y = (0..100).map(|y| y as f64).collect::>(); + let z: Vec> = x + .iter() + .map(|x| { + y.iter() + .map(|y| (x / 5.0).powf(2.0) + (y / 5.0).powf(2.0)) + .collect::>() + }) + .collect::>>(); + + let (_z_min, z_max) = z + .iter() + .flatten() + .fold((f64::MAX, f64::MIN), |(min, max), &x| { + (min.min(x), max.max(x)) + }); + + let colorscale = ColorScalePalette::Jet; + + let trace = HeatMap::new(x, y, z) + .zmin(z_max * 0.4) + .zmax(z_max * 0.5) + .color_scale(colorscale.into()); + + let layout = Layout::new() + .title(Title::new("Customized Heatmap")) + .font(Font::new().size(32)); + + let mut plot = Plot::new(); + plot.set_layout(layout); + plot.add_trace(trace); + + plot.show(); +} + fn main() { // Uncomment any of these lines to display the example. // Contour Plots - simple_contour_plot(); - colorscale_for_contour_plot(); - customizing_size_and_range_of_a_contour_plots_contours(); - customizing_spacing_between_x_and_y_ticks(); + // simple_contour_plot(); + // colorscale_for_contour_plot(); + // customizing_size_and_range_of_a_contour_plots_contours(); + // customizing_spacing_between_x_and_y_ticks(); // Heatmaps - basic_heat_map(); + // basic_heat_map(); + // customized_heat_map(); } diff --git a/plotly/src/traces/heat_map.rs b/plotly/src/traces/heat_map.rs index 151b6941..07c216ed 100644 --- a/plotly/src/traces/heat_map.rs +++ b/plotly/src/traces/heat_map.rs @@ -110,9 +110,9 @@ where zauto: Option, #[serde(rename = "zhoverformat")] zhover_format: Option, - zmax: Option, - zmid: Option, - zmin: Option, + zmax: Option, + zmid: Option, + zmin: Option, zsmooth: Option, } @@ -179,10 +179,10 @@ mod tests { #[test] fn test_serialize_heat_map_z() { - let trace = HeatMap::new_z(vec![1.0]); + let trace = HeatMap::new_z(vec![vec![1.0]]); let expected = json!({ "type": "heatmap", - "z": [1.0], + "z": [[1.0]], }); assert_eq!(to_value(trace).unwrap(), expected); @@ -190,37 +190,41 @@ mod tests { #[test] fn test_serialize_heat_map() { - let trace = HeatMap::new(vec![0.0, 1.0], vec![2.0, 3.0], vec![4.0, 5.0]) - .auto_color_scale(true) - .color_bar(ColorBar::new()) - .color_scale(ColorScale::Palette(ColorScalePalette::Picnic)) - .connect_gaps(false) - .hover_info(HoverInfo::None) - .hover_label(Label::new()) - .hover_on_gaps(true) - .hover_template("tmpl") - .hover_template_array(vec!["tmpl1", "tmpl2"]) - .hover_text(vec!["hov", "er"]) - .legend_group("1") - .legend_group_title(LegendGroupTitle::new("Legend Group Title")) - .name("name") - .opacity(0.99) - .reverse_scale(false) - .show_legend(true) - .show_scale(false) - .text(vec!["te", "xt"]) - .transpose(true) - .visible(Visible::LegendOnly) - .x_axis("x") - .x_calendar(Calendar::Hebrew) - .y_axis("y") - .y_calendar(Calendar::Islamic) - .zauto(true) - .zhover_format("fmt") - .zmax(10.0) - .zmid(5.0) - .zmin(0.0) - .zsmooth(Smoothing::Fast); + let trace = HeatMap::new( + vec![0.0, 1.0], + vec![2.0, 3.0], + vec![vec![4.0, 5.0], vec![6.0, 7.0]], + ) + .auto_color_scale(true) + .color_bar(ColorBar::new()) + .color_scale(ColorScale::Palette(ColorScalePalette::Picnic)) + .connect_gaps(false) + .hover_info(HoverInfo::None) + .hover_label(Label::new()) + .hover_on_gaps(true) + .hover_template("tmpl") + .hover_template_array(vec!["tmpl1", "tmpl2"]) + .hover_text(vec!["hov", "er"]) + .legend_group("1") + .legend_group_title(LegendGroupTitle::new("Legend Group Title")) + .name("name") + .opacity(0.99) + .reverse_scale(false) + .show_legend(true) + .show_scale(false) + .text(vec!["te", "xt"]) + .transpose(true) + .visible(Visible::LegendOnly) + .x_axis("x") + .x_calendar(Calendar::Hebrew) + .y_axis("y") + .y_calendar(Calendar::Islamic) + .zauto(true) + .zhover_format("fmt") + .zmax(10.0) + .zmid(5.0) + .zmin(0.0) + .zsmooth(Smoothing::Fast); let expected = json!({ "type": "heatmap", @@ -249,7 +253,7 @@ mod tests { "y": [2.0, 3.0], "yaxis": "y", "ycalendar": "islamic", - "z": [4.0, 5.0], + "z": [[4.0, 5.0], [6.0, 7.0]], "zauto": true, "zhoverformat": "fmt", "zmax": 10.0, From 13a8971ccc0d23f4581edb979f515af5307845bb Mon Sep 17 00:00:00 2001 From: Filip T Date: Tue, 25 Jun 2024 23:41:44 +0200 Subject: [PATCH 38/39] Improve ergonomics of `Title` and `LegendGroupTitle` structs (#154) * Improve ergonomics of LegendGroupTitle method/struct - Add From impl for Title * update changelog * disable spurious kaleido save to file failing tests on MacOS and Windows --------- Co-authored-by: Michael Freeborn Co-authored-by: Andrei Gherghescu <8067229+andrei-ng@users.noreply.github.com> --- CHANGELOG.md | 2 + examples/3d_charts/src/main.rs | 12 ++-- examples/basic_charts/src/main.rs | 24 ++++---- examples/financial_charts/src/main.rs | 6 +- examples/scientific_charts/src/main.rs | 10 +-- examples/shapes/src/main.rs | 2 +- examples/statistical_charts/src/main.rs | 30 +++------ examples/subplots/src/main.rs | 18 +++--- examples/wasm-yew-minimal/src/main.rs | 3 +- plotly/src/common/mod.rs | 82 +++++++++++++++++++++---- plotly/src/layout/mod.rs | 10 +-- plotly/src/layout/themes.rs | 32 ++++++++-- plotly/src/layout/update_menu.rs | 7 +-- plotly/src/plot.rs | 18 +++--- plotly/src/traces/bar.rs | 2 +- plotly/src/traces/box_plot.rs | 2 +- plotly/src/traces/candlestick.rs | 2 +- plotly/src/traces/contour.rs | 9 ++- plotly/src/traces/heat_map.rs | 2 +- plotly/src/traces/histogram.rs | 2 +- plotly/src/traces/image.rs | 2 +- plotly/src/traces/mesh3d.rs | 2 +- plotly/src/traces/ohlc.rs | 4 +- plotly/src/traces/sankey.rs | 2 +- plotly/src/traces/scatter.rs | 2 +- plotly/src/traces/scatter3d.rs | 2 +- plotly/src/traces/scatter_mapbox.rs | 2 +- plotly/src/traces/scatter_polar.rs | 2 +- plotly/src/traces/surface.rs | 2 +- plotly_derive/src/field_setter.rs | 12 ++++ plotly_kaleido/src/lib.rs | 16 +++-- 31 files changed, 207 insertions(+), 116 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index eab1cfc5..0aefb75a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,8 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) a - [[#163](https://github.com/plotly/plotly.rs/pull/163)] Added `DensityMapbox`. - [[#161](https://github.com/plotly/plotly.rs/pull/161)] Added `Axis` `scaleanchor` settter. - [[#159](https://github.com/plotly/plotly.rs/pull/159)] Make `heat_map` module public to expose `Smoothing enum`. +- [[#157](https://github.com/plotly/plotly.rs/pull/157)] Fix `HeatMap`'s setters for correctly setting `zmin`, `zmax` and `zmin` independent of `Z` input type. +- [[#154](https://github.com/plotly/plotly.rs/pull/154)] Improve ergonomics of `Title` and `LegendGroupTitle` structs: `new` method now takes no arguments as per other structs, whilst a new `with_text()` constructor is added for convenience. Where other structs contain a `Title` (and `LegendGroupTitle`), users can now call the `title()` (and `legend_group_title()`) method with anything that `impl`s `Into`, viz. `String`, `&String`, `&str` and `Title`. - [[#153](https://github.com/plotly/plotly.rs/pull/153)] Added `LayoutScene`. ## [0.8.4] - 2023-07-09 diff --git a/examples/3d_charts/src/main.rs b/examples/3d_charts/src/main.rs index e575daf1..ed484f73 100644 --- a/examples/3d_charts/src/main.rs +++ b/examples/3d_charts/src/main.rs @@ -3,7 +3,7 @@ use ndarray::Array; use plotly::{ color::Rgb, - common::{ColorBar, ColorScale, ColorScalePalette, Font, Marker, MarkerSymbol, Mode, Title}, + common::{ColorBar, ColorScale, ColorScalePalette, Font, Marker, MarkerSymbol, Mode}, layout::{Axis, Camera, Layout, LayoutScene, Legend, Margin, ProjectionType}, Mesh3D, Plot, Scatter3D, Surface, }; @@ -69,7 +69,7 @@ fn customized_scatter3d_plot() { let front_color: Rgb = Rgb::new(255, 255, 255); let layout = Layout::new() - .title("Helix".into()) + .title("Helix") .legend(Legend::new().x(0.9).y(0.9)) .font(Font::new().color(front_color)) .paper_background_color(background_color) @@ -77,19 +77,19 @@ fn customized_scatter3d_plot() { LayoutScene::new() .x_axis( Axis::new() - .title("x (A meaningful axis name goes here)".into()) + .title("x (A meaningful axis name goes here)") .tick_angle(0f64) .grid_color(front_color) .color(front_color), ) .y_axis( Axis::new() - .title(Title::new("This is the label of the Y axis")) + .title("This is the label of the Y axis") .tick_format(".1f") .grid_color(front_color) .color(front_color), ) - .z_axis(Axis::new().title("".into()).tick_values(vec![])) + .z_axis(Axis::new().title("").tick_values(vec![])) .aspect_mode(plotly::layout::AspectMode::Manual) .aspect_ratio((3.0, 1.0, 1.0).into()) .camera( @@ -213,7 +213,7 @@ fn colorscale_plot() { let layout = Layout::new() .font(Font::new().size(18).family("Palatino-Linotype")) - .title(format!("Colorscale: {colorscale:?}").as_str().into()) + .title(format!("Colorscale: {colorscale:?}")) .width(1200) .height(1000) .scene( diff --git a/examples/basic_charts/src/main.rs b/examples/basic_charts/src/main.rs index 9408c755..14f31adb 100644 --- a/examples/basic_charts/src/main.rs +++ b/examples/basic_charts/src/main.rs @@ -5,7 +5,7 @@ use plotly::{ color::{NamedColor, Rgb, Rgba}, common::{ ColorScale, ColorScalePalette, DashType, Fill, Font, Line, LineShape, Marker, Mode, - Orientation, Title, + Orientation, }, layout::{Axis, BarMode, Layout, Legend, TicksDirection, TraceOrder}, sankey::{Line as SankeyLine, Link, Node}, @@ -118,9 +118,9 @@ fn data_labels_hover() { plot.add_trace(trace2); let layout = Layout::new() - .title("Data Labels Hover".into()) - .x_axis(Axis::new().title("x".into()).range(vec![0.75, 5.25])) - .y_axis(Axis::new().title("y".into()).range(vec![0., 8.])); + .title("Data Labels Hover") + .x_axis(Axis::new().title("x").range(vec![0.75, 5.25])) + .y_axis(Axis::new().title("y").range(vec![0., 8.])); plot.set_layout(layout); plot.show(); @@ -143,7 +143,7 @@ fn data_labels_on_the_plot() { plot.add_trace(trace2); let layout = Layout::new() - .title("Data Labels on the Plot".into()) + .title("Data Labels on the Plot") .x_axis(Axis::new().range(vec![0.75, 5.25])) .y_axis(Axis::new().range(vec![0., 8.])); plot.set_layout(layout); @@ -216,14 +216,14 @@ fn colored_and_styled_scatter_plot() { .marker(Marker::new().color(Rgb::new(142, 124, 195)).size(12)); let layout = Layout::new() - .title(Title::new("Quarter 1 Growth")) + .title("Quarter 1 Growth") .x_axis( Axis::new() - .title(Title::new("GDP per Capita")) + .title("GDP per Capita") .show_grid(false) .zero_line(false), ) - .y_axis(Axis::new().title(Title::new("Percent")).show_line(false)); + .y_axis(Axis::new().title("Percent").show_line(false)); let mut plot = Plot::new(); plot.add_trace(trace1); plot.add_trace(trace2); @@ -280,7 +280,7 @@ fn adding_names_to_line_and_scatter_plot() { .mode(Mode::LinesMarkers) .name("Scatter + Lines"); - let layout = Layout::new().title(Title::new("Adding Names to Line and Scatter Plot")); + let layout = Layout::new().title("Adding Names to Line and Scatter Plot"); let mut plot = Plot::new(); plot.add_trace(trace1); plot.add_trace(trace2); @@ -305,7 +305,7 @@ fn line_and_scatter_styling() { .marker(Marker::new().color(Rgb::new(128, 0, 128)).size(12)) .line(Line::new().color(Rgb::new(128, 0, 128)).width(1.0)); - let layout = Layout::new().title(Title::new("Line and Scatter Styling")); + let layout = Layout::new().title("Line and Scatter Styling"); let mut plot = Plot::new(); plot.add_trace(trace1); plot.add_trace(trace2); @@ -326,7 +326,7 @@ fn styling_line_plot() { .line(Line::new().color(Rgb::new(55, 128, 191)).width(1.0)); let layout = Layout::new() - .title(Title::new("Styling Line Plot")) + .title("Styling Line Plot") .width(500) .height(500); let mut plot = Plot::new(); @@ -595,7 +595,7 @@ fn basic_sankey_diagram() { ); let layout = Layout::new() - .title("Basic Sankey".into()) + .title("Basic Sankey") .font(Font::new().size(10)); let mut plot = Plot::new(); diff --git a/examples/financial_charts/src/main.rs b/examples/financial_charts/src/main.rs index 2805482b..1473699e 100644 --- a/examples/financial_charts/src/main.rs +++ b/examples/financial_charts/src/main.rs @@ -3,7 +3,7 @@ use std::env; use std::path::PathBuf; -use plotly::common::{TickFormatStop, Title}; +use plotly::common::TickFormatStop; use plotly::layout::{Axis, RangeSelector, RangeSlider, SelectorButton, SelectorStep, StepMode}; use plotly::{Candlestick, Layout, Ohlc, Plot, Scatter}; use serde::Deserialize; @@ -50,7 +50,7 @@ fn time_series_plot_with_custom_date_range() { let layout = Layout::new() .x_axis(Axis::new().range(vec!["2016-07-01", "2016-12-31"])) - .title(Title::new("Manually Set Date Range")); + .title("Manually Set Date Range"); plot.set_layout(layout); plot.show(); @@ -68,7 +68,7 @@ fn time_series_with_range_slider() { let layout = Layout::new() .x_axis(Axis::new().range_slider(RangeSlider::new().visible(true))) - .title(Title::new("Manually Set Date Range")); + .title("Manually Set Date Range"); plot.set_layout(layout); plot.show(); diff --git a/examples/scientific_charts/src/main.rs b/examples/scientific_charts/src/main.rs index 34ace161..bea229e2 100644 --- a/examples/scientific_charts/src/main.rs +++ b/examples/scientific_charts/src/main.rs @@ -2,7 +2,7 @@ use std::f64::consts::PI; -use plotly::common::{ColorScale, ColorScalePalette, Font, Title}; +use plotly::common::{ColorScale, ColorScalePalette, Font}; use plotly::contour::Contours; use plotly::{Contour, HeatMap, Layout, Plot}; @@ -47,7 +47,7 @@ fn colorscale_for_contour_plot() { ]; let trace = Contour::new_z(z).color_scale(ColorScale::Palette(ColorScalePalette::Jet)); - let layout = Layout::new().title(Title::new("Colorscale for Contour Plot")); + let layout = Layout::new().title("Colorscale for Contour Plot"); let mut plot = Plot::new(); plot.set_layout(layout); plot.add_trace(trace); @@ -68,7 +68,7 @@ fn customizing_size_and_range_of_a_contour_plots_contours() { .auto_contour(false) .contours(Contours::new().start(0.0).end(8.0).size(2)); - let layout = Layout::new().title(Title::new("Customizing Size and Range of Contours")); + let layout = Layout::new().title("Customizing Size and Range of Contours"); let mut plot = Plot::new(); plot.set_layout(layout); plot.add_trace(trace); @@ -91,7 +91,7 @@ fn customizing_spacing_between_x_and_y_ticks() { .dy(10.0) .y0(10.0); - let layout = Layout::new().title(Title::new("Customizing Size and Range of Contours")); + let layout = Layout::new().title("Customizing Size and Range of Contours"); let mut plot = Plot::new(); plot.set_layout(layout); plot.add_trace(trace); @@ -136,7 +136,7 @@ fn customized_heat_map() { .color_scale(colorscale.into()); let layout = Layout::new() - .title(Title::new("Customized Heatmap")) + .title("Customized Heatmap") .font(Font::new().size(32)); let mut plot = Plot::new(); diff --git a/examples/shapes/src/main.rs b/examples/shapes/src/main.rs index 871986d1..84eaafc0 100644 --- a/examples/shapes/src/main.rs +++ b/examples/shapes/src/main.rs @@ -138,7 +138,7 @@ fn creating_tangent_lines_with_shapes() { plot.add_trace(trace); let mut layout = - Layout::new().title("$f(x)=x\\sin(x^2)+1\\\\ f\'(x)=\\sin(x^2)+2x^2\\cos(x^2)$".into()); + Layout::new().title("$f(x)=x\\sin(x^2)+1\\\\ f\'(x)=\\sin(x^2)+2x^2\\cos(x^2)$"); layout.add_shape( Shape::new() diff --git a/examples/statistical_charts/src/main.rs b/examples/statistical_charts/src/main.rs index b8c83d34..f1c00633 100644 --- a/examples/statistical_charts/src/main.rs +++ b/examples/statistical_charts/src/main.rs @@ -4,7 +4,7 @@ use ndarray::Array; use plotly::{ box_plot::{BoxMean, BoxPoints}, color::{NamedColor, Rgb, Rgba}, - common::{ErrorData, ErrorType, Line, Marker, Mode, Orientation, Title}, + common::{ErrorData, ErrorType, Line, Marker, Mode, Orientation}, histogram::{Bins, Cumulative, HistFunc, HistNorm}, layout::{Axis, BarMode, BoxMode, Layout, Margin}, Bar, BoxPlot, Histogram, Plot, Scatter, @@ -203,11 +203,7 @@ fn grouped_box_plot() { plot.add_trace(trace3); let layout = Layout::new() - .y_axis( - Axis::new() - .title(Title::new("normalized moisture")) - .zero_line(false), - ) + .y_axis(Axis::new().title("normalized moisture").zero_line(false)) .box_mode(BoxMode::Group); plot.set_layout(layout); @@ -248,7 +244,7 @@ fn box_plot_styling_outliers() { .marker(Marker::new().color(Rgb::new(107, 174, 214))) .box_points(BoxPoints::Outliers); - let layout = Layout::new().title(Title::new("Box Plot Styling Outliers")); + let layout = Layout::new().title("Box Plot Styling Outliers"); let mut plot = Plot::new(); plot.set_layout(layout); @@ -274,7 +270,7 @@ fn box_plot_styling_mean_and_standard_deviation() { .name("Mean and Standard Deviation") .marker(Marker::new().color(Rgb::new(8, 81, 156))) .box_mean(BoxMean::StandardDeviation); - let layout = Layout::new().title(Title::new("Box Plot Styling Mean and Standard Deviation")); + let layout = Layout::new().title("Box Plot Styling Mean and Standard Deviation"); let mut plot = Plot::new(); plot.set_layout(layout); @@ -321,12 +317,8 @@ fn grouped_horizontal_box_plot() { plot.add_trace(trace3); let layout = Layout::new() - .title(Title::new("Grouped Horizontal Box Plot")) - .x_axis( - Axis::new() - .title(Title::new("normalized moisture")) - .zero_line(false), - ) + .title("Grouped Horizontal Box Plot") + .x_axis(Axis::new().title("normalized moisture").zero_line(false)) .box_mode(BoxMode::Group); plot.set_layout(layout); @@ -370,9 +362,7 @@ fn fully_styled_box_plot() { let mut plot = Plot::new(); let layout = Layout::new() - .title(Title::new( - "Points Scored by the Top 9 Scoring NBA Players in 2012", - )) + .title("Points Scored by the Top 9 Scoring NBA Players in 2012") .y_axis( Axis::new() .auto_range(true) @@ -522,9 +512,9 @@ fn colored_and_styled_histograms() { .auto_bin_x(false) .x_bins(Bins::new(-3.2, 4.0, 0.06)); let layout = Layout::new() - .title(Title::new("Colored and Styled Histograms")) - .x_axis(Axis::new().title(Title::new("Value"))) - .y_axis(Axis::new().title(Title::new("Count"))) + .title("Colored and Styled Histograms") + .x_axis(Axis::new().title("Value")) + .y_axis(Axis::new().title("Count")) .bar_mode(BarMode::Overlay) .bar_gap(0.05) .bar_group_gap(0.2); diff --git a/examples/subplots/src/main.rs b/examples/subplots/src/main.rs index d96616a0..c78bde5a 100644 --- a/examples/subplots/src/main.rs +++ b/examples/subplots/src/main.rs @@ -194,7 +194,7 @@ fn multiple_custom_sized_subplots() { plot.add_trace(trace4); let layout = Layout::new() - .title(Title::new("Multiple Custom Sized Subplots")) + .title("Multiple Custom Sized Subplots") .x_axis(Axis::new().domain(&[0., 0.45]).anchor("y1")) .y_axis(Axis::new().domain(&[0.5, 1.]).anchor("x1")) .x_axis2(Axis::new().domain(&[0.55, 1.]).anchor("y2")) @@ -220,11 +220,11 @@ fn two_y_axes() { plot.add_trace(trace2); let layout = Layout::new() - .title(Title::new("Double Y Axis Example")) - .y_axis(Axis::new().title(Title::new("yaxis title"))) + .title("Double Y Axis Example") + .y_axis(Axis::new().title("yaxis title")) .y_axis2( Axis::new() - .title(Title::new("yaxis2 title").font(Font::new().color(Rgb::new(148, 103, 189)))) + .title(Title::from("yaxis2 title").font(Font::new().color(Rgb::new(148, 103, 189)))) .tick_font(Font::new().color(Rgb::new(148, 103, 189))) .overlaying("y") .side(AxisSide::Right), @@ -249,17 +249,17 @@ fn multiple_axes() { plot.add_trace(trace4); let layout = Layout::new() - .title(Title::new("multiple y-axes example")) + .title("multiple y-axes example") .width(800) .x_axis(Axis::new().domain(&[0.3, 0.7])) .y_axis( Axis::new() - .title(Title::new("yaxis title").font(Font::new().color("#1f77b4"))) + .title(Title::from("yaxis title").font(Font::new().color("#1f77b4"))) .tick_font(Font::new().color("#1f77b4")), ) .y_axis2( Axis::new() - .title(Title::new("yaxis2 title").font(Font::new().color("#ff7f0e"))) + .title(Title::from("yaxis2 title").font(Font::new().color("#ff7f0e"))) .tick_font(Font::new().color("#ff7f0e")) .anchor("free") .overlaying("y") @@ -268,7 +268,7 @@ fn multiple_axes() { ) .y_axis3( Axis::new() - .title(Title::new("yaxis3 title").font(Font::new().color("#d62728"))) + .title(Title::from("yaxis3 title").font(Font::new().color("#d62728"))) .tick_font(Font::new().color("#d62728")) .anchor("x") .overlaying("y") @@ -276,7 +276,7 @@ fn multiple_axes() { ) .y_axis4( Axis::new() - .title(Title::new("yaxis4 title").font(Font::new().color("#9467bd"))) + .title(Title::from("yaxis4 title").font(Font::new().color("#9467bd"))) .tick_font(Font::new().color("#9467bd")) .anchor("free") .overlaying("y") diff --git a/examples/wasm-yew-minimal/src/main.rs b/examples/wasm-yew-minimal/src/main.rs index f38ab848..cb0fb2bc 100644 --- a/examples/wasm-yew-minimal/src/main.rs +++ b/examples/wasm-yew-minimal/src/main.rs @@ -9,8 +9,7 @@ pub fn plot_component() -> Html { let trace = Scatter::new(vec![0, 1, 2], vec![2, 1, 0]); plot.add_trace(trace); - let layout = - plotly::Layout::new().title(plotly::common::Title::new("Displaying a Chart in Yew")); + let layout = plotly::Layout::new().title("Displaying a Chart in Yew"); plot.set_layout(layout); async move { diff --git a/plotly/src/common/mod.rs b/plotly/src/common/mod.rs index 4777afb5..74956fa2 100644 --- a/plotly/src/common/mod.rs +++ b/plotly/src/common/mod.rs @@ -58,14 +58,36 @@ pub enum HoverInfo { #[serde_with::skip_serializing_none] #[derive(Serialize, Clone, Debug, Default)] pub struct LegendGroupTitle { - text: String, + text: Option<String>, font: Option<Font>, } +impl From<&str> for LegendGroupTitle { + fn from(title: &str) -> Self { + LegendGroupTitle::with_text(title) + } +} + +impl From<String> for LegendGroupTitle { + fn from(value: String) -> Self { + LegendGroupTitle::with_text(value) + } +} + +impl From<&String> for LegendGroupTitle { + fn from(value: &String) -> Self { + LegendGroupTitle::with_text(value) + } +} + impl LegendGroupTitle { - pub fn new(text: &str) -> Self { - Self { - text: text.to_string(), + pub fn new() -> Self { + Default::default() + } + + pub fn with_text<S: Into<String>>(text: S) -> Self { + LegendGroupTitle { + text: Some(text.into()), ..Default::default() } } @@ -976,8 +998,8 @@ impl ColorBar { self } - pub fn title(mut self, title: Title) -> Self { - self.title = Some(title); + pub fn title<T: Into<Title>>(mut self, title: T) -> Self { + self.title = Some(title.into()); self } @@ -1235,7 +1257,7 @@ impl Pad { #[serde_with::skip_serializing_none] #[derive(Serialize, Clone, Debug, Default)] pub struct Title { - text: String, + text: Option<String>, font: Option<Font>, side: Option<Side>, #[serde(rename = "xref")] @@ -1253,14 +1275,30 @@ pub struct Title { impl From<&str> for Title { fn from(title: &str) -> Self { - Title::new(title) + Title::with_text(title) + } +} + +impl From<String> for Title { + fn from(value: String) -> Self { + Title::with_text(value) + } +} + +impl From<&String> for Title { + fn from(value: &String) -> Self { + Title::with_text(value) } } impl Title { - pub fn new(text: &str) -> Self { + pub fn new() -> Self { + Default::default() + } + + pub fn with_text<S: Into<String>>(text: S) -> Self { Title { - text: text.to_owned(), + text: Some(text.into()), ..Default::default() } } @@ -1694,7 +1732,7 @@ mod tests { .tick_width(55) .tick0(0.0) .ticks(Ticks::Outside) - .title(Title::new("title")) + .title(Title::new()) .x(5.0) .x_anchor(Anchor::Bottom) .x_pad(2.2) @@ -1735,7 +1773,7 @@ mod tests { "tickwidth": 55, "tick0": 0.0, "ticks": "outside", - "title": {"text": "title"}, + "title": {}, "x": 5.0, "xanchor": "bottom", "xpad": 2.2, @@ -2172,6 +2210,15 @@ mod tests { assert_eq!(to_value(Reference::Paper).unwrap(), json!("paper")); } + #[test] + #[rustfmt::skip] + fn test_serialize_legend_group_title() { + assert_eq!(to_value(LegendGroupTitle::new()).unwrap(), json!({})); + assert_eq!(to_value(LegendGroupTitle::with_text("title_str").font(Font::default())).unwrap(), json!({"font": {}, "text": "title_str"})); + assert_eq!(to_value(LegendGroupTitle::from(String::from("title_string"))).unwrap(), json!({"text" : "title_string"})); + assert_eq!(to_value(LegendGroupTitle::from(&String::from("title_string"))).unwrap(), json!({"text" : "title_string"})); + } + #[test] fn test_serialize_pad() { let pad = Pad::new(1, 2, 3); @@ -2186,7 +2233,7 @@ mod tests { #[test] fn test_serialize_title() { - let title = Title::new("title") + let title = Title::with_text("title") .font(Font::new()) .side(Side::Top) .x_ref(Reference::Paper) @@ -2307,4 +2354,13 @@ mod tests { assert_eq!(to_value(HoverOn::PointsAndFills).unwrap(), json!("points+fills")); } + + #[test] + #[allow(clippy::needless_borrows_for_generic_args)] + fn test_title_method_can_take_string() { + ColorBar::new().title("Title"); + ColorBar::new().title(String::from("Title")); + ColorBar::new().title(&String::from("Title")); + ColorBar::new().title(Title::with_text("Title")); + } } diff --git a/plotly/src/layout/mod.rs b/plotly/src/layout/mod.rs index d0d53f8d..7a70c23e 100644 --- a/plotly/src/layout/mod.rs +++ b/plotly/src/layout/mod.rs @@ -2180,7 +2180,7 @@ mod tests { .y(2.0) .y_anchor(Anchor::Left) .valign(VAlign::Middle) - .title(Title::new("title")) + .title("title") .group_click(GroupClick::ToggleItem) .item_width(50); @@ -2430,7 +2430,7 @@ mod tests { let axis = Axis::new() .visible(false) .color("#678123") - .title(Title::new("title")) + .title(Title::with_text("title")) .type_(AxisType::Date) .auto_range(false) .range_mode(RangeMode::NonNegative) @@ -2962,7 +2962,7 @@ mod tests { #[test] fn test_serialize_layout_template() { let layout_template = LayoutTemplate::new() - .title("Title".into()) + .title("Title") .show_legend(false) .legend(Legend::new()) .margin(Margin::new()) @@ -3104,7 +3104,9 @@ mod tests { #[test] fn test_serialize_layout() { let layout = Layout::new() - .title("Title".into()) + .title("Title") + .title(String::from("Title")) + .title(Title::with_text("Title")) .show_legend(false) .legend(Legend::new()) .margin(Margin::new()) diff --git a/plotly/src/layout/themes.rs b/plotly/src/layout/themes.rs index a4fb2774..a687caa7 100644 --- a/plotly/src/layout/themes.rs +++ b/plotly/src/layout/themes.rs @@ -62,7 +62,7 @@ pub static PLOTLY_WHITE: Lazy<Template> = Lazy::new(|| { .hover_mode(HoverMode::Closest) .paper_background_color("#ffffff") .plot_background_color("#ffffff") - .title(Title::new("").x(0.05)) + .title(Title::new().x(0.05)) .x_axis( Axis::new() .auto_margin(true) @@ -138,7 +138,7 @@ pub static PLOTLY_DARK: Lazy<Template> = Lazy::new(|| { .hover_mode(HoverMode::Closest) .paper_background_color("#111111") .plot_background_color("#111111") - .title(Title::new("").x(0.05)) + .title(Title::new().x(0.05)) .x_axis( Axis::new() .auto_margin(true) @@ -165,6 +165,31 @@ mod tests { use super::*; use crate::*; + #[test] + fn test_plotly_default() { + let template = &*DEFAULT; + let layout = Layout::new().template(template); + let mut plot = Plot::new(); + plot.set_layout(layout); + plot.add_trace(Bar::new(vec![0], vec![1])); + + let expected = r##"{"template":{"layout":{}}}"##; // etc... + assert!(plot.to_json().contains(expected)); + } + + #[test] + fn test_plotly_white() { + let template = &*PLOTLY_WHITE; + let layout = Layout::new().template(template); + let mut plot = Plot::new(); + plot.set_layout(layout); + plot.add_trace(Bar::new(vec![0], vec![1])); + dbg!(plot.to_json()); + + let expected = r##"{"template":{"layout":{"title":{"x":0.05},"font":{"color":"#2a3f5f"}"##; // etc... + assert!(plot.to_json().contains(expected)); + } + #[test] fn test_plotly_dark() { let template = &*PLOTLY_DARK; @@ -173,8 +198,7 @@ mod tests { plot.set_layout(layout); plot.add_trace(Bar::new(vec![0], vec![1])); - let expected = - r##"{"template":{"layout":{"title":{"text":"","x":0.05},"font":{"color":"#f2f5fa"}"##; // etc... + let expected = r##"{"template":{"layout":{"title":{"x":0.05},"font":{"color":"#f2f5fa"}"##; // etc... assert!(plot.to_json().contains(expected)); } } diff --git a/plotly/src/layout/update_menu.rs b/plotly/src/layout/update_menu.rs index eea463f0..f662a7f2 100644 --- a/plotly/src/layout/update_menu.rs +++ b/plotly/src/layout/update_menu.rs @@ -246,10 +246,7 @@ mod tests { use serde_json::{json, to_value}; use super::*; - use crate::{ - common::{Title, Visible}, - Layout, - }; + use crate::{common::Visible, Layout}; #[test] fn test_serialize_button_method() { @@ -315,7 +312,7 @@ mod tests { Visible::True, Visible::False, ])) - .push_relayout(Layout::modify_title(Title::new("Hello"))) + .push_relayout(Layout::modify_title("Hello")) .push_relayout(Layout::modify_width(20)) .build(); diff --git a/plotly/src/plot.rs b/plotly/src/plot.rs index 03fe4ae0..d02fe92d 100644 --- a/plotly/src/plot.rs +++ b/plotly/src/plot.rs @@ -161,7 +161,7 @@ impl Traces { /// plot.add_trace(trace2); /// plot.add_trace(trace3); /// -/// let layout = Layout::new().title("<b>Line and Scatter Plot</b>".into()); +/// let layout = Layout::new().title("<b>Line and Scatter Plot</b>"); /// plot.set_layout(layout); /// /// # if false { // We don't actually want to try and display the plot in a browser when running a doctest. @@ -463,7 +463,7 @@ impl Plot { fn show_with_default_app(temp_path: &str) { use std::process::Command; Command::new("open") - .args(&[temp_path]) + .args([temp_path]) .output() .expect(DEFAULT_HTML_APP_NOT_FOUND); } @@ -548,7 +548,7 @@ mod tests { #[test] fn test_plot_serialize_with_layout() { let mut plot = create_test_plot(); - let layout = Layout::new().title("Title".into()); + let layout = Layout::new().title("Title"); plot.set_layout(layout); let expected = json!({ @@ -597,7 +597,7 @@ mod tests { #[test] fn test_layout_to_json() { let mut plot = create_test_plot(); - let layout = Layout::new().title("TestTitle".into()); + let layout = Layout::new().title("TestTitle"); plot.set_layout(layout); let expected = json!({ @@ -651,7 +651,7 @@ mod tests { assert!(!dst.exists()); } - #[cfg(not(target_os = "windows"))] + #[cfg(target_os = "linux")] #[test] #[cfg(feature = "kaleido")] fn test_save_to_png() { @@ -663,7 +663,7 @@ mod tests { assert!(!dst.exists()); } - #[cfg(not(target_os = "windows"))] + #[cfg(target_os = "linux")] #[test] #[cfg(feature = "kaleido")] fn test_save_to_jpeg() { @@ -675,7 +675,7 @@ mod tests { assert!(!dst.exists()); } - #[cfg(not(target_os = "windows"))] + #[cfg(target_os = "linux")] #[test] #[cfg(feature = "kaleido")] fn test_save_to_svg() { @@ -699,7 +699,7 @@ mod tests { assert!(!dst.exists()); } - #[cfg(not(target_os = "windows"))] + #[cfg(target_os = "linux")] #[test] #[cfg(feature = "kaleido")] fn test_save_to_pdf() { @@ -711,7 +711,7 @@ mod tests { assert!(!dst.exists()); } - #[cfg(not(target_os = "windows"))] + #[cfg(target_os = "linux")] #[test] #[cfg(feature = "kaleido")] fn test_save_to_webp() { diff --git a/plotly/src/traces/bar.rs b/plotly/src/traces/bar.rs index 16300ae6..0acaed0d 100644 --- a/plotly/src/traces/bar.rs +++ b/plotly/src/traces/bar.rs @@ -159,7 +159,7 @@ mod tests { .inside_text_anchor(TextAnchor::End) .inside_text_font(Font::new()) .legend_group("legend-group") - .legend_group_title(LegendGroupTitle::new("legend-group-title")) + .legend_group_title("legend-group-title") .marker(Marker::new()) .name("Bar") .offset(5) diff --git a/plotly/src/traces/box_plot.rs b/plotly/src/traces/box_plot.rs index 5b8e9c91..8903c480 100644 --- a/plotly/src/traces/box_plot.rs +++ b/plotly/src/traces/box_plot.rs @@ -283,7 +283,7 @@ mod tests { .jitter(0.5) .line(Line::new()) .legend_group("one") - .legend_group_title(LegendGroupTitle::new("Legend Group Title")) + .legend_group_title("Legend Group Title") .lower_fence(vec![0., 1.]) .marker(Marker::new()) .mean(vec![12., 13.]) diff --git a/plotly/src/traces/candlestick.rs b/plotly/src/traces/candlestick.rs index 2fe6a197..64b25a5b 100644 --- a/plotly/src/traces/candlestick.rs +++ b/plotly/src/traces/candlestick.rs @@ -144,7 +144,7 @@ mod tests { .visible(Visible::True) .show_legend(false) .legend_group("group_1") - .legend_group_title(LegendGroupTitle::new("Legend Group Title")) + .legend_group_title("Legend Group Title") .opacity(0.3) .text_array(vec!["text", "here"]) .text("text here") diff --git a/plotly/src/traces/contour.rs b/plotly/src/traces/contour.rs index 844f55c2..576e58f1 100644 --- a/plotly/src/traces/contour.rs +++ b/plotly/src/traces/contour.rs @@ -339,8 +339,11 @@ where Box::new(self) } - pub fn legend_group_title(mut self, legend_group_title: LegendGroupTitle) -> Box<Self> { - self.legend_group_title = Some(legend_group_title); + pub fn legend_group_title( + mut self, + legend_group_title: impl Into<LegendGroupTitle>, + ) -> Box<Self> { + self.legend_group_title = Some(legend_group_title.into()); Box::new(self) } @@ -583,7 +586,7 @@ mod tests { .hover_template_array(vec!["ok {1}", "ok {2}"]) .hover_text(vec!["p3", "p4"]) .legend_group("group_1") - .legend_group_title(LegendGroupTitle::new("Legend Group Title")) + .legend_group_title("Legend Group Title") .line(Line::new()) .n_contours(5) .name("contour trace") diff --git a/plotly/src/traces/heat_map.rs b/plotly/src/traces/heat_map.rs index 07c216ed..811dcfb6 100644 --- a/plotly/src/traces/heat_map.rs +++ b/plotly/src/traces/heat_map.rs @@ -206,7 +206,7 @@ mod tests { .hover_template_array(vec!["tmpl1", "tmpl2"]) .hover_text(vec!["hov", "er"]) .legend_group("1") - .legend_group_title(LegendGroupTitle::new("Legend Group Title")) + .legend_group_title("Legend Group Title") .name("name") .opacity(0.99) .reverse_scale(false) diff --git a/plotly/src/traces/histogram.rs b/plotly/src/traces/histogram.rs index 7ae6dd59..b4b9b97f 100644 --- a/plotly/src/traces/histogram.rs +++ b/plotly/src/traces/histogram.rs @@ -410,7 +410,7 @@ mod tests { .hover_text("hover_text") .hover_text_array(vec!["hover_text_1", "hover_text_2"]) .legend_group("legendgroup") - .legend_group_title(LegendGroupTitle::new("Legend Group Title")) + .legend_group_title("Legend Group Title") .marker(Marker::new()) .n_bins_x(5) .n_bins_y(10) diff --git a/plotly/src/traces/image.rs b/plotly/src/traces/image.rs index 4efbf0c9..d081f9b4 100644 --- a/plotly/src/traces/image.rs +++ b/plotly/src/traces/image.rs @@ -408,7 +408,7 @@ mod tests { .name("image name") .visible(Visible::True) .legend_rank(1000) - .legend_group_title(LegendGroupTitle::new("Legend Group Title")) + .legend_group_title("Legend Group Title") .opacity(0.5) .ids(vec!["one"]) .x0(0.0) diff --git a/plotly/src/traces/mesh3d.rs b/plotly/src/traces/mesh3d.rs index fae98c9a..fc45d781 100644 --- a/plotly/src/traces/mesh3d.rs +++ b/plotly/src/traces/mesh3d.rs @@ -493,7 +493,7 @@ mod tests { .show_legend(true) .legend_rank(1000) .legend_group("legend_group") - .legend_group_title(LegendGroupTitle::new("Legend Group Title")) + .legend_group_title("Legend Group Title") .opacity(0.5) .ids(vec!["one"]) .face_color(vec!["#ff00ff"]) diff --git a/plotly/src/traces/ohlc.rs b/plotly/src/traces/ohlc.rs index cf1b4e50..7067514f 100644 --- a/plotly/src/traces/ohlc.rs +++ b/plotly/src/traces/ohlc.rs @@ -28,7 +28,7 @@ use crate::{ /// let expected = serde_json::json!({ /// "type": "ohlc", /// "x": ["2022-08-22", "2022-08-23"], -/// "open": [5, 6], +/// "open": [5, 6], /// "high": [8, 10], /// "low": [2, 4], /// "close": [6, 7] @@ -133,7 +133,7 @@ mod test { .hover_text("1") .increasing(Direction::Increasing { line: Line::new() }) .legend_group("legendgroup") - .legend_group_title(LegendGroupTitle::new("Legend Group Title")) + .legend_group_title("Legend Group Title") .line(Line::new()) .name("ohlc_trace") .opacity(0.4) diff --git a/plotly/src/traces/sankey.rs b/plotly/src/traces/sankey.rs index 1a53d2c8..be96afa2 100644 --- a/plotly/src/traces/sankey.rs +++ b/plotly/src/traces/sankey.rs @@ -436,7 +436,7 @@ mod tests { .name("sankey") .visible(true) .legend_rank(1000) - .legend_group_title(LegendGroupTitle::new("Legend Group Title")) + .legend_group_title("Legend Group Title") .ids(vec!["one"]) .hover_info(HoverInfo::All) .hover_label(Label::new()) diff --git a/plotly/src/traces/scatter.rs b/plotly/src/traces/scatter.rs index caa2a076..fe9f5b9c 100644 --- a/plotly/src/traces/scatter.rs +++ b/plotly/src/traces/scatter.rs @@ -456,7 +456,7 @@ mod tests { .hover_template_array(vec!["hover_template"]) .ids(vec!["1"]) .legend_group("legend_group") - .legend_group_title(LegendGroupTitle::new("Legend Group Title")) + .legend_group_title("Legend Group Title") .line(Line::new()) .marker(Marker::new()) .meta("meta") diff --git a/plotly/src/traces/scatter3d.rs b/plotly/src/traces/scatter3d.rs index 66c72c03..412ba1f8 100644 --- a/plotly/src/traces/scatter3d.rs +++ b/plotly/src/traces/scatter3d.rs @@ -367,7 +367,7 @@ mod tests { .ids(vec!["1"]) .legend_group("legend_group") .legend_rank(1000) - .legend_group_title(LegendGroupTitle::new("Legend Group Title")) + .legend_group_title("Legend Group Title") .line(Line::new()) .marker(Marker::new()) .meta("meta") diff --git a/plotly/src/traces/scatter_mapbox.rs b/plotly/src/traces/scatter_mapbox.rs index 1ee3c164..76348e6a 100644 --- a/plotly/src/traces/scatter_mapbox.rs +++ b/plotly/src/traces/scatter_mapbox.rs @@ -311,7 +311,7 @@ mod tests { .show_legend(true) .legend_rank(1000) .legend_group("legend group") - .legend_group_title(LegendGroupTitle::new("Legend Group Title")) + .legend_group_title("Legend Group Title") .opacity(0.5) .mode(Mode::LinesText) .ids(vec!["one"]) diff --git a/plotly/src/traces/scatter_polar.rs b/plotly/src/traces/scatter_polar.rs index ae3ed244..a9101607 100644 --- a/plotly/src/traces/scatter_polar.rs +++ b/plotly/src/traces/scatter_polar.rs @@ -368,7 +368,7 @@ mod tests { .hover_text_array(vec!["hover_text"]) .ids(vec!["1"]) .legend_group("legend_group") - .legend_group_title(LegendGroupTitle::new("Legend Group Title")) + .legend_group_title("Legend Group Title") .line(Line::new()) .marker(Marker::new()) .meta("meta") diff --git a/plotly/src/traces/surface.rs b/plotly/src/traces/surface.rs index b4110d3b..3f692543 100644 --- a/plotly/src/traces/surface.rs +++ b/plotly/src/traces/surface.rs @@ -328,7 +328,7 @@ mod tests { .hover_text("hover_text") .hover_text_array(vec!["hover_text_1"]) .legend_group("legend_group") - .legend_group_title(LegendGroupTitle::new("Legend Group Title")) + .legend_group_title("Legend Group Title") .lighting(Lighting::new()) .light_position(Position::new(0, 0, 0)) .name("surface_trace") diff --git a/plotly_derive/src/field_setter.rs b/plotly_derive/src/field_setter.rs index f330be21..ca13d1d3 100644 --- a/plotly_derive/src/field_setter.rs +++ b/plotly_derive/src/field_setter.rs @@ -140,6 +140,8 @@ enum FieldType { OptionString, OptionNumOrString, OptionNumOrStringCollection, + OptionTitle, + OptionLegendGroupTitle, OptionOther(syn::Type), } @@ -202,6 +204,8 @@ impl FieldType { FieldType::OptionNumOrStringCollection => quote![crate::private::NumOrStringCollection], FieldType::OptionOther(inner) => quote![#inner], FieldType::OptionBoxOther(inner) => quote![Box<#inner>], + FieldType::OptionTitle => quote![Title], + FieldType::OptionLegendGroupTitle => quote![LegendGroupTitle], } } @@ -225,6 +229,8 @@ impl FieldType { ["Box", "Color"] => FieldType::OptionBoxColor, ["Box", ..] => FieldType::OptionBoxOther(types.get(2).cloned().unwrap()), ["Vec", "Box", "Color"] => FieldType::OptionVecBoxColor, + ["Title"] => FieldType::OptionTitle, + ["LegendGroupTitle"] => FieldType::OptionLegendGroupTitle, _ => FieldType::OptionOther(types.get(1).cloned().unwrap()), } } @@ -344,6 +350,12 @@ impl FieldReceiver { quote![value.into()], quote![], ), + FieldType::OptionTitle => (quote![impl Into<Title>], quote![value.into()], quote![]), + FieldType::OptionLegendGroupTitle => ( + quote![impl Into<LegendGroupTitle>], + quote![value.into()], + quote![], + ), }; struct ModifyEnum { diff --git a/plotly_kaleido/src/lib.rs b/plotly_kaleido/src/lib.rs index 199c77fe..f6641c25 100644 --- a/plotly_kaleido/src/lib.rs +++ b/plotly_kaleido/src/lib.rs @@ -239,7 +239,8 @@ mod tests { assert_eq!(to_value(kaleido_data).unwrap(), expected); } - #[cfg(not(target_os = "windows"))] + // This seems to fail unpredictably on MacOs. + #[cfg(target_os = "linux")] #[test] fn test_save_png() { let test_plot = create_test_plot(); @@ -250,7 +251,8 @@ mod tests { assert!(std::fs::remove_file(dst.as_path()).is_ok()); } - #[cfg(not(target_os = "windows"))] + // This seems to fail unpredictably on MacOs. + #[cfg(target_os = "linux")] #[test] fn test_save_jpeg() { let test_plot = create_test_plot(); @@ -261,7 +263,8 @@ mod tests { assert!(std::fs::remove_file(dst.as_path()).is_ok()); } - #[cfg(not(target_os = "windows"))] + // This seems to fail unpredictably on MacOs. + #[cfg(target_os = "linux")] #[test] fn test_save_webp() { let test_plot = create_test_plot(); @@ -272,7 +275,8 @@ mod tests { assert!(std::fs::remove_file(dst.as_path()).is_ok()); } - #[cfg(not(target_os = "windows"))] + // This seems to fail unpredictably on MacOs. + #[cfg(target_os = "linux")] #[test] fn test_save_svg() { let test_plot = create_test_plot(); @@ -283,7 +287,8 @@ mod tests { assert!(std::fs::remove_file(dst.as_path()).is_ok()); } - #[cfg(not(target_os = "windows"))] + // This seems to fail unpredictably on MacOs. + #[cfg(target_os = "linux")] #[test] fn test_save_pdf() { let test_plot = create_test_plot(); @@ -294,6 +299,7 @@ mod tests { assert!(std::fs::remove_file(dst.as_path()).is_ok()); } + // This doesn't work for some reason #[test] #[ignore] fn test_save_eps() { From 2ab92bfcd33389268f6b50e270332d0568c17c78 Mon Sep 17 00:00:00 2001 From: Andrei <8067229+andrei-ng@users.noreply.github.com> Date: Sat, 29 Jun 2024 10:24:30 +0200 Subject: [PATCH 39/39] update Cargo.toml version for release (#214) Signed-off-by: Andrei Gherghescu <8067229+andrei-ng@users.noreply.github.com> --- CHANGELOG.md | 22 +++++++++++----------- README.md | 6 +++--- docs/book/src/getting_started.md | 4 ++-- plotly/Cargo.toml | 8 ++++---- plotly_derive/Cargo.toml | 2 +- plotly_kaleido/Cargo.toml | 2 +- 6 files changed, 22 insertions(+), 22 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 44f210e8..0ecb4ecb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,19 +3,19 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). -## [0.9.0] - 2024-xx-xx +## [0.9.0] - 2024-06-29 ### Added -- [[#207](https://github.com/plotly/plotly,rs/pull/207)] Add `Table` trace. -- [[#181](https://github.com/plotly/plotly,rs/pull/181)] Fix compilation error when mixing the crate with `askama/with-axum` by adding `with-axum` feature. -- [[#180](https://github.com/plotly/plotly.rs/pull/180)] Add setter for `Mapbox::domain`. -- [[#178](https://github.com/plotly/plotly.rs/pull/178)] Fix setter for `Axis::matches` to take string arg. -- [[#166](https://github.com/plotly/plotly.rs/pull/166)] Added subplot example with multiple titles. -- [[#163](https://github.com/plotly/plotly.rs/pull/163)] Added `DensityMapbox`. -- [[#161](https://github.com/plotly/plotly.rs/pull/161)] Added `Axis` `scaleanchor` settter. -- [[#159](https://github.com/plotly/plotly.rs/pull/159)] Make `heat_map` module public to expose `Smoothing enum`. -- [[#157](https://github.com/plotly/plotly.rs/pull/157)] Fix `HeatMap`'s setters for correctly setting `zmin`, `zmax` and `zmin` independent of `Z` input type. -- [[#154](https://github.com/plotly/plotly.rs/pull/154)] Improve ergonomics of `Title` and `LegendGroupTitle` structs: `new` method now takes no arguments as per other structs, whilst a new `with_text()` constructor is added for convenience. Where other structs contain a `Title` (and `LegendGroupTitle`), users can now call the `title()` (and `legend_group_title()`) method with anything that `impl`s `Into<Title>`, viz. `String`, `&String`, `&str` and `Title`. - [[#153](https://github.com/plotly/plotly.rs/pull/153)] Added `LayoutScene`. +- [[#154](https://github.com/plotly/plotly.rs/pull/154)] Improve ergonomics of `Title` and `LegendGroupTitle` structs: `new` method now takes no arguments as per other structs, whilst a new `with_text()` constructor is added for convenience. Where other structs contain a `Title` (and `LegendGroupTitle`), users can now call the `title()` (and `legend_group_title()`) method with anything that `impl`s `Into<Title>`, viz. `String`, `&String`, `&str` and `Title`. +- [[#157](https://github.com/plotly/plotly.rs/pull/157)] Fix `HeatMap`'s setters for correctly setting `zmin`, `zmax` and `zmin` independent of `Z` input type. +- [[#159](https://github.com/plotly/plotly.rs/pull/159)] Make `heat_map` module public to expose `Smoothing enum`. +- [[#161](https://github.com/plotly/plotly.rs/pull/161)] Added `Axis` `scaleanchor` settter. +- [[#163](https://github.com/plotly/plotly.rs/pull/163)] Added `DensityMapbox`. +- [[#166](https://github.com/plotly/plotly.rs/pull/166)] Added subplot example with multiple titles. +- [[#178](https://github.com/plotly/plotly.rs/pull/178)] Fix setter for `Axis::matches` to take string arg. +- [[#180](https://github.com/plotly/plotly.rs/pull/180)] Add setter for `Mapbox::domain`. +- [[#181](https://github.com/plotly/plotly,rs/pull/181)] Fix compilation error when mixing the crate with `askama/with-axum` by adding `with-axum` feature. +- [[#207](https://github.com/plotly/plotly,rs/pull/207)] Add `Table` trace. - [[#212](https://github.com/plotly/plotly.rs/pull/212)] Update LICENSE ## [0.8.4] - 2023-07-09 diff --git a/README.md b/README.md index 1909419e..8407d6ba 100644 --- a/README.md +++ b/README.md @@ -61,7 +61,7 @@ Add this to your `Cargo.toml`: ```toml [dependencies] -plotly = "0.8.4" +plotly = "0.9.0" ``` ## Exporting an Interactive Plot @@ -103,7 +103,7 @@ To save a plot as a static image, the `kaleido` feature is required: # Cargo.toml [dependencies] -plotly = { version = "0.8.4", features = ["kaleido"] } +plotly = { version = "0.9.0", features = ["kaleido"] } ``` With this feature enabled, plots can be saved as any of `png`, `jpeg`, `webp`, `svg`, `pdf` and `eps`. Note that the plot will be a static image, i.e. they will be non-interactive. @@ -130,7 +130,7 @@ Using `Plotly.rs` in a Wasm-based frontend framework is possible by enabling the # Cargo.toml [dependencies] -plotly = { version = "0.8.4", features = ["wasm"] } +plotly = { version = "0.9.0", features = ["wasm"] } ``` First, make sure that you have the Plotly JavaScript library in your base HTML template: diff --git a/docs/book/src/getting_started.md b/docs/book/src/getting_started.md index e0a83086..ee3acc79 100644 --- a/docs/book/src/getting_started.md +++ b/docs/book/src/getting_started.md @@ -22,7 +22,7 @@ To start using [plotly.rs](https://github.com/plotly/plotly.rs) in your project ```toml [dependencies] -plotly = "0.8.4" +plotly = "0.9.0" ``` [Plotly.rs](https://github.com/plotly/plotly.rs) is ultimately a thin wrapper around the `plotly.js` library. The main job of this library is to provide `structs` and `enums` which get serialized to `json` and passed to the `plotly.js` library to actually do the heavy lifting. As such, if you are familiar with `plotly.js` or its derivatives (e.g. the equivalent Python library), then you should find [`plotly.rs`](https://github.com/plotly/plotly.rs) intuitive to use. @@ -97,7 +97,7 @@ To add the ability to save plots in the following formats: png, jpeg, webp, svg, ```toml [dependencies] -plotly = { version = "0.8.4", features = ["kaleido"] } +plotly = { version = "0.9.0", features = ["kaleido"] } ``` ## WebAssembly Support diff --git a/plotly/Cargo.toml b/plotly/Cargo.toml index 55df4e53..ff9b07aa 100644 --- a/plotly/Cargo.toml +++ b/plotly/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "plotly" -version = "0.8.4" +version = "0.9.0" description = "A plotting library powered by Plotly.js" authors = ["Ioannis Giagkiozis <i.giagkiozis@gmail.com>"] license = "MIT" @@ -28,8 +28,8 @@ erased-serde = "0.4" getrandom = { version = "0.2", features = ["js"], optional = true } image = { version = "0.25", optional = true } js-sys = { version = "0.3", optional = true } -plotly_derive = { version = "0.8.4", path = "../plotly_derive" } -plotly_kaleido = { version = "0.8.4", path = "../plotly_kaleido", optional = true } +plotly_derive = { version = "0.9.0", path = "../plotly_derive" } +plotly_kaleido = { version = "0.9.0", path = "../plotly_kaleido", optional = true } ndarray = { version = "0.15.4", optional = true } once_cell = "1" serde = { version = "1.0.132", features = ["derive"] } @@ -46,5 +46,5 @@ image = "0.25" itertools = ">=0.10, <0.14" itertools-num = "0.1.3" ndarray = "0.15.4" -plotly_kaleido = { version = "0.8.4", path = "../plotly_kaleido" } +plotly_kaleido = { version = "0.9.0", path = "../plotly_kaleido" } rand_distr = "0.4" diff --git a/plotly_derive/Cargo.toml b/plotly_derive/Cargo.toml index 5cd66285..b818e8de 100644 --- a/plotly_derive/Cargo.toml +++ b/plotly_derive/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "plotly_derive" -version = "0.8.4" +version = "0.9.0" description = "Internal proc macro crate for Plotly-rs." authors = ["Ioannis Giagkiozis <i.giagkiozis@gmail.com>"] license = "MIT" diff --git a/plotly_kaleido/Cargo.toml b/plotly_kaleido/Cargo.toml index 73b873cb..ed7403a8 100644 --- a/plotly_kaleido/Cargo.toml +++ b/plotly_kaleido/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "plotly_kaleido" -version = "0.8.4" +version = "0.9.0" description = "Additional output format support for plotly using Kaleido" authors = ["Ioannis Giagkiozis <i.giagkiozis@gmail.com>"] license = "MIT"