Skip to content

Matplotlib Jupyter widget follow-up #6414

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

Closed
izaid opened this issue May 12, 2016 · 15 comments
Closed

Matplotlib Jupyter widget follow-up #6414

izaid opened this issue May 12, 2016 · 15 comments

Comments

@izaid
Copy link

izaid commented May 12, 2016

This is a follow-up issue to #5754, in which we widgetized the Matplotlib nbagg backend for Jupyter notebooks.

I'm using this pretty extensively, so I'm happy to report issues I find here. I'd also like to personally fix them, but I will need some guidance on how to do that. So far, I've found 3 things that we should fix:

  1. The Matplotlib widget does not respect layout widgets as much as it should.

If I place widgets in layouts, they are autoscaled to not run over the sides of the notebook (for instance). Matplotlib always defaults to a particular size, which means it often runs over. See the below screenshot
screenshot from 2016-05-12 13-29-43

  1. The titlebars seem unnecessary much of the time.

I suspect most users in notebooks don't really care about having a titlebar in the figure. We should make it easy to turn this off. Maybe this should be the default? Is it already possible to do so?

  1. Getting the widget that needs to be added to Jupyter layouts is mysterious.

To actually put the widget in a layout, one needs to get fig.canvas.manager.canvas and add that to a layout. That's not really the API we want, is it? Is there a way we can make this easier?

Pinging who I think are the relevant people: @blink1073 @tacaswell @mdboom @SylvainCorlay

@jenshnielsen
Copy link
Member

Other issues that I noticed while working on it.

The figure closing both from the Python side and from the widget is not respected as document in the UAT notebook

I.e.

Do something like
One cell

plt.plot(range(10))

close the figure widget.

and execute something from a different cell:

plt.plot(range(100)) 

And observe that no new figure is created.

Creating a figure attached to an ipywidte interact and exporting the figure followed by touching the slider widget leads to lot of blank white space.

@blink1073
Copy link
Member

I'm pretty well saturated at this point, but can offer a few suggestions:

  1. There must be a way that widgets in a ipywidgets layout are notified of changes that could be hooked in to.
  2. The figure title can be used to show that two figures are in fact identical.
  3. This is the canonical way of embedding a matplotlib figure into another GUI (same way it is done in Qt).

@SylvainCorlay
Copy link
Member

Regarding 1 we are currently using the scroll event hack in bqplot to
detect resize events.

It should not be necessary anymore with phosphor layout. I think that we
could use the same trick with the matplotlib widget.
On May 12, 2016 7:20 PM, "Steven Silvester" notifications@github.com
wrote:

I'm pretty well saturated at this point, but can offer a few suggestions:

  1. There must be a way that widgets in a ipywidgets layout are notified of
    changes that could be hooked in to.
  2. The figure title can be used to show that two figures are in fact
    identical.
  3. This is the canonical way of embedding a matplotlib figure into another
    GUI (same way it is done in Qt).


You are receiving this because you were mentioned.
Reply to this email directly or view it on GitHub
#6414 (comment)

@izaid
Copy link
Author

izaid commented May 12, 2016

Okay, so here is my attempt so far to solve 1). What I did was add observers to some traits in the Matplotlib widget's layout, e.g. https://github.com/ipython/ipywidgets/blob/master/ipywidgets/widgets/widget_layout.py#L31 -- this works for simple things, like changing the width and height, but not sure how we'd extend it to the whole flex layout.

@SylvainCorlay, are you saying I can get away with just a single event with some scroll event hack? Can you point me to where in bqplot you do this?

@SylvainCorlay
Copy link
Member

@izaid sorry for the late reply. I spent most of my time in airports in the last 3 days...

The problem you have is that the browser does not provide resize events for DOM elements. (There is only a window.resize event). In the case of a CSS flexbox, there are multiple other reasons than a window resize that can cause things to relayout, and trying to catch them all is not realistic.

In the case of libraries like phosphor js, which is the one used for the new jupyterlab, all dom elements are sized and positioned absolutely and we know when things are resized. So in the bright future of JupyterLab, things will be better.

In the meantime (before JupyterLab is released and becomes the main notebook) there are ways to emulate DOM element resize events, such as the one we use in the bqplot PR bqplot/bqplot#131, which is not great in terms of performance but does the job.

I guess that this could be used for matplotlib too.

@SylvainCorlay
Copy link
Member

SylvainCorlay commented May 15, 2016

Regarding the matplotlib widget, I believe that the [notebook/web] backend and the widget wrapping should be in a different GitHub repo than the main matplotlib one.

We now have a cookiecutter repo for custom Jupyter widget library https://github.com/jupyter/widget-cookiecutter. The thing is that Jupyter is a fast moving target and you probably want the notebook integration to evolve independently from the matplotlib release cycle. Besides, it will make it easy to add the support for Jupyterlab when it is released.

cc @blink1073 @jasongrout

@tacaswell
Copy link
Member

I am nominally 👍 on pulling the notebook backend out of the mainline. Maybe pull the inline backend out of IPython as will and put both of them in a repo in the Jupyter/IPython part of the world?

I am a +0 on pulling the web backend out, it runs its own tornado server and has a independent js front end, but I think that some of the js is reused in the notebook widget so splitting them up make less sense so pulling them out together and putting them in a repo under the mpl organization makes sense (so long as there is still a way to have mpl re-import the web backend without picking up a hard jupyter dependency).

@blink1073
Copy link
Member

@tacaswell, I talked with Sylvain about this today. We could create a separate package under matplotlib that has the { web, inline, notebook } backends and would not depend on Jupyter unless using the inline or notebook backends.

@izaid
Copy link
Author

izaid commented May 16, 2016

I'm +1 to this as well. What @SylvainCorlay didn't mention is that he's already done it -- https://github.com/sylvaincorlay/jupyter-matplotlib ;)

I've got this working now, maybe it makes more sense to work off of that?

@SylvainCorlay
Copy link
Member

@tacaswell besides, the thing is that as soon as Matplotlib follows the jupyter-js-widgets practices, embedding live matplotlib figures in any webpage with or without a backend will come for free.

Example here with the ipyleaflet widget:

screencast

I wonder if you will want to keep maintaining a matplotlib specific tornado based server...

@tacaswell
Copy link
Member

tacaswell commented May 16, 2016

Fair enough

@SylvainCorlay I will give you enough permissions to move that repo into the mpl namespace.

@izaid
Copy link
Author

izaid commented May 16, 2016

Okay, some progress here. First, the trick @SylvainCorlay is indeed very good at getting resize events, so that's great.

The problem here, however, seems to be that the width and height passed to the resize event (including the existing ones) is not what I would expect. If I manually set the width of the widget in Jupyter, the width passed to the resize event is very different. It does change, just not in the ways I would expect...

Edit: And, to be clear, it's not a pixels vs inches thing. Everything seems to be clearly in pixels.

@stonebig
Copy link
Contributor

any news ?

@tacaswell
Copy link
Member

https://github.com/matplotlib/jupyter-matplotlib exists, it works for the notebook and integration with jupyter lab is on-going.

@jklymak
Copy link
Member

jklymak commented Jan 17, 2021

I'm going to close this as thoroughly subsumed by ipympl. But feel free to re-open if I've misunderstood.

@jklymak jklymak closed this as completed Jan 17, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

8 participants