Skip to content

Commit cc64d6f

Browse files
authored
add Pie Chart trace (#265)
* 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]>
1 parent b6155ab commit cc64d6f

File tree

20 files changed

+724
-69
lines changed

20 files changed

+724
-69
lines changed

Diff for: docs/book/src/SUMMARY.md

+4-3
Original file line numberDiff line numberDiff line change
@@ -10,15 +10,16 @@
1010
- [Basic Charts](./recipes/basic_charts.md)
1111
- [Scatter Plots](./recipes/basic_charts/scatter_plots.md)
1212
- [Line Charts](./recipes/basic_charts/line_charts.md)
13-
- [Bar Charts](./recipes/basic_charts/bar_charts.md)
14-
- [Sankey Diagrams](./recipes/basic_charts/sankey_diagrams.md)
13+
- [Bar Charts](./recipes/basic_charts/bar_charts.md)
14+
- [Pie Charts](./recipes/basic_charts/pie_charts.md)
15+
- [Sankey Diagrams](./recipes/basic_charts/sankey_diagrams.md)
1516
- [Statistical Charts](./recipes/statistical_charts.md)
1617
- [Error Bars](./recipes/statistical_charts/error_bars.md)
1718
- [Box Plots](./recipes/statistical_charts/box_plots.md)
1819
- [Histograms](./recipes/statistical_charts/histograms.md)
1920
- [Scientific Charts](./recipes/scientific_charts.md)
2021
- [Contour Plots](./recipes/scientific_charts/contour_plots.md)
21-
- [Heatmaps](./recipes/scientific_charts/heatmaps.md)
22+
- [Heatmaps](./recipes/scientific_charts/heatmaps.md)
2223
- [Financial Charts](./recipes/financial_charts.md)
2324
- [Time Series and Date Axes](./recipes/financial_charts/time_series_and_date_axes.md)
2425
- [Candlestick Charts](./recipes/financial_charts/candlestick_charts.md)

Diff for: docs/book/src/recipes/basic_charts.md

+2-1
Original file line numberDiff line numberDiff line change
@@ -6,5 +6,6 @@ Kind | Link
66
:---|:----:
77
Scatter Plots |[![Scatter Plots](./img/line_and_scatter_plot.png)](./basic_charts/scatter_plots.md)
88
Line Charts | [![Line Charts](./img/line_shape_options_for_interpolation.png)](./basic_charts/line_charts.md)
9-
Bar Charts | [![Scatter Plots](./img/bar_chart_with_error_bars.png)](./basic_charts/scatter_plots.md)
9+
Bar Charts | [![Bar Charts](./img/bar_chart_with_error_bars.png)](./basic_charts/scatter_plots.md)
10+
Pie Charts | [![Pie Charts](./img/pie_charts.png)](./basic_charts/pie_charts.md)
1011
Sankey Diagrams | [![Sankey Diagrams](./img/basic_sankey.png)](./basic_charts/sankey_diagrams.md)

Diff for: docs/book/src/recipes/basic_charts/pie_charts.md

+41
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
# Pie Charts
2+
3+
The following imports have been used to produce the plots below:
4+
5+
```rust,no_run
6+
use plotly::common::{Domain, Font, HoverInfo, Orientation};
7+
use plotly::layout::{
8+
Annotation, Layout, LayoutGrid},
9+
use plotly::layout::Layout;
10+
use plotly::{Pie, Plot};
11+
```
12+
13+
The `to_inline_html` method is used to produce the html plot displayed in this page.
14+
15+
16+
## Basic Pie Chart
17+
```rust,no_run
18+
{{#include ../../../../../examples/basic_charts/src/main.rs:basic_pie_chart}}
19+
```
20+
21+
{{#include ../../../../../examples/basic_charts/out/basic_pie_chart.html}}
22+
23+
```rust,no_run
24+
{{#include ../../../../../examples/basic_charts/src/main.rs:basic_pie_chart_labels}}
25+
```
26+
27+
{{#include ../../../../../examples/basic_charts/out/basic_pie_chart_labels.html}}
28+
29+
## Grouped Pie Chart
30+
```rust,no_run
31+
{{#include ../../../../../examples/basic_charts/src/main.rs:grouped_donout_pie_charts}}
32+
```
33+
34+
{{#include ../../../../../examples/basic_charts/out/grouped_donout_pie_charts.html}}
35+
36+
## Pie Chart Text Control
37+
```rust,no_run
38+
{{#include ../../../../../examples/basic_charts/src/main.rs:pie_chart_text_control}}
39+
```
40+
41+
{{#include ../../../../../examples/basic_charts/out/pie_chart_text_control.html}}

Diff for: docs/book/src/recipes/img/pie_charts.png

36 KB
Loading

Diff for: examples/basic_charts/src/main.rs

+148-4
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,16 @@ use ndarray::Array;
44
use plotly::{
55
color::{NamedColor, Rgb, Rgba},
66
common::{
7-
ColorScale, ColorScalePalette, DashType, Fill, Font, Line, LineShape, Marker, Mode,
8-
Orientation, Pattern, PatternShape,
7+
ColorScale, ColorScalePalette, DashType, Domain, Fill, Font, HoverInfo, Line, LineShape,
8+
Marker, Mode, Orientation, Pattern, PatternShape,
9+
},
10+
layout::{
11+
Annotation, Axis, BarMode, CategoryOrder, Layout, LayoutGrid, Legend, TicksDirection,
12+
TraceOrder,
913
},
10-
layout::{Axis, BarMode, CategoryOrder, Layout, Legend, TicksDirection, TraceOrder},
1114
sankey::{Line as SankeyLine, Link, Node},
1215
traces::table::{Cells, Header},
13-
Bar, Plot, Sankey, Scatter, ScatterPolar, Table,
16+
Bar, Pie, Plot, Sankey, Scatter, ScatterPolar, Table,
1417
};
1518
use rand_distr::{Distribution, Normal, Uniform};
1619

@@ -819,6 +822,138 @@ fn table_chart(show: bool) -> Plot {
819822
}
820823
// ANCHOR_END: table_chart
821824

825+
// Pie Charts
826+
// ANCHOR: basic_pie_chart
827+
fn basic_pie_chart(show: bool) -> Plot {
828+
let values = vec![2, 3, 4];
829+
let labels = vec!["giraffes", "orangutans", "monkeys"];
830+
let t = Pie::new(values).labels(labels);
831+
let mut plot = Plot::new();
832+
plot.add_trace(t);
833+
834+
if show {
835+
plot.show();
836+
}
837+
plot
838+
}
839+
// ANCHOR_END: basic_pie_chart
840+
841+
// ANCHOR: basic_pie_chart_labels
842+
fn basic_pie_chart_labels(show: bool) -> Plot {
843+
let labels = ["giraffes", "giraffes", "orangutans", "monkeys"];
844+
let t = Pie::<u32>::from_labels(&labels);
845+
let mut plot = Plot::new();
846+
plot.add_trace(t);
847+
848+
if show {
849+
plot.show();
850+
}
851+
plot
852+
}
853+
// ANCHOR_END: basic_pie_chart_labels
854+
855+
// ANCHOR: pie_chart_text_control
856+
fn pie_chart_text_control(show: bool) -> Plot {
857+
let values = vec![2, 3, 4, 4];
858+
let labels = vec!["Wages", "Operating expenses", "Cost of sales", "Insurance"];
859+
let t = Pie::new(values)
860+
.labels(labels)
861+
.automargin(true)
862+
.show_legend(true)
863+
.text_position(plotly::common::Position::Outside)
864+
.name("Costs")
865+
.text_info("label+percent");
866+
let mut plot = Plot::new();
867+
plot.add_trace(t);
868+
869+
let layout = Layout::new().height(700).width(700).show_legend(true);
870+
plot.set_layout(layout);
871+
872+
if show {
873+
plot.show();
874+
}
875+
plot
876+
}
877+
// ANCHOR_END: pie_chart_text_control
878+
879+
// ANCHOR: grouped_donout_pie_charts
880+
fn grouped_donout_pie_charts(show: bool) -> Plot {
881+
let mut plot = Plot::new();
882+
883+
let values = vec![16, 15, 12, 6, 5, 4, 42];
884+
let labels = vec![
885+
"US",
886+
"China",
887+
"European Union",
888+
"Russian Federation",
889+
"Brazil",
890+
"India",
891+
"Rest of World",
892+
];
893+
let t = Pie::new(values)
894+
.labels(labels)
895+
.name("GHG Emissions")
896+
.hover_info(HoverInfo::All)
897+
.text("GHG")
898+
.hole(0.4)
899+
.domain(Domain::new().column(0));
900+
plot.add_trace(t);
901+
902+
let values = vec![27, 11, 25, 8, 1, 3, 25];
903+
let labels = vec![
904+
"US",
905+
"China",
906+
"European Union",
907+
"Russian Federation",
908+
"Brazil",
909+
"India",
910+
"Rest of World",
911+
];
912+
913+
let t = Pie::new(values)
914+
.labels(labels)
915+
.name("CO2 Emissions")
916+
.hover_info(HoverInfo::All)
917+
.text("CO2")
918+
.text_position(plotly::common::Position::Inside)
919+
.hole(0.4)
920+
.domain(Domain::new().column(1));
921+
plot.add_trace(t);
922+
923+
let layout = Layout::new()
924+
.title("Global Emissions 1990-2011")
925+
.height(400)
926+
.width(600)
927+
.annotations(vec![
928+
Annotation::new()
929+
.font(Font::new().size(20))
930+
.show_arrow(false)
931+
.text("GHG")
932+
.x(0.17)
933+
.y(0.5),
934+
Annotation::new()
935+
.font(Font::new().size(20))
936+
.show_arrow(false)
937+
.text("CO2")
938+
.x(0.82)
939+
.y(0.5),
940+
])
941+
.show_legend(false)
942+
.grid(
943+
LayoutGrid::new()
944+
.columns(2)
945+
.rows(1)
946+
.pattern(plotly::layout::GridPattern::Independent),
947+
);
948+
plot.set_layout(layout);
949+
950+
if show {
951+
plot.show();
952+
}
953+
plot
954+
}
955+
// ANCHOR_END: grouped_donout_pie_charts
956+
822957
fn write_example_to_html(plot: Plot, name: &str) {
823958
std::fs::create_dir_all("./out").unwrap();
824959
let html = plot.to_inline_html(Some(name));
@@ -869,4 +1004,13 @@ fn main() {
8691004

8701005
// Sankey Diagrams
8711006
write_example_to_html(basic_sankey_diagram(false), "basic_sankey_diagram");
1007+
1008+
// Pie Charts
1009+
write_example_to_html(basic_pie_chart(false), "basic_pie_chart");
1010+
write_example_to_html(basic_pie_chart_labels(false), "basic_pie_chart_labels");
1011+
write_example_to_html(pie_chart_text_control(false), "pie_chart_text_control");
1012+
write_example_to_html(
1013+
grouped_donout_pie_charts(false),
1014+
"grouped_donout_pie_charts",
1015+
);
8721016
}

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

+20-21
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,22 @@
1-
//! This module provides several user interfaces for describing a color to be
2-
//! used throughout the rest of the library. The easiest way of describing a
3-
//! colour is to use a `&str` or `String`, which is simply serialized as-is and
4-
//! passed on to the underlying `plotly.js` library. `plotly.js` supports [`CSS
5-
//! color formats`], and will fallback to some default color if the color string
6-
//! is malformed.
7-
//!
8-
//! For a more type-safe approach, the `RGB` or `RGBA` structs can be used to
9-
//! construct a valid color, which will then get serialized to an appropriate
10-
//! string representation. Cross-browser compatible [`predefined colors`] are
11-
//! supported via the `NamedColor` enum.
12-
//!
13-
//! The `Color` trait is public, and so can be implemented for custom colour
14-
//! types. The user can then implement a valid serialization function according
15-
//! to their own requirements. On the whole, that should be largely unnecessary
16-
//! given the functionality already provided within this module.
17-
//!
18-
//! [`CSS color formats`]: https://www.w3schools.com/cssref/css_colors_legal.asp
19-
//! [`predefined colors`]: https://www.w3schools.com/cssref/css_colors.asp
20-
1+
/// This module provides several user interfaces for describing a color to be
2+
/// used throughout the rest of the library. The easiest way of describing a
3+
/// colour is to use a `&str` or `String`, which is simply serialized as-is and
4+
/// passed on to the underlying `plotly.js` library. `plotly.js` supports [`CSS
5+
/// color formats`], and will fallback to some default color if the color string
6+
/// is malformed.
7+
///
8+
/// For a more type-safe approach, the `RGB` or `RGBA` structs can be used to
9+
/// construct a valid color, which will then get serialized to an appropriate
10+
/// string representation. Cross-browser compatible [`predefined colors`] are
11+
/// supported via the `NamedColor` enum.
12+
///
13+
/// The `Color` trait is public, and so can be implemented for custom colour
14+
/// types. The user can then implement a valid serialization function according
15+
/// to their own requirements. On the whole, that should be largely unnecessary
16+
/// given the functionality already provided within this module.
17+
///
18+
/// [`CSS color formats`]: <https://www.w3schools.com/cssref/css_colors_legal.asp>
19+
/// [`predefined colors`]: <https://www.w3schools.com/cssref/css_colors.asp>
2120
use dyn_clone::DynClone;
2221
use erased_serde::Serialize as ErasedSerialize;
2322
use serde::Serialize;
@@ -116,7 +115,7 @@ impl Serialize for Rgba {
116115

117116
/// Cross-browser compatible [`predefined colors`].
118117
///
119-
/// [`predefined colors`]: https://www.w3schools.com/cssref/css_colors.asp
118+
/// [`predefined colors`]: <https://www.w3schools.com/cssref/css_colors.asp>
120119
#[derive(Debug, Clone, Copy, Serialize)]
121120
#[serde(rename_all = "lowercase")]
122121
pub enum NamedColor {

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

+11
Original file line numberDiff line numberDiff line change
@@ -153,10 +153,16 @@ pub enum ConstrainText {
153153

154154
#[derive(Serialize, Clone, Debug)]
155155
pub enum Orientation {
156+
#[serde(rename = "a")]
157+
Auto,
156158
#[serde(rename = "v")]
157159
Vertical,
158160
#[serde(rename = "h")]
159161
Horizontal,
162+
#[serde(rename = "r")]
163+
Radial,
164+
#[serde(rename = "t")]
165+
Tangential,
160166
}
161167

162168
#[derive(Serialize, Clone, Debug)]
@@ -225,6 +231,7 @@ pub enum PlotType {
225231
Surface,
226232
DensityMapbox,
227233
Table,
234+
Pie,
228235
}
229236

230237
#[derive(Serialize, Clone, Debug)]
@@ -273,6 +280,10 @@ pub enum Position {
273280
BottomCenter,
274281
#[serde(rename = "bottom right")]
275282
BottomRight,
283+
#[serde(rename = "inside")]
284+
Inside,
285+
#[serde(rename = "outside")]
286+
Outside,
276287
}
277288

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

Diff for: plotly/src/configuration.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -212,7 +212,7 @@ impl Configuration {
212212
/// When set it determines base URL for the "Edit in Chart Studio"
213213
/// `show_edit_in_chart_studio`/`show_send_to_cloud` mode bar button and
214214
/// the show_link/send_data on-graph link. To enable sending your data to
215-
/// Chart Studio Cloud, you need to set both `plotly_server_url` to "https://chart-studio.plotly.com" and
215+
/// Chart Studio Cloud, you need to set both `plotly_server_url` to <https://chart-studio.plotly.com> and
216216
/// also set `showSendToCloud` to `true`.
217217
pub fn plotly_server_url(mut self, plotly_server_url: &str) -> Self {
218218
self.plotly_server_url = Some(plotly_server_url.to_string());

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

+4-4
Original file line numberDiff line numberDiff line change
@@ -929,7 +929,7 @@ pub struct Shape {
929929
#[serde(rename = "fillcolor")]
930930
fill_color: Option<Box<dyn Color>>,
931931
/// Determines which regions of complex paths constitute the interior. For
932-
/// more info please visit https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill-rule
932+
/// more info please visit <https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill-rule>
933933
#[serde(rename = "fillrule")]
934934
fill_rule: Option<FillRule>,
935935
/// Determines whether the shape could be activated for edit or not. Has no
@@ -994,7 +994,7 @@ pub struct NewShape {
994994
#[serde(rename = "fillcolor")]
995995
fill_color: Option<Box<dyn Color>>,
996996
/// Determines the path's interior. For more info please
997-
/// visit https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill-rule
997+
/// visit <https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill-rule>
998998
#[serde(rename = "fillrule")]
999999
fill_rule: Option<FillRule>,
10001000
/// Sets the opacity of new shapes. Number between or equal to 0 and 1.
@@ -1071,8 +1071,8 @@ pub struct Annotation {
10711071
visible: Option<bool>,
10721072
/// Sets the text associated with this annotation. Plotly uses a subset of
10731073
/// HTML tags to do things like newline (<br>), bold (<b></b>), italics
1074-
/// (<i></i>), hyperlinks (<a href='...'></a>). Tags <em>, <sup>, <sub>
1075-
/// <span> are also supported.
1074+
/// (<i></i>), hyperlinks (<a href='...'></a>). Tags <em></em>, <sup></sup>,
1075+
/// <sub></sub> <span></span> are also supported.
10761076
text: Option<String>,
10771077
/// Sets the angle at which the `text` is drawn with respect to the
10781078
/// horizontal.

Diff for: plotly/src/lib.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ pub use traces::{
3636
// Bring the different trace types into the top-level scope
3737
pub use traces::{
3838
Bar, BoxPlot, Candlestick, Contour, DensityMapbox, HeatMap, Histogram, Image, Mesh3D, Ohlc,
39-
Sankey, Scatter, Scatter3D, ScatterMapbox, ScatterPolar, Surface, Table,
39+
Pie, Sankey, Scatter, Scatter3D, ScatterMapbox, ScatterPolar, Surface, Table,
4040
};
4141

4242
pub trait Restyle: serde::Serialize {}

Diff for: plotly/src/plot.rs

+1
Original file line numberDiff line numberDiff line change
@@ -585,6 +585,7 @@ impl PartialEq for Plot {
585585
mod tests {
586586
use std::path::PathBuf;
587587

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

0 commit comments

Comments
 (0)