Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make compatible with plotly 3.0 #2864

Closed
philippjfr opened this issue Jul 7, 2018 · 7 comments · Fixed by #3194
Closed

Make compatible with plotly 3.0 #2864

philippjfr opened this issue Jul 7, 2018 · 7 comments · Fixed by #3194

Comments

@philippjfr
Copy link
Member

No description provided.

@philippjfr philippjfr added this to the v1.11 milestone Jul 7, 2018
@jonmmease
Copy link
Collaborator

Hi @philippjfr , let me know if you all have any migration questions. Glad to see you're interested in making the jump!

Also, I'm not very familiar with how holoviews pulls off its interactive magic, but I wonder what it would take to display plotly figures in the notebook using the new FigureWidget ipywidgets class (rather than iplot). If this were possible, I think FigureWidget has the hooks needed to support dynamic maps, datashader resampling, streaming data, and some of the interactive stream types (selection, hover, and tap).

I don't expect anyone to have time to work on this in the near future, but I'd be interested to get your take on it and maybe sketch out a high-level outline of what it could look like.

@jbednar
Copy link
Member

jbednar commented Jul 23, 2018

That's tricky, as FigureWidget is an ipywidget, and thus ties everything to Jupyter notebooks. In general we use mechanisms that work in or outside of a Jupyter context. @philippjfr can comment on the details in a week or so from now, but in the meantime, is there a lower-level interface to what FigureWidget does that does not depend explicitly on Jupyter?

@jonmmease
Copy link
Collaborator

The Python portion of FigureWidget has the job of converting plot mutation operations (property assignment, trace addition, etc.) into messages that correspond to Plotly.js method calls. Then it accepts messages from the front-end with information about the default properties and user interaction events.

The JavaScript portion of FigureWidget is mostly concerned with accepting these messages, calling the appropriate Plotly.js methods, and then doing a bunch of work to keep the single model in sync with potentially multiple views.

Here's what I was imagining:

A plotly_widget backend that only works in the Jupyter context. The display of a holoviews object would be itself an ipywidgets layout with a FigureWidget inside along with other ipywidget interaction controls if needed. In principal this could be a pure Python implementation (No additional JavaScript or Jupyter extensions), where the Python side just wires up callbacks on a FigureWidget and other ipywidgets to implement the holoviews specification.

@philippjfr
Copy link
Member Author

Thanks for chiming in here @jonmmease I suspect your help will be immensely helpful. We've had the concept of Jupyter based renderer modes in the past, e.g. to support nbagg in matplotlib, so I have no particular objection to providing both notebook based and static export rendering capabilities.

One question I have is how easy it will be to switch between a regular static Figure and a FigureWidget, are the APIs identical such that I can simply switch one out for the other, at least when creating the initial figure? I suspect when updating an existing plot the FigureWidget based approach will make things a lot easier while the Figure based approach will probably just rerender the whole plot each time (which I think is what it is doing now).

@jonmmease
Copy link
Collaborator

Thanks for your thoughts @philippjfr.

Is the idea that a Jupyter-based capability would use paramnb to generate ipywidgets controls, and then put them in an ipywidgets layout with a FigureWidget? Whereas the static export capability would use parambokeh and then render the JSON representation of plotly figures using Plotly.js directly? Do you imagine that these would be separate backend extensions (plotly vs plotly_widget), or just context dependent modes?

Yes, the version 3 Figure and FigureWidget classes have an identical API (FigureWidget is basically a subclass of Figure and ipywidgets.DOMWidget). The differences between the version 2 and version 3 API is summarized in the migration guide: https://github.com/plotly/plotly.py/blob/master/migration-guide.md.

In this case, do you think most of the plotly.py logic could be common between the static and notebook modes?

Again, I don't have time to do much more than talk about the idea at this point. But I could definitely see a full-featured Plotly ipywidget backend for HoloViews being pretty exciting and valuable to the Plotly, PyViz, and Jupyter communities. So let's at least keep talking about it 🙂

As a side note: for updating the entire figure with the static approach, the (relatively) new Plotly.react method can make things a bit faster (https://plot.ly/javascript/plotlyjs-function-reference/#plotlyreact). It has the same API as Plotly.newPlot but it computes diffs internally to do things more efficiently.

@philippjfr
Copy link
Member Author

Thanks for the quick reply!

Is the idea that a Jupyter-based capability would use paramnb to generate ipywidgets controls, and then put them in an ipywidgets layout with a FigureWidget? Whereas the static export capability would use parambokeh and then render the JSON representation of plotly figures using Plotly.js directly?

No this would be independent of any work in paramnb and parambokeh, although we should of course figure out how they will integrate there.

Do you imagine that these would be separate backend extensions (plotly vs plotly_widget), or just context dependent modes?

That's definitely one option but we also have the concept of renderer modes which let you set how the rendering should work. This would look something like this:

# static renderering
hv.extension('plotly')

# widget based rendering
hv.extension('plotly:nb')

In this case, do you think most of the plotly.py logic could be common between the static and notebook modes?

Yes I think so, the plot classes would simply instantiate either a Figure or a FigureWidget depending on the renderer mode. The main question is how the syncing works but this is actually quite analogous to the server mode we have in bokeh, where all the syncing of plot properties happens automatically and we don't have to compute the diffs manually.

I'd have to look at the new Plotly.react code but by the sound of it I think we can make all this work pretty cleanly.

@jonmmease
Copy link
Collaborator

Ok, yeah, the rendering mode approach makes a lot of sense (at lease from an end-user perspective).

For syncing in the notebook mode I'm guessing that it would be helpful to have a FigureWidget method that fully replaces the entire state of the figure and syncs it to the front-end widget. Something like:

import plotly.graph_objs as go
fig = go.FigureWidget(...)

# Do stuff
new_fig = go.Figure({'data': [...], 'layout': {...}})
fig.reset(new_fig)

We don't have this yet (our focus so far has been on syncing modifications to nested sub-properties), but it wouldn't be hard to add and would be useful in other contexts as well.

If you have a chance, could you point out where HoloViews performs (or requests) this synchronization for the Bokeh backend in server mode?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants