Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
102 changes: 30 additions & 72 deletions docs/book/src/fundamentals/jupyter_support.md
Original file line number Diff line number Diff line change
@@ -1,109 +1,67 @@
# Jupyter Support

As of version `0.7.0`, [Plotly.rs](https://github.com/plotly/plotly.rs) has native support for the [EvCxR Jupyter Kernel](https://github.com/google/evcxr/tree/master/evcxr_jupyter).
As of version `0.7.0`, [Plotly.rs](https://github.com/plotly/plotly.rs) has native support for the [EvCxR Jupyter Kernel](https://github.com/evcxr/evcxr/tree/main/evcxr_jupyter).

Once you've installed the required packages you'll be able to run all the examples shown here as well as all [the recipes](../recipes.md) in Jupyter Lab!

> Tested against JupyterLab 4.4.7.

## Installation
It is assumed that an installation of the [Anaconda](https://www.anaconda.com/products/individual) Python distribution is already present in the system. If that is not the case you can follow these [instructions](https://www.anaconda.com/products/individual) to get up and running with `Anaconda`.

```shell script
conda install -c plotly plotly=4.9.0
conda install jupyterlab "ipywidgets=7.5"
Install the plotly package and JupyterLab using pip or conda:

**pip**
```shell
pip install plotly jupyterlab
```

optionally (or instead of `jupyterlab`) you can also install Jupyter Notebook:
```shell script
conda install notebook
**conda**
```shell
conda install -c conda-forge plotly jupyterlab
```

Although there are alternative methods to enable support for the [EvCxR Jupyter Kernel](https://github.com/google/evcxr/tree/master/evcxr_jupyter), we have elected to keep the requirements consistent with what those of other languages, e.g. Julia, Python and R. This way users know what to expect; and also the folks at [Plotly](https://plotly.com/python/getting-started/#jupyter-notebook-support) have done already most of the heavy lifting to create an extension for Jupyter Lab that works very well.
No separate JupyterLab extension install is required — the plotly renderer is bundled
with the plotly package (5.x+) and JupyterLab picks it up automatically.

Run the following to install the Plotly Jupyter Lab extension:
```shell script
jupyter labextension install jupyterlab-plotly@4.9.0
```
> **Note:** `anywidget` is required for Python's `FigureWidget` interactive features
> but is **not** needed for the Rust `evcxr_display()` path.

Once this step is complete to make sure the installation so far was successful, run the following command:
```shell script
jupyter lab
```
Next, install the EvCxR Jupyter Kernel:

Open a `Python 3` kernel copy/paste the following code in a cell and run it:
```python
import plotly.graph_objects as go
fig = go.Figure(data=go.Bar(x=['a', 'b', 'c'], y=[11, 22, 33]))
fig.show()
```
You should see the following figure:
<div id="jupyter_lab_demo_bar_chart_python" class="plotly-graph-div" style="height:100%; width:100%;"></div>
<script type="text/javascript">
window.PLOTLYENV=window.PLOTLYENV || {};
if (document.getElementById("jupyter_lab_demo_bar_chart_python")) {
var d3 = Plotly.d3;
var image_element= d3.select('#image-export');
var trace_0 = {"x":["a","b","c"],"y":[11,22,33],"type":"bar"};
var data = [trace_0];
var layout = {};
Plotly.newPlot('jupyter_lab_demo_bar_chart_python', data, layout, {"responsive": true});
};
</script>

Next you need to install the [EvCxR Jupyter Kernel](https://github.com/google/evcxr/tree/master/evcxr_jupyter). Note that EvCxR requires [CMake](https://cmake.org/download/) as it has to compile ZMQ. If [CMake](https://cmake.org/download/) is already installed on your system and is in your path (to test that simply run ```cmake --version``` if that returns a version you're good to go) then continue to the next steps.

In a command line execute the following commands:
```shell script
```shell
cargo install evcxr_jupyter
evcxr_jupyter --install
```

If you're not familiar with the EvCxR kernel it would be good that you at least glance over the [EvCxR Jupyter Tour](https://github.com/google/evcxr/blob/master/evcxr_jupyter/samples/evcxr_jupyter_tour.ipynb).

## Usage

Launch Jupyter Lab:
```shell script

```shell
jupyter lab
```

create a new notebook and select the `Rust` kernel. Then create the following three cells and execute them in order:
Create a new notebook and select the `Rust` kernel. Add the plotly dependency and
display a plot:

```shell script
:dep ndarray = "0.15.6"
:dep plotly = { version = ">=0.7.0" }
**Cell 1**
```

```rust
extern crate ndarray;
extern crate plotly;
extern crate rand_distr;
:dep plotly = "0.14"
```

**Cell 2**
```rust
use ndarray::Array;
use plotly::common::Mode;
use plotly::layout::{Layout};
use plotly::{Plot, Scatter};
use rand_distr::{num_traits::Float, Distribution};
```

Now we're ready to start plotting!

```rust
let x0 = Array::linspace(1.0, 3.0, 200).into_raw_vec();
let y0 = x0.iter().map(|v| *v * (v.powf(2.)).sin() + 1.).collect();

let trace = Scatter::new(x0, y0);
let trace = Scatter::new(vec![1.0, 2.0, 3.0], vec![1.0, 4.0, 9.0]);
let mut plot = Plot::new();
plot.add_trace(trace);

let layout = Layout::new().height(525);
plot.set_layout(layout);

plot.lab_display();
format!("EVCXR_BEGIN_CONTENT application/vnd.plotly.v1+json\n{}\nEVCXR_END_CONTENT", plot.to_json())
plot.evcxr_display();
```
For Jupyter Lab there are two ways to display a plot in the `EvCxR` kernel, either have the plot object be in the last line without a semicolon or directly invoke the `Plot::lab_display` method on it; both have the same result. You can also find an example notebook [here](https://github.com/plotly/plotly.rs/tree/main/examples/jupyter/jupyter_lab.ipynb) that will periodically be updated with examples.

The process for Jupyter Notebook is very much the same with one exception; the `Plot::notebook_display` method must be used to display the plot. You can find an example notebook [here](https://github.com/plotly/plotly.rs/tree/main/examples/jupyter/jupyter_notebook.ipynb)
`evcxr_display()` works in both Jupyter Lab and Notebook. Alternatively you can
leave the plot on the last line of a cell without a semicolon for the same effect.

You can find a full notebook example
[here](https://github.com/plotly/plotly.rs/tree/main/examples/jupyter/jupyter_notebook.ipynb).
56 changes: 50 additions & 6 deletions plotly/src/plot.rs
Original file line number Diff line number Diff line change
Expand Up @@ -403,18 +403,28 @@ impl Plot {
tmpl.render().unwrap()
}

fn to_evcxr_notebook_format(&self) -> String {
format!(
"EVCXR_BEGIN_CONTENT text/html\n{}\nEVCXR_END_CONTENT",
self.to_jupyter_notebook_html()
)
}

fn to_evcxr_lab_format(&self) -> String {
format!(
"EVCXR_BEGIN_CONTENT application/vnd.plotly.v1+json\n{}\nEVCXR_END_CONTENT",
self.to_json()
)
}

/// Display plot in Jupyter Notebook.
pub fn notebook_display(&self) {
let plot_data = self.to_jupyter_notebook_html();
println!("EVCXR_BEGIN_CONTENT text/html\n{plot_data}\nEVCXR_END_CONTENT");
println!("{}", self.to_evcxr_notebook_format());
}

/// Display plot in Jupyter Lab.
pub fn lab_display(&self) {
let plot_data = self.to_json();
println!(
"EVCXR_BEGIN_CONTENT application/vnd.plotly.v1+json\n{plot_data}\nEVCXR_END_CONTENT"
);
println!("{}", self.to_evcxr_lab_format());
}

/// Displays the plot in Jupyter Lab; if running a Jupyter Notebook then use
Expand Down Expand Up @@ -875,6 +885,40 @@ mod tests {
plot.lab_display();
}

#[test]
fn lab_display_output() {
let plot = create_test_plot();
let output = plot.to_evcxr_lab_format();

assert!(output.starts_with("EVCXR_BEGIN_CONTENT application/vnd.plotly.v1+json\n"));
assert!(output.ends_with("\nEVCXR_END_CONTENT"));

let json_str = output
.strip_prefix("EVCXR_BEGIN_CONTENT application/vnd.plotly.v1+json\n")
.unwrap()
.strip_suffix("\nEVCXR_END_CONTENT")
.unwrap();
let json: serde_json::Value = serde_json::from_str(json_str).unwrap();
assert!(json.get("data").is_some());
assert!(json.get("layout").is_some());
}

#[test]
fn notebook_display_output() {
let plot = create_test_plot();
let output = plot.to_evcxr_notebook_format();

assert!(output.starts_with("EVCXR_BEGIN_CONTENT text/html\n"));
assert!(output.ends_with("\nEVCXR_END_CONTENT"));

let html = output
.strip_prefix("EVCXR_BEGIN_CONTENT text/html\n")
.unwrap()
.strip_suffix("\nEVCXR_END_CONTENT")
.unwrap();
assert!(html.contains("plotly"));
}

#[test]
fn plot_serialize_simple() {
let plot = create_test_plot();
Expand Down