plotpy icon indicating copy to clipboard operation
plotpy copied to clipboard

evcxr_jupyter support

Open wangjiawen2013 opened this issue 1 year ago • 14 comments
trafficstars

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

wangjiawen2013 avatar Aug 13 '24 10:08 wangjiawen2013

Hi, unfortunately, evcxr is not supported.

cpmech avatar Aug 13 '24 21:08 cpmech

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 avatar Aug 14 '24 09:08 wangjiawen2013

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.

wangjiawen2013 avatar Aug 14 '24 09:08 wangjiawen2013

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.

cpmech avatar Aug 14 '24 10:08 cpmech

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.

wangjiawen2013 avatar Aug 15 '24 01:08 wangjiawen2013

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?

cpmech avatar Aug 19 '24 06:08 cpmech

It worked in my windows10 desktop and centos7 server.

wangjiawen2013 avatar Aug 19 '24 08:08 wangjiawen2013

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(...)?

cpmech avatar Aug 21 '24 22:08 cpmech

Hi, there are several styles we can consider:

  • Plotly.rs uses the function plot.lab_display() and Plot::notebook_display() to show figures in Jupyter.
  • Plotters uses the function evcxr_figure() to only show figures in Jupyter, while uses evcxr_figure_with_saving() to save and show the figures at the same time, which is the case you care.
  • Showata just uses the function data.show() simply.
  • Petgraph just uses the function draw_graph() to draw a graph in evcxr_jupyter.

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.

wangjiawen2013 avatar Aug 22 '24 02:08 wangjiawen2013

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.

davidlattimore avatar Aug 22 '24 03:08 davidlattimore

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):

  • show(...) which shows the figure using Python/Matplotlib standard backend
  • show_in_jupyter(...), which shows the figure in Jupyter via evcxr

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

cpmech avatar Aug 22 '24 04:08 cpmech

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 avatar Aug 22 '24 06:08 wangjiawen2013

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.

wangjiawen2013 avatar Aug 22 '24 07:08 wangjiawen2013

Thank you. This has been fixed in version 1.6.1

cpmech avatar Aug 22 '24 07:08 cpmech