use kuva::plot::scatter::ScatterPlot;
use kuva::plot::LinePlot;
use kuva::backend::svg::SvgBackend;
use kuva::render::render::render_multiple;
use kuva::render::layout::Layout;
use kuva::render::plots::Plot;
use kuva::render::annotations::{TextAnnotation, ReferenceLine, ShadedRegion};
use kuva::TickFormat;
const OUT: &str = "docs/src/assets/layout";
fn main() {
std::fs::create_dir_all(OUT).expect("could not create docs/src/assets/layout");
log_scale();
tick_formats();
tick_controls();
annotations();
text_annotation();
reference_line();
shaded_region();
println!("Layout SVGs written to {OUT}/");
}
fn log_scale() {
let data: Vec<(f64, f64)> = vec![
(1.0, 0.001), (3.0, 0.02), (10.0, 0.5),
(30.0, 8.0), (100.0, 150.0), (300.0, 3_000.0),
(1000.0, 60_000.0),
];
let scatter = ScatterPlot::new()
.with_data(data)
.with_color("steelblue")
.with_size(5.0);
let plots = vec![Plot::Scatter(scatter)];
let layout = Layout::auto_from_plots(&plots)
.with_log_scale()
.with_title("Log-Scale Axes")
.with_x_label("X (log₁₀)")
.with_y_label("Y (log₁₀)");
let svg = SvgBackend.render_scene(&render_multiple(plots, layout));
std::fs::write(format!("{OUT}/log_scale.svg"), svg).unwrap();
}
fn tick_formats() {
let data_linear = vec![(0.0_f64, 0.0_f64), (0.25, 0.25), (0.5, 0.5), (0.75, 0.75), (1.0, 1.0)];
let data_large = vec![(0.0_f64, 0.0_f64), (25_000.0, 50_000.0), (50_000.0, 100_000.0)];
{
let plot = ScatterPlot::new().with_data(data_linear.clone()).with_color("steelblue").with_size(5.0);
let plots = vec![Plot::Scatter(plot)];
let layout = Layout::auto_from_plots(&plots).with_title("Auto");
let svg = SvgBackend.render_scene(&render_multiple(plots, layout));
std::fs::write(format!("{OUT}/tick_auto.svg"), svg).unwrap();
}
{
let plot = ScatterPlot::new().with_data(data_linear.clone()).with_color("steelblue").with_size(5.0);
let plots = vec![Plot::Scatter(plot)];
let layout = Layout::auto_from_plots(&plots)
.with_title("Fixed(2)")
.with_tick_format(TickFormat::Fixed(2));
let svg = SvgBackend.render_scene(&render_multiple(plots, layout));
std::fs::write(format!("{OUT}/tick_fixed.svg"), svg).unwrap();
}
{
let plot = ScatterPlot::new().with_data(data_linear.clone()).with_color("steelblue").with_size(5.0);
let plots = vec![Plot::Scatter(plot)];
let layout = Layout::auto_from_plots(&plots)
.with_title("Percent")
.with_tick_format(TickFormat::Percent);
let svg = SvgBackend.render_scene(&render_multiple(plots, layout));
std::fs::write(format!("{OUT}/tick_percent.svg"), svg).unwrap();
}
{
let plot = ScatterPlot::new().with_data(data_large.clone()).with_color("steelblue").with_size(5.0);
let plots = vec![Plot::Scatter(plot)];
let layout = Layout::auto_from_plots(&plots)
.with_title("Sci")
.with_tick_format(TickFormat::Sci);
let svg = SvgBackend.render_scene(&render_multiple(plots, layout));
std::fs::write(format!("{OUT}/tick_sci.svg"), svg).unwrap();
}
}
fn tick_controls() {
let data: Vec<(f64, f64)> = (0..=10).map(|i| (i as f64, (i as f64 * 0.6).sin() * 3.0 + 4.0)).collect();
let save = |name: &str, title: &str, axis_w: f64, tick_w: f64, tick_len: f64, grid_w: f64| {
let plot = ScatterPlot::new().with_data(data.clone()).with_color("steelblue").with_size(4.0);
let plots = vec![Plot::Scatter(plot)];
let layout = Layout::auto_from_plots(&plots)
.with_title(title)
.with_width(280.0)
.with_height(220.0)
.with_axis_line_width(axis_w)
.with_tick_width(tick_w)
.with_tick_length(tick_len)
.with_grid_line_width(grid_w);
let svg = SvgBackend.render_scene(&render_multiple(plots, layout));
std::fs::write(format!("{OUT}/{name}.svg"), svg).unwrap();
};
save("tick_controls_default", "Defaults", 1.0, 1.0, 5.0, 1.0);
save("tick_controls_heavy", "Heavy / long ticks", 2.0, 1.5, 10.0, 0.5);
}
fn text_annotation() {
let data = vec![
(1.0_f64, 1.2_f64), (1.8, 2.5), (2.4, 1.9), (3.1, 3.4),
(3.8, 2.8), (4.5, 4.1), (5.2, 3.9), (6.0, 9.0),
];
let plot = ScatterPlot::new()
.with_data(data)
.with_color("steelblue")
.with_size(5.0);
let plots = vec![Plot::Scatter(plot)];
let layout = Layout::auto_from_plots(&plots)
.with_title("Text Annotation")
.with_x_label("X")
.with_y_label("Y")
.with_annotation(
TextAnnotation::new("Outlier", 5.0, 7.5)
.with_arrow(6.0, 9.0)
.with_color("crimson")
.with_font_size(12),
);
let svg = SvgBackend.render_scene(&render_multiple(plots, layout));
std::fs::write(format!("{OUT}/text_annotation.svg"), svg).unwrap();
}
fn reference_line() {
let data = vec![
(0.5_f64, 0.28_f64), (1.2, 0.14), (1.8, 0.04), (2.4, 0.19),
(2.9, 0.08), (3.8, 0.21), (4.5, 0.12), (5.1, 0.07),
(5.8, 0.25), (6.5, 0.09),
];
let plot = ScatterPlot::new()
.with_data(data)
.with_color("steelblue")
.with_size(5.0);
let plots = vec![Plot::Scatter(plot)];
let layout = Layout::auto_from_plots(&plots)
.with_title("Reference Lines")
.with_x_label("X")
.with_y_label("p-value")
.with_reference_line(
ReferenceLine::horizontal(0.05)
.with_color("crimson")
.with_label("p = 0.05"),
)
.with_reference_line(
ReferenceLine::vertical(3.5)
.with_color("steelblue")
.with_label("cutoff")
.with_stroke_width(1.5)
.with_dasharray("8 4"),
);
let svg = SvgBackend.render_scene(&render_multiple(plots, layout));
std::fs::write(format!("{OUT}/reference_line.svg"), svg).unwrap();
}
fn shaded_region() {
let data = vec![
(2.0_f64, 1.0_f64), (5.0, 3.2), (8.0, 0.8), (12.0, 5.5),
(15.0, 2.1), (18.0, 6.3), (22.0, 3.8), (25.0, 1.5), (28.0, 4.7),
];
let plot = ScatterPlot::new()
.with_data(data)
.with_color("steelblue")
.with_size(5.0);
let plots = vec![Plot::Scatter(plot)];
let layout = Layout::auto_from_plots(&plots)
.with_title("Shaded Regions")
.with_x_label("X")
.with_y_label("Y")
.with_shaded_region(
ShadedRegion::horizontal(2.0, 4.0)
.with_color("gold")
.with_opacity(0.2),
)
.with_shaded_region(
ShadedRegion::vertical(10.0, 20.0)
.with_color("steelblue")
.with_opacity(0.15),
);
let svg = SvgBackend.render_scene(&render_multiple(plots, layout));
std::fs::write(format!("{OUT}/shaded_region.svg"), svg).unwrap();
}
fn annotations() {
let xs: Vec<f64> = (0..=60).map(|i| i as f64 * 0.1).collect();
let line = LinePlot::new()
.with_data(xs.iter().map(|&x| (x, x.sin())))
.with_color("steelblue")
.with_stroke_width(2.0);
let plots = vec![Plot::Line(line)];
let layout = Layout::auto_from_plots(&plots)
.with_title("Annotations")
.with_x_label("X")
.with_y_label("Y")
.with_shaded_region(
ShadedRegion::horizontal(0.0, 1.1)
.with_color("steelblue")
.with_opacity(0.08),
)
.with_reference_line(
ReferenceLine::horizontal(0.0)
.with_color("black")
.with_label("y = 0"),
)
.with_reference_line(
ReferenceLine::vertical(1.57)
.with_color("crimson")
.with_label("π/2"),
)
.with_annotation(
TextAnnotation::new("peak", 1.0, 1.15)
.with_arrow(1.57, 1.0)
.with_color("crimson"),
);
let svg = SvgBackend.render_scene(&render_multiple(plots, layout));
std::fs::write(format!("{OUT}/annotations.svg"), svg).unwrap();
}