Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion examples/basic_charts/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1100,7 +1100,7 @@ fn set_lower_or_upper_bound_on_axis(show: bool, file_name: &str) {

// Create layout with subplots
let mut layout = Layout::new()
.title("Iris Dataset - Subplots by Species")
.title("Iris Dataset - SubplotsBuilder by Species")
.grid(
LayoutGrid::new()
.rows(1)
Expand Down
102 changes: 93 additions & 9 deletions examples/subplots/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use plotly::Configuration;
use plotly::{color::Rgb, Plot, Scatter};
use plotly_utils::write_example_to_html;

// Subplots
// SubplotsBuilder
// ANCHOR: simple_subplot
fn simple_subplot(show: bool, file_name: &str) {
let trace1 = Scatter::new(vec![1, 2, 3], vec![4, 5, 6]).name("trace1");
Expand Down Expand Up @@ -232,7 +232,7 @@ fn multiple_custom_sized_subplots(show: bool, file_name: &str) {
plot.add_trace(trace4);

let layout = Layout::new()
.title("Multiple Custom Sized Subplots")
.title("Multiple Custom Sized SubplotsBuilder")
.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"))
Expand Down Expand Up @@ -423,12 +423,14 @@ fn subplots_with_multiple_traces(show: bool, file_name: &str) {
plot.add_trace(trace4);
plot.add_trace(trace5);

let layout = Layout::new().title("Subplots with Multiple Traces").grid(
LayoutGrid::new()
.rows(1)
.columns(2)
.pattern(GridPattern::Independent),
);
let layout = Layout::new()
.title("SubplotsBuilder with Multiple Traces")
.grid(
LayoutGrid::new()
.rows(1)
.columns(2)
.pattern(GridPattern::Independent),
);
plot.set_layout(layout);

let path = write_example_to_html(&plot, file_name);
Expand All @@ -438,9 +440,88 @@ fn subplots_with_multiple_traces(show: bool, file_name: &str) {
}
// ANCHOR_END: subplots_with_multiple_traces

// ANCHOR: make_subplots_api
fn make_subplots_api(show: bool, file_name: &str) {
use plotly::subplot::SubplotsBuilder;
let mut fig = SubplotsBuilder::new(1, 2)
.subplot_titles(vec!["Plot 1", "Plot 2"])
.x_axis_titles(vec!["X Axis 1", "X Axis 2"])
.y_axis_titles(vec!["Y Axis 1", "Y Axis 2"])
.x_title_at(1, 1, "X Axis 1")
.y_title_at(1, 2, "Y Axis 2")
.horizontal_spacing(0.1);
fig.add_trace(Scatter::new(vec![1, 2, 3], vec![4, 5, 6]), 1, 1);
fig.add_trace(Scatter::new(vec![20, 30, 40], vec![50, 60, 70]), 1, 2);

let plot = fig.make_subplots();
let path = write_example_to_html(&plot, file_name);
if show {
plot.show_html(path);
}
}

// ANCHOR: make_subplots_large_grid
fn make_subplots_large_grid(show: bool, file_name: &str) {
use plotly::subplot::SubplotsBuilder;

// Create a 4x4 grid (16 subplots) to test beyond the 8-axis hardcoded limit
let titles = vec![
"Subplot 1",
"Subplot 2",
"Subplot 3",
"Subplot 4",
"Subplot 5",
"Subplot 6",
"Subplot 7",
"Subplot 8",
"Subplot 9",
"Subplot 10",
"Subplot 11",
"Subplot 12",
"Subplot 13",
"Subplot 14",
"Subplot 15",
"Subplot 16",
];

let rows = 4;
let cols = 4;
let mut fig = SubplotsBuilder::new(rows, cols)
.subplot_titles(titles)
.x_axis_titles(vec!["X Axis 1", "X Axis 2", "X Axis 3", "X Axis 4"])
.y_axis_titles(vec!["Y Axis 1", "Y Axis 2", "Y Axis 3", "Y Axis 4"])
.x_title_at(1, 1, "X Axis 1")
.y_title_at(1, 2, "Y Axis 2")
.horizontal_spacing(0.05)
.vertical_spacing(0.5);

for row in 1..=rows {
for col in 1..=cols {
let subplot_num = (row - 1) * cols + col;
let x_data: Vec<i32> = (1..=5).map(|i| (i as i32) * subplot_num as i32).collect();
let y_data: Vec<i32> = (1..=5)
.map(|i| (i as i32) * subplot_num as i32 + 10)
.collect();

fig.add_trace(
Scatter::new(x_data, y_data).name(&format!("Trace {}", subplot_num)),
row as usize,
col as usize,
);
}
}

let plot = fig.make_subplots();
let path = write_example_to_html(&plot, file_name);
if show {
plot.show_html(path);
}
}
// ANCHOR_END: make_subplots_large_grid

fn main() {
// Change false to true on any of these lines to display the example.
// Subplots
// SubplotsBuilder
simple_subplot(false, "simple_subplot");

simple_subplot_matches_x_axis(false, "simple_subplot_matches_x_axis");
Expand All @@ -462,4 +543,7 @@ fn main() {
// Multiple Axes
two_y_axes(false, "two_y_axes");
multiple_axes(false, "multiple_axes");

make_subplots_api(false, "make_subplots_api");
make_subplots_large_grid(false, "make_subplots_large_grid");
}
34 changes: 34 additions & 0 deletions plotly/src/layout/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -285,6 +285,10 @@ pub struct LayoutFields {
hover_label: Option<Label>,
grid: Option<LayoutGrid>,
calendar: Option<Calendar>,
#[serde(flatten)]
#[field_setter(skip)]
axes: Option<std::collections::BTreeMap<String, Box<Axis>>>,
// Keeping these hardcoded axes for backward compatibility
#[serde(rename = "xaxis")]
x_axis: Option<Box<Axis>>,
#[serde(rename = "yaxis")]
Expand Down Expand Up @@ -383,6 +387,36 @@ pub struct LayoutFields {
sliders: Option<Vec<Slider>>,
}

impl Layout {
pub fn axis_by_name<S: Into<String>>(&mut self, axis_name: S, axis: Axis) -> &mut Self {
if self.axes.is_none() {
self.axes = Some(std::collections::BTreeMap::new());
}
self.axes
.as_mut()
.unwrap()
.insert(axis_name.into(), Box::new(axis));
self
}

pub fn set_x_axis(&mut self, index: usize, axis: Axis) -> &mut Self {
let key = if index == 1 {
"xaxis".to_string()
} else {
format!("xaxis{index}")
};
self.axis_by_name(key, axis)
}
pub fn set_y_axis(&mut self, index: usize, axis: Axis) -> &mut Self {
let key = if index == 1 {
"yaxis".to_string()
} else {
format!("yaxis{index}")
};
self.axis_by_name(key, axis)
}
}

#[cfg(test)]
mod tests {
use serde_json::{json, to_value};
Expand Down
2 changes: 2 additions & 0 deletions plotly/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,12 +52,14 @@ pub mod configuration;
pub mod export;
pub mod layout;
pub mod plot;
pub mod subplot;
pub mod traces;

pub use common::color;
pub use configuration::Configuration;
pub use layout::Layout;
pub use plot::{Plot, Trace, Traces};
pub use subplot::{HasXYAxes, StartCell, SubplotsBuilder};
// Also provide easy access to modules which contain additional trace-specific types
pub use traces::{
box_plot, contour, heat_map, histogram, image, mesh3d, sankey, scatter, scatter3d,
Expand Down
Loading
Loading