use velociplot::prelude::*;
fn main() -> Result<()> {
println!("🦖 velociplot - Violin plot example");
let mut group1 = Vec::new();
let mut group2 = Vec::new();
let mut group3 = Vec::new();
let mut seed = 42u64;
for _ in 0..100 {
seed = (seed.wrapping_mul(1103515245).wrapping_add(12345)) % (1 << 31);
let u1 = seed as f64 / (1u64 << 31) as f64;
seed = (seed.wrapping_mul(1103515245).wrapping_add(12345)) % (1 << 31);
let u2 = seed as f64 / (1u64 << 31) as f64;
let z = (-2.0 * u1.ln()).sqrt() * (2.0 * std::f64::consts::PI * u2).cos();
group1.push(10.0 + 2.0 * z);
}
for _ in 0..100 {
seed = (seed.wrapping_mul(1103515245).wrapping_add(12345)) % (1 << 31);
let u1 = seed as f64 / (1u64 << 31) as f64;
seed = (seed.wrapping_mul(1103515245).wrapping_add(12345)) % (1 << 31);
let u2 = seed as f64 / (1u64 << 31) as f64;
let z = (-2.0 * u1.ln()).sqrt() * (2.0 * std::f64::consts::PI * u2).cos();
group2.push(15.0 + 3.0 * z);
}
for _ in 0..100 {
seed = (seed.wrapping_mul(1103515245).wrapping_add(12345)) % (1 << 31);
let u1 = seed as f64 / (1u64 << 31) as f64;
seed = (seed.wrapping_mul(1103515245).wrapping_add(12345)) % (1 << 31);
let u2 = seed as f64 / (1u64 << 31) as f64;
let z = (-2.0 * u1.ln()).sqrt() * (2.0 * std::f64::consts::PI * u2).cos();
group3.push(12.0 + 1.5 * z);
}
let violin1 = ViolinPlot::new(&group1, 1.0)
.width(0.3)
.color(Color::from_hex("#9b59b6").unwrap())
.show_box(true)
.kernel(Kernel::Gaussian)
.label("Group A");
let violin2 = ViolinPlot::new(&group2, 2.0)
.width(0.3)
.color(Color::from_hex("#e74c3c").unwrap())
.show_box(true)
.kernel(Kernel::Gaussian)
.label("Group B");
let violin3 = ViolinPlot::new(&group3, 3.0)
.width(0.3)
.color(Color::from_hex("#3498db").unwrap())
.show_box(true)
.kernel(Kernel::Gaussian)
.label("Group C");
let bounds1 = violin1.bounds().unwrap();
let bounds2 = violin2.bounds().unwrap();
let bounds3 = violin3.bounds().unwrap();
let combined = bounds1.union(&bounds2).union(&bounds3);
let bounds = combined.with_padding(0.1);
let mut canvas = SkiaCanvas::new(800, 600, bounds)?;
canvas.fill_background(&Color::WHITE.to_rgba())?;
let x_axis = Axis::new(AxisPosition::Bottom)
.label("Groups")
.tick_count(4)
.show_grid(false);
let y_axis = Axis::new(AxisPosition::Left)
.label("Value")
.tick_count(8)
.show_grid(true);
x_axis.draw(&mut canvas)?;
y_axis.draw(&mut canvas)?;
violin1.draw(&mut canvas)?;
violin2.draw(&mut canvas)?;
violin3.draw(&mut canvas)?;
let mut legend = Legend::new().position(LegendPosition::UpperRight);
for violin in [&violin1, &violin2, &violin3] {
if let Some(entry) = violin.legend_entry() {
legend = legend.add_entry(entry);
}
}
legend.draw(&mut canvas)?;
canvas.save_png("examples/images/violin_plot.png")?;
println!("✓ Plot saved to examples/images/violin_plot.png");
println!(" Three violin plots showing distribution shapes");
println!(" Wider sections = more data points");
println!(" Box plot overlays show quartiles and median");
Ok(())
}