#!/usr/bin/env python # coding: utf-8 # Python has a large collection of plotting libraries and while any content that rendens in a Jupyter Notebooks will render in Jupyter-flex dashboards there are some things to consider for plots to look the best they can. # # ## Interactive (JS) libraries # # Since Jupyter-flex dashboards have a web frontend, either static `.html` files or a running webserver, in general any library that outputs a web based plot will look better, this includes: [Altair](https://altair-viz.github.io/), [plotly](https://plot.ly/python/), [Bokeh](https://docs.bokeh.org/en/latest/index.html) and [bqplot](https://github.com/bloomberg/bqplot). # ## Responsive # # For plots to look great in flex dashboards they should be responsive, that means that they should ocupy all the space that the parent html components has instead of having a static width and heigth. # # A responsive behaviour is usually not the default for most plotting libraries and but it's very easy to change this. # The way to do this differs from library to library here are some tips to make this happen in the libraries that we test more. # # We include some CSS as part of the library to make these popular plotting libraries behave better in the dashboards. # ### Altair # # Starting from [Altair](https://altair-viz.github.io/) version 4.0 it's possible to make a responsive chart width and height, one can do that by setting the `width` and `height` properties to `"container"`. # # For example take this example: # In[ ]: import altair as alt from vega_datasets import data # In[ ]: source = data.cars() plot = alt.Chart(source).mark_circle(size=60).encode( x='Horsepower', y='Miles_per_Gallon', color='Origin', tooltip=['Name', 'Origin', 'Horsepower', 'Miles_per_Gallon'] ) # In[ ]: plot # If we tag the previous cell with `body` then the size will be static and not responsive, to make it responsive we just add a bit of code: # In[ ]: plot.properties( width='container', height='container' ) None # This could make the plot very small on the Jupyter Notebook interface but will look great and expanded in a Flex dashboard. # # It's usually easy to add the call to `property()` once you are done with the Notebook or control this globally using a variable. # [![Jupyter-flex altair](/assets/img/screenshots/plots/altair-single.png "Altair single")](/examples/altair-single.html) # ### Plotly # # [Plotly](https://plot.ly/python/) requires no big changes thanks to the some extra code and styling included in Jupyter-flex. # We can make things look a bit better by changing the margin of the plot. # # For example a simple plot that uses `plotly.express`: # In[ ]: import plotly.express as px import plotly.graph_objects as go # In[ ]: margin = go.layout.Margin(l=20, r=20, b=20, t=30) # In[ ]: df = px.data.iris() fig = px.scatter(df, x="sepal_width", y="sepal_length") fig.update_layout(margin=margin) fig # [![Jupyter-flex plotly](/assets/img/screenshots/plots/plotly-single.png "Plotly single")](/examples/plotly-single.html) # # # ### Bokeh # # Using [Bokeh](https://docs.bokeh.org/en/latest/index.html) plots in Jupyter-flex dashboard requires two things: # # 1. One `meta` tag in the cell that does `output_notebook()` to embed the bokeh JS code in the notebook. The `meta` tag will add that cell to the dashboard `.html` with the `display: none;` style. # 2. Add `sizing_mode="stretch_both"` to the Bokeh `figure()` call # # Lets look at this example Notebook: # In[ ]: import numpy as np from bokeh.plotting import figure, show, output_notebook output_notebook() # In[ ]: x = np.linspace(0, 4 * np.pi, 100) y = np.sin(x) # In[ ]: fig = figure() fig.line(x, y) show(fig) # In[ ]: fig = figure(sizing_mode="stretch_both") fig.line(x, y) # Similar to what happens in Altair we see that the plot might not look its best well in the Jupyter Notebook interface but renders beautifully in the final flex dashboard. # # It's usually easy to add the `sizing_mode="stretch_both"` code once you are done with the Notebook or control this globally using a variable. # # [![Jupyter-flex bokeh](/assets/img/screenshots/plots/bokeh-single.png "Bokeh single")](/examples/bokeh-single.html) # # # ### bqplot # # [bqplot](https://github.com/bloomberg/bqplot) is a plotting library that is 100% based on ipywidgets and therefore works great with them, it also required no major changes for the plots to look great on Jupyter-flex dashboards. # # Once simple example: # In[ ]: import numpy as np from bqplot import * # In[ ]: size = 100 np.random.seed(42) x_data = range(size) y_data = np.random.randn(size) y_data_2 = np.random.randn(size) y_data_3 = np.cumsum(np.random.randn(size) * 100.) # In[ ]: x_ord = OrdinalScale() y_sc = LinearScale() bar = Bars(x=np.arange(10), y=np.random.rand(10), scales={'x': x_ord, 'y': y_sc}) ax_x = Axis(scale=x_ord) ax_y = Axis(scale=y_sc, tick_format='0.2f', orientation='vertical') Figure(marks=[bar], axes=[ax_x, ax_y], padding_x=0.025, padding_y=0.025) # [![Jupyter-flex bqplot](/assets/img/screenshots/plots/bqplot-single.png "bqplot single")](/examples/bqplot-single.html) # # # ## Updating plots # # When using Voila and IPython widgets to dynamically update the content of plots in the dashboard there are some things to consider: # # 1. If the library has native support for IPython Widgets then it's a good idea to use that functionality, this is possible in: # 1. bqplot because the library is designed that way # 2. plotly using [Figure Widget](https://plot.ly/python/figurewidget/) # 2. If the library doesn't have native support for ipywidgets it's still possible to use it and update the dashboard the using [Output Widgets](https://ipywidgets.readthedocs.io/en/latest/examples/Output%20Widget.html) # # When using Output Widgets remember to call `clear()` before displaying new content, for example: # # ``` # out = widgets.Output() # # with out: # out.clear_output() # display(...) # ``` # # It's common to have the `with out: ...` code inside a callback function from a widgets `observe()` method. # ## Examples # # More examples that show the plotting libraries in action and other examples that show how to have more dyamic dashboards with ipywidgets: # #
#
# # Jupyter-flex: altair # #
Altair plots
#
#
# # Jupyter-flex: Plotly Plots # #
Plotly plots
#
#
# # Jupyter-flex: Bokeh Plots # #
Bokeh plots
#
#
# #
#
# # Jupyter-flex: bqplot # #
bqplot plots (runs in mybinder.org)
#
#
# # Jupyter-flex: Movie Explorer # #
Movie Explorer (runs in mybinder.org)
#
#
# # Jupyter-flex: Wealth of Nations # #
Wealth of Nations (runs in mybinder.org)
#
#
# #
#
# # Jupyter-flex: Iris Clustering # #
Iris clustering (runs in mybinder.org)
#
#
#
#
#
#
# In[ ]: