cpmech / plotpy

Rust plotting library using Python (Matplotlib)
MIT License
63 stars 6 forks source link

evcxr_jupyter support #58

Closed wangjiawen2013 closed 2 weeks ago

wangjiawen2013 commented 4 weeks ago

Hi, Does plotpy support evcxr_jupyter ? If so, it would be very convinience ! Plotters and plotly.rs support evcxr_jupyter now.

cpmech commented 4 weeks ago

Hi, unfortunately, evcxr is not supported.

wangjiawen2013 commented 4 weeks ago

Jupyter notebook is very popular in data science and data visualization, it's hard to abandon it for lots of users. Plotpy can get more attractive for people getting used to jupyter if it can support it. Now I get an idea on how to use plotpy in evcxr_jupyter. Here is the code:

:dep plotpy
use plotpy::{generate3d, Contour, Plot, StrError};
use std::fs;
use std::io;

// Function to show the saved figure in evcxr_jupyter
fn show(figure_path: &str) -> Result<(), io::Error> {
    let figure = fs::read_to_string(figure_path)?;
    println!("EVCXR_BEGIN_CONTENT text/html\n{}\nEVCXR_END_CONTENT", figure);
    Ok(())
}

// Set python path to integrate with evcxr later
let python = "/home/wangjw/programs/miniconda3/envs/py311/bin/python";
// Set the file path and name to be saved
let file = "figure.svg";

let n = 21;
let (x, y, z) = generate3d(-2.0, 2.0, -2.0, 2.0, n, n, |x, y| x * x - y * y);

// configure contour
let mut contour = Contour::new();
contour
    .set_colorbar_label("temperature")
    .set_colormap_name("terrain")
    .set_selected_level(0.0, true);

// draw contour
contour.draw(&x, &y, &z);

// add contour to plot
let mut plot = Plot::new();

// We may have various (ananconda) python environment, but there's not currently any
// integration with evcxr, so we must set python path in order to use the suitable
// python environment
plot.set_python_exe(python);
plot.add(&contour);
plot.save(file)?;
show(file)?;  // impl this method for plot later, then we can just call plot.show()

And here is the running result: image If you think it's feasible, I will try to send you a PR ("try to" because I am a novice of Rust and have few experience on github PR and Rust).

wangjiawen2013 commented 4 weeks ago

There are alread many Rust visualization crate yet (plotters, plotly.rs, chart-rs, charming and so on), but all of them are lack of maintenance. I don't think it's feasible to construct a independent visualization ecosystem for Rust. Maybe It's a good way to take advantage of some mature visualization tools in other languages, just like rust plotpy and hope you can add more plotting function. I'll help to enhance this crate once I am familiar with Rust and plotpy and have the ability to contribute.

cpmech commented 4 weeks ago

Hi, thank you. This looks fantastic! But you mentioned the keyword here maintenance. Since I'm unfamiliar with evcxr, maintaining such integration would be very difficult. Also, you mentioned that you're getting more familiar with Rust; therefore, it may be time-consuming for you. Nonetheless, if the only required implementation is to call another function like your show function, we may be able to do it.

wangjiawen2013 commented 3 weeks ago

Evcxr is an evaluation context for Rust under active maintenance by David Lattimore, so don't worry about Evcxr. At present, it appears that the only thing need do is the show function. I'll start to implement it this week.

cpmech commented 3 weeks ago

Hi,

Thanks again for the suggestion and implementation. The function show_in_evcxr is now available in version 1.4.0

Can you please try it to see if it works in your system?

wangjiawen2013 commented 3 weeks ago

It worked in my windows10 desktop and centos7 server.

cpmech commented 2 weeks ago

Hi, thanks again for the code and suggestions to Readme. I've submitted another PR with the Readme changes.

Now, I'm wondering: would it be better if show_in_evcxr saved the figure already? So, we don't need to call save?

This is how the save_and_show function works. The user could forget to save or use a different filename, so I enforced saving and showing at the same time.

For instance, we could save and show in Jupyter (is this a better name? because we are effectively showing in Jupyter, right? I don't know LOL. I guess evcxr is just a middleman...):

Instead of:

plot.save(...)?
plot.show_in_ivcxr(...)

We would have:

plot.save_and_show_in_jupyter(...)?
wangjiawen2013 commented 2 weeks ago

Hi, there are several styles we can consider:

I prefer both save_and_show_in_jupyter() and evcxr_figure_with_saving. Let's see what the author of evcxr suggests. I have refered this issue to him.

davidlattimore commented 2 weeks ago

I don't have any strong opinions. Naming things is hard.

I assume some of the crates wouldn't have save in the name because they don't need to save a file in order to show it - i.e. they just print out the image data directly to stdout without creating any files.

I assume saving is necessary due to the way plotpy works. If the image were saved to a temporary file that's subsequently deleted, then that seems somewhat like an implementation detail, so maybe wouldn't need to be in the method name.

cpmech commented 2 weeks ago

Thank you both for the feedback.

It makes sense to simply call show(), knowing that a temporary file is created.

Now, on version 1.6.0, we have two functions (one existed already and has been renamed):

Both functions save a temporary file automatically, so the user won't need to call save beforehand.

wangjiawen2013 commented 2 weeks ago

I see it! I tested it and it worked. And here is a typo in line 1131 (src/plot.rs), evcxr should be jupyter now (and also in the readme). image

readme: image

wangjiawen2013 commented 2 weeks ago

And .save(path)? in the code is not needed now.

// set the python path
let python = "where-is-my/python";

// set the figure path and name to be saved
let path = "my-figure.svg";

// plot and show in a Jupyter notebook
let mut plot = Plot::new();
plot.set_python_exe(python).set_label_x("x").set_label_y("y");
plot.show_in_jupyter(path)?;

The figure will be saved in the path automatically when showing.

cpmech commented 2 weeks ago

Thank you. This has been fixed in version 1.6.1