plotters-rs / plotters

A rust drawing library for high quality data plotting for both WASM and native, statically and realtimely 🦀 📈🚀
https://plotters-rs.github.io/home/
MIT License
3.81k stars 276 forks source link

Ability to save figures in the same way you can in rust in a notebook environment. #552

Closed JaminMartin closed 5 months ago

JaminMartin commented 7 months ago

What is the feature?

The ability to save a figure from a jupyter notebook instance.

It is not obvious to me that this can currently be done with how the evcxr_figure function is implemented.

(Optional) Why this feature is useful and how people would use the feature?

This would improve usability, especially for use in Data Science. A notebook is a great learning environment for Rust in this context and so it would be good to be able to save the outputs in the same way you would when using it in Rust.

(Optional) Additional Information

This is an attempt at making this change, or at least how I would interpret it to be done. I hope it is this simple!

pub fn evcxr_figure<
    Draw: FnOnce(DrawingArea<SVGBackend, Shift>) -> Result<(), Box<dyn std::error::Error>>,
>(
    filename: &str,
    size: (u32, u32),
    draw: Draw,
) -> SVGWrapper {
    let root = SVGBackend::new(filename, size).into_drawing_area();
    draw(root).expect("Drawing failure");
    SVGWrapper(filename.to_string(), "".to_string())
}

However, I am not sure how the SVG wrapper itself works so I am not sure if this would actually work as an implementation, just here to aid in the explanation of the feature.

wangjiawen2013 commented 6 months ago

Is the following you want ? You can run them in jupyter notebook and the image will be saved.

// Create a 800*600 svg and start drawing
let mut backend = SVGBackend::new("figures/output.svg", (800, 600));
// And if we want bitmap backend
//let mut backend = BitMapBackend::new("figures/output.png", (300, 200));
backend.draw_rect((50, 50), (200, 150), &RED, true)?;
backend.present()?;

or

// In jupyter notebook 中,main() can be replaced with any name, such as rectangle()
use plotters::prelude::*;
fn main() -> Result<(), Box<dyn std::error::Error>> {
    let mut backend = SVGBackend::new("figures/output.svg", (800, 600));
    backend.draw_rect((50, 50), (200, 150), &RED, true)?;
    backend.present()?;
    Ok(())
}

main(); // call plotting function in this jupyter cell
JaminMartin commented 6 months ago

Thanks but what I was wanting was to be able to generate a plot in the notebook to see visually but also simultaneously save it without duplicating code.

I've added a function to handle this in the pull request #559.

Thanks for your feedback though!

wangjiawen2013 commented 6 months ago

Good job ! Looking forward to plotters new release so we can use it as soon as possible