Open chapmanbe opened 4 years ago
I believe that altair rendering in ipywidgets only works with the mimetype renderer; see https://altair-viz.github.io/user_guide/display_frontends.html#displaying-in-jupyterlab
Thanks. That fixes the issue with jupyterlab 2.1.0. I'm currently failing in getting the vega5 extension to install on my jupyterlab 1.25 system. Wish I could just update it to 2.10!
Brian
EDIT: Better, HTML-renderer-using solution below.
For anyone else who Googles this up: in Notebook, the trick is to
jupyter nbextension install --sys-prefix --py vega
jupyter nbextension enable vega --py --sys-prefix
pip install altair_saver
alt.renderers.enable('notebook')
.display()
within the Output
context managerAll together,
jupyter nbextension install vega --py --sys-prefix
jupyter nbextension enable vega --py --sys-prefix
pip install altair_saver
import altair as alt
import ipywidgets as widgets
from vega_datasets import data
alt.renderers.enable('notebook', embed_options={'actions': False})
cars = data.cars()
children = [widgets.Output() for _ in range(3)]
for out in children:
with out:
c = alt.Chart(cars).mark_point().encode(
x='Horsepower',
y='Miles_per_Gallon',
color='Origin')
c.display()
widgets.HBox(children)
Interactivity is a bit laggy, seemingly because of the ye olde notebook
renderer as opposed to the modern, default html
one.
Actually, turns out the HTML renderer works too! This comment put me onto the solution: you need to display
the widget before .display()
ing the plot:
import altair as alt
import ipywidgets as widgets
from vega_datasets import data
from IPython.display import display
cars = data.cars()
children = [widgets.Output() for _ in range(3)]
box = widgets.HBox(children)
display(box)
for out in children:
with out:
c = alt.Chart(cars).mark_point().encode(
x='Horsepower',
y='Miles_per_Gallon',
color='Origin').interactive()
c.display()
Bit prescriptive but hey, it works.
@andyljones That last snippet was really helpful. I almost ended up with manually taking the javascript out in something like:
from IPython.display import HTML, display
from IPython.utils import io
def chart_to_widget(chart):
with io.capture_output(display=True) as captured:
chart.display()
html = captured.outputs[0].data['text/html']
html, js = html.strip().split("\n", maxsplit=1)
return widgets.HTML(html), js
chart = plot_example('blue')
h1, js1 = chart_to_widget(chart)
chart = plot_example('green')
h2, js2 = chart_to_widget(chart)
tab = widgets.Tab()
tab.children = [h1, h2]
tab.set_title(0, 'figure 1')
tab.set_title(1, 'figure 2')
display(tab)
display(HTML(js1 + js2))
@jakevdp Do you think is useful adding @andyljones' snippet to the docs the help users of ipywidgets
work with altair?
I am having an issue with Altair in Jupyterlab that I was hoping people could provide some help on. I confess that I have little understanding of JavaScript and the overall construction of the ecosystems. I have created several notebooks that provide interactive interrogation of a data set. Based on web searches, in order to facilitate the interaction I use the following code to display the Altair chart:
Where
em_plots_out
is an instance ofipywidgets.Output
I have several notebooks that use similar code. However, I cannot have the notebooks open at the same time. If I open a new notebook, I see an error message displayed below each widget:
Error displaying widget: model not found
and the JavaScript console shows errors of the following sort:renderer.js:45 Error: widget model not found at k.get_model (manager.js:375) at h.renderModel (renderer.js:38)
If I close all other notebooks with similar code and shutdown all the kernels, then opening any individual notebook and restarting the kernel works fine. If I open a second notebook, then the first notebook will start using the Output widget for the second notebook. I have seen the output from code in one notebook being drawn in second notebook even when there is no Python kernel for the second notebook.
I have also tried putting the widgets in the same notebook. Similar behavior. When I've only run the cell with the first output widget defined, everything seems to work fine, although the JavaScript console shows this error:
VM64094:17 Uncaught ReferenceError: vegaEmbed is not defined at <anonymous>:17:8 at t.attachWidget (panellayout.js:215) at t.insertWidget (panellayout.js:118) at k._insertOutput (widget.js:392) at k.onModelChanged (widget.js:216) at m (index.js:478) at Object.c [as emit] (index.js:435) at e.emit (index.js:108) at f._onListChanged (model.js:231) at m (index.js:478) (anonymous) @ VM64094:17 t.attachWidget @ panellayout.js:215 t.insertWidget @ panellayout.js:118 _insertOutput @ widget.js:392 onModelChanged @ widget.js:216 m @ index.js:478 c @ index.js:435 e.emit @ index.js:108 _onListChanged @ model.js:231 m @ index.js:478 c @ index.js:435 e.emit @ index.js:108 push @ observablelist.js:135 _add @ model.js:207 add @ model.js:128 add @ output.js:62 _msgHook @ output.js:17 process @ future.js:338 async function (async) process @ future.js:321 _handleIOPub @ future.js:212 handleMsg @ future.js:186 _handleMessage @ default.js:1087 (anonymous) @ default.js:94 Promise.then (async) _onWSMessage @ default.js:91 VM64095 vega-embed@6:26 Uncaught TypeError: Cannot read property 'version' of undefined at VM64095 vega-embed@6:26 at VM64095 vega-embed@6:1 at VM64095 vega-embed@6:1
When I run the code with the object (an ipywidget Box containing multiple widgets) containing the second Output widget, the second object "takes control" of the first Output widget and draws all its output in the first output. Both objects work, fine they just both use the Output that was activated first.
This seems to be Altair specific because each object/widget.Box contains Output widgets for displaying Pandas DataFrames slices, both of which work fine.
Environment: This behavior has been seen on two different systems.
First system:
jupyterlab=='2.1.0' ipywidgets=='7.5.1' altair=='4.1.0' @jupyter-widgets/jupyterlab-manager v2.0.0 enabled OK
Second system:
jupyterlab=='1.2.5' ipywidgets=='7.5.1' altair=='4.1.0' @jupyter-widgets/jupyterlab-manager v2.0.0 enabled OK @jupyter-widgets/jupyterlab-manager v1.1.0 enabled OK
Thanks,
Brian