Skip to content

Commit

Permalink
add Pie Chart trace (#265)
Browse files Browse the repository at this point in the history
* add Pie Chart trace

 - add examples
 - add section in mdBook

Signed-off-by: Andrei Gherghescu <[email protected]>

* fix cargo doc warnings

Signed-off-by: Andrei Gherghescu <[email protected]>

* add pie unittests and fix docs

Signed-off-by: Andrei Gherghescu <[email protected]>

---------

Signed-off-by: Andrei Gherghescu <[email protected]>
  • Loading branch information
andrei-ng authored Dec 31, 2024
1 parent b6155ab commit cc64d6f
Show file tree
Hide file tree
Showing 20 changed files with 724 additions and 69 deletions.
7 changes: 4 additions & 3 deletions docs/book/src/SUMMARY.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,16 @@
- [Basic Charts](./recipes/basic_charts.md)
- [Scatter Plots](./recipes/basic_charts/scatter_plots.md)
- [Line Charts](./recipes/basic_charts/line_charts.md)
- [Bar Charts](./recipes/basic_charts/bar_charts.md)
- [Sankey Diagrams](./recipes/basic_charts/sankey_diagrams.md)
- [Bar Charts](./recipes/basic_charts/bar_charts.md)
- [Pie Charts](./recipes/basic_charts/pie_charts.md)
- [Sankey Diagrams](./recipes/basic_charts/sankey_diagrams.md)
- [Statistical Charts](./recipes/statistical_charts.md)
- [Error Bars](./recipes/statistical_charts/error_bars.md)
- [Box Plots](./recipes/statistical_charts/box_plots.md)
- [Histograms](./recipes/statistical_charts/histograms.md)
- [Scientific Charts](./recipes/scientific_charts.md)
- [Contour Plots](./recipes/scientific_charts/contour_plots.md)
- [Heatmaps](./recipes/scientific_charts/heatmaps.md)
- [Heatmaps](./recipes/scientific_charts/heatmaps.md)
- [Financial Charts](./recipes/financial_charts.md)
- [Time Series and Date Axes](./recipes/financial_charts/time_series_and_date_axes.md)
- [Candlestick Charts](./recipes/financial_charts/candlestick_charts.md)
Expand Down
3 changes: 2 additions & 1 deletion docs/book/src/recipes/basic_charts.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,6 @@ Kind | Link
:---|:----:
Scatter Plots |[![Scatter Plots](./img/line_and_scatter_plot.png)](./basic_charts/scatter_plots.md)
Line Charts | [![Line Charts](./img/line_shape_options_for_interpolation.png)](./basic_charts/line_charts.md)
Bar Charts | [![Scatter Plots](./img/bar_chart_with_error_bars.png)](./basic_charts/scatter_plots.md)
Bar Charts | [![Bar Charts](./img/bar_chart_with_error_bars.png)](./basic_charts/scatter_plots.md)
Pie Charts | [![Pie Charts](./img/pie_charts.png)](./basic_charts/pie_charts.md)
Sankey Diagrams | [![Sankey Diagrams](./img/basic_sankey.png)](./basic_charts/sankey_diagrams.md)
41 changes: 41 additions & 0 deletions docs/book/src/recipes/basic_charts/pie_charts.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
# Pie Charts

The following imports have been used to produce the plots below:

```rust,no_run
use plotly::common::{Domain, Font, HoverInfo, Orientation};
use plotly::layout::{
Annotation, Layout, LayoutGrid},
use plotly::layout::Layout;
use plotly::{Pie, Plot};
```

The `to_inline_html` method is used to produce the html plot displayed in this page.


## Basic Pie Chart
```rust,no_run
{{#include ../../../../../examples/basic_charts/src/main.rs:basic_pie_chart}}
```

{{#include ../../../../../examples/basic_charts/out/basic_pie_chart.html}}

```rust,no_run
{{#include ../../../../../examples/basic_charts/src/main.rs:basic_pie_chart_labels}}
```

{{#include ../../../../../examples/basic_charts/out/basic_pie_chart_labels.html}}

## Grouped Pie Chart
```rust,no_run
{{#include ../../../../../examples/basic_charts/src/main.rs:grouped_donout_pie_charts}}
```

{{#include ../../../../../examples/basic_charts/out/grouped_donout_pie_charts.html}}

## Pie Chart Text Control
```rust,no_run
{{#include ../../../../../examples/basic_charts/src/main.rs:pie_chart_text_control}}
```

{{#include ../../../../../examples/basic_charts/out/pie_chart_text_control.html}}
Binary file added docs/book/src/recipes/img/pie_charts.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
152 changes: 148 additions & 4 deletions examples/basic_charts/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,16 @@ use ndarray::Array;
use plotly::{
color::{NamedColor, Rgb, Rgba},
common::{
ColorScale, ColorScalePalette, DashType, Fill, Font, Line, LineShape, Marker, Mode,
Orientation, Pattern, PatternShape,
ColorScale, ColorScalePalette, DashType, Domain, Fill, Font, HoverInfo, Line, LineShape,
Marker, Mode, Orientation, Pattern, PatternShape,
},
layout::{
Annotation, Axis, BarMode, CategoryOrder, Layout, LayoutGrid, Legend, TicksDirection,
TraceOrder,
},
layout::{Axis, BarMode, CategoryOrder, Layout, Legend, TicksDirection, TraceOrder},
sankey::{Line as SankeyLine, Link, Node},
traces::table::{Cells, Header},
Bar, Plot, Sankey, Scatter, ScatterPolar, Table,
Bar, Pie, Plot, Sankey, Scatter, ScatterPolar, Table,
};
use rand_distr::{Distribution, Normal, Uniform};

Expand Down Expand Up @@ -819,6 +822,138 @@ fn table_chart(show: bool) -> Plot {
}
// ANCHOR_END: table_chart

// Pie Charts
// ANCHOR: basic_pie_chart
fn basic_pie_chart(show: bool) -> Plot {
let values = vec![2, 3, 4];
let labels = vec!["giraffes", "orangutans", "monkeys"];
let t = Pie::new(values).labels(labels);
let mut plot = Plot::new();
plot.add_trace(t);

if show {
plot.show();
}
plot
}
// ANCHOR_END: basic_pie_chart

// ANCHOR: basic_pie_chart_labels
fn basic_pie_chart_labels(show: bool) -> Plot {
let labels = ["giraffes", "giraffes", "orangutans", "monkeys"];
let t = Pie::<u32>::from_labels(&labels);
let mut plot = Plot::new();
plot.add_trace(t);

if show {
plot.show();
}
plot
}
// ANCHOR_END: basic_pie_chart_labels

// ANCHOR: pie_chart_text_control
fn pie_chart_text_control(show: bool) -> Plot {
let values = vec![2, 3, 4, 4];
let labels = vec!["Wages", "Operating expenses", "Cost of sales", "Insurance"];
let t = Pie::new(values)
.labels(labels)
.automargin(true)
.show_legend(true)
.text_position(plotly::common::Position::Outside)
.name("Costs")
.text_info("label+percent");
let mut plot = Plot::new();
plot.add_trace(t);

let layout = Layout::new().height(700).width(700).show_legend(true);
plot.set_layout(layout);

if show {
plot.show();
}
plot
}
// ANCHOR_END: pie_chart_text_control

// ANCHOR: grouped_donout_pie_charts
fn grouped_donout_pie_charts(show: bool) -> Plot {
let mut plot = Plot::new();

let values = vec![16, 15, 12, 6, 5, 4, 42];
let labels = vec![
"US",
"China",
"European Union",
"Russian Federation",
"Brazil",
"India",
"Rest of World",
];
let t = Pie::new(values)
.labels(labels)
.name("GHG Emissions")
.hover_info(HoverInfo::All)
.text("GHG")
.hole(0.4)
.domain(Domain::new().column(0));
plot.add_trace(t);

let values = vec![27, 11, 25, 8, 1, 3, 25];
let labels = vec![
"US",
"China",
"European Union",
"Russian Federation",
"Brazil",
"India",
"Rest of World",
];

let t = Pie::new(values)
.labels(labels)
.name("CO2 Emissions")
.hover_info(HoverInfo::All)
.text("CO2")
.text_position(plotly::common::Position::Inside)
.hole(0.4)
.domain(Domain::new().column(1));
plot.add_trace(t);

let layout = Layout::new()
.title("Global Emissions 1990-2011")
.height(400)
.width(600)
.annotations(vec![
Annotation::new()
.font(Font::new().size(20))
.show_arrow(false)
.text("GHG")
.x(0.17)
.y(0.5),
Annotation::new()
.font(Font::new().size(20))
.show_arrow(false)
.text("CO2")
.x(0.82)
.y(0.5),
])
.show_legend(false)
.grid(
LayoutGrid::new()
.columns(2)
.rows(1)
.pattern(plotly::layout::GridPattern::Independent),
);
plot.set_layout(layout);

if show {
plot.show();
}
plot
}
// ANCHOR_END: grouped_donout_pie_charts

fn write_example_to_html(plot: Plot, name: &str) {
std::fs::create_dir_all("./out").unwrap();
let html = plot.to_inline_html(Some(name));
Expand Down Expand Up @@ -869,4 +1004,13 @@ fn main() {

// Sankey Diagrams
write_example_to_html(basic_sankey_diagram(false), "basic_sankey_diagram");

// Pie Charts
write_example_to_html(basic_pie_chart(false), "basic_pie_chart");
write_example_to_html(basic_pie_chart_labels(false), "basic_pie_chart_labels");
write_example_to_html(pie_chart_text_control(false), "pie_chart_text_control");
write_example_to_html(
grouped_donout_pie_charts(false),
"grouped_donout_pie_charts",
);
}
41 changes: 20 additions & 21 deletions plotly/src/common/color.rs
Original file line number Diff line number Diff line change
@@ -1,23 +1,22 @@
//! This module provides several user interfaces for describing a color to be
//! used throughout the rest of the library. The easiest way of describing a
//! colour is to use a `&str` or `String`, which is simply serialized as-is and
//! passed on to the underlying `plotly.js` library. `plotly.js` supports [`CSS
//! color formats`], and will fallback to some default color if the color string
//! is malformed.
//!
//! For a more type-safe approach, the `RGB` or `RGBA` structs can be used to
//! construct a valid color, which will then get serialized to an appropriate
//! string representation. Cross-browser compatible [`predefined colors`] are
//! supported via the `NamedColor` enum.
//!
//! The `Color` trait is public, and so can be implemented for custom colour
//! types. The user can then implement a valid serialization function according
//! to their own requirements. On the whole, that should be largely unnecessary
//! given the functionality already provided within this module.
//!
//! [`CSS color formats`]: https://www.w3schools.com/cssref/css_colors_legal.asp
//! [`predefined colors`]: https://www.w3schools.com/cssref/css_colors.asp
/// This module provides several user interfaces for describing a color to be
/// used throughout the rest of the library. The easiest way of describing a
/// colour is to use a `&str` or `String`, which is simply serialized as-is and
/// passed on to the underlying `plotly.js` library. `plotly.js` supports [`CSS
/// color formats`], and will fallback to some default color if the color string
/// is malformed.
///
/// For a more type-safe approach, the `RGB` or `RGBA` structs can be used to
/// construct a valid color, which will then get serialized to an appropriate
/// string representation. Cross-browser compatible [`predefined colors`] are
/// supported via the `NamedColor` enum.
///
/// The `Color` trait is public, and so can be implemented for custom colour
/// types. The user can then implement a valid serialization function according
/// to their own requirements. On the whole, that should be largely unnecessary
/// given the functionality already provided within this module.
///
/// [`CSS color formats`]: <https://www.w3schools.com/cssref/css_colors_legal.asp>
/// [`predefined colors`]: <https://www.w3schools.com/cssref/css_colors.asp>
use dyn_clone::DynClone;
use erased_serde::Serialize as ErasedSerialize;
use serde::Serialize;
Expand Down Expand Up @@ -116,7 +115,7 @@ impl Serialize for Rgba {

/// Cross-browser compatible [`predefined colors`].
///
/// [`predefined colors`]: https://www.w3schools.com/cssref/css_colors.asp
/// [`predefined colors`]: <https://www.w3schools.com/cssref/css_colors.asp>
#[derive(Debug, Clone, Copy, Serialize)]
#[serde(rename_all = "lowercase")]
pub enum NamedColor {
Expand Down
11 changes: 11 additions & 0 deletions plotly/src/common/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -153,10 +153,16 @@ pub enum ConstrainText {

#[derive(Serialize, Clone, Debug)]
pub enum Orientation {
#[serde(rename = "a")]
Auto,
#[serde(rename = "v")]
Vertical,
#[serde(rename = "h")]
Horizontal,
#[serde(rename = "r")]
Radial,
#[serde(rename = "t")]
Tangential,
}

#[derive(Serialize, Clone, Debug)]
Expand Down Expand Up @@ -225,6 +231,7 @@ pub enum PlotType {
Surface,
DensityMapbox,
Table,
Pie,
}

#[derive(Serialize, Clone, Debug)]
Expand Down Expand Up @@ -273,6 +280,10 @@ pub enum Position {
BottomCenter,
#[serde(rename = "bottom right")]
BottomRight,
#[serde(rename = "inside")]
Inside,
#[serde(rename = "outside")]
Outside,
}

#[derive(Serialize, Clone, Debug)]
Expand Down
2 changes: 1 addition & 1 deletion plotly/src/configuration.rs
Original file line number Diff line number Diff line change
Expand Up @@ -212,7 +212,7 @@ impl Configuration {
/// When set it determines base URL for the "Edit in Chart Studio"
/// `show_edit_in_chart_studio`/`show_send_to_cloud` mode bar button and
/// the show_link/send_data on-graph link. To enable sending your data to
/// Chart Studio Cloud, you need to set both `plotly_server_url` to "https://chart-studio.plotly.com" and
/// Chart Studio Cloud, you need to set both `plotly_server_url` to <https://chart-studio.plotly.com> and
/// also set `showSendToCloud` to `true`.
pub fn plotly_server_url(mut self, plotly_server_url: &str) -> Self {
self.plotly_server_url = Some(plotly_server_url.to_string());
Expand Down
8 changes: 4 additions & 4 deletions plotly/src/layout/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -929,7 +929,7 @@ pub struct Shape {
#[serde(rename = "fillcolor")]
fill_color: Option<Box<dyn Color>>,
/// Determines which regions of complex paths constitute the interior. For
/// more info please visit https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill-rule
/// more info please visit <https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill-rule>
#[serde(rename = "fillrule")]
fill_rule: Option<FillRule>,
/// Determines whether the shape could be activated for edit or not. Has no
Expand Down Expand Up @@ -994,7 +994,7 @@ pub struct NewShape {
#[serde(rename = "fillcolor")]
fill_color: Option<Box<dyn Color>>,
/// Determines the path's interior. For more info please
/// visit https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill-rule
/// visit <https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill-rule>
#[serde(rename = "fillrule")]
fill_rule: Option<FillRule>,
/// Sets the opacity of new shapes. Number between or equal to 0 and 1.
Expand Down Expand Up @@ -1071,8 +1071,8 @@ pub struct Annotation {
visible: Option<bool>,
/// Sets the text associated with this annotation. Plotly uses a subset of
/// HTML tags to do things like newline (<br>), bold (<b></b>), italics
/// (<i></i>), hyperlinks (<a href='...'></a>). Tags <em>, <sup>, <sub>
/// <span> are also supported.
/// (<i></i>), hyperlinks (<a href='...'></a>). Tags <em></em>, <sup></sup>,
/// <sub></sub> <span></span> are also supported.
text: Option<String>,
/// Sets the angle at which the `text` is drawn with respect to the
/// horizontal.
Expand Down
2 changes: 1 addition & 1 deletion plotly/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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, Table,
Pie, Sankey, Scatter, Scatter3D, ScatterMapbox, ScatterPolar, Surface, Table,
};

pub trait Restyle: serde::Serialize {}
Expand Down
1 change: 1 addition & 0 deletions plotly/src/plot.rs
Original file line number Diff line number Diff line change
Expand Up @@ -585,6 +585,7 @@ impl PartialEq for Plot {
mod tests {
use std::path::PathBuf;

#[cfg(feature = "kaleido")]
use base64::{engine::general_purpose, Engine as _};
use serde_json::{json, to_value};

Expand Down
Loading

0 comments on commit cc64d6f

Please sign in to comment.