-
Notifications
You must be signed in to change notification settings - Fork 224
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
Implement image/png repr #343
Conversation
js/src/mpl_widget.js
Outdated
@@ -186,7 +188,11 @@ export class MPLCanvasModel extends widgets.DOMWidgetModel { | |||
this.image.src = image_url; | |||
|
|||
// Tell Jupyter that the notebook contents must change. | |||
this.send_message('ack'); | |||
if (!this.acknowledged_rendered) { | |||
this.send_message('ack'); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why do we need a round-trip to the front-end??
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It looks like we were trying to update the mime bundle with an "update display" message, but honnestly I don't remmember.
We should probably try to keep the PR as simple as possible for now...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I tried implementing it without the round-trip but I wasn't able. I need to look deeper into that.
865af81
to
b5f42aa
Compare
Yes, that is expected as per our discussion on data type priority and the html renderer. |
@ianhi I was not aware of this binder link for PRs, is this really using a dev installation of ipympl? I see ipympl in the |
Relies on jupyter/notebook#6181 and jupyter-widgets/ipywidgets#3280 for Jupyter Notebook |
:/ indeed it seems to be wrong. Ideally the bot that commented gives you a link to binder based on the PR in question. |
Testing locally it seems that this doesn't work on jlab 3.0.14 but does on 3.1.12 so something in rendering priorities or response to errors changed between 3.0 and 3.1? potential problem: If I understand correctly this approach works because jlab falls back on the lower priority mimetypes when there is an error loading the widget state. This error shows up because the full widget state wasn't saved, but if you check the (Somewhere I've written down why I think this is happening and how it might be fixed, I'll try to find that) |
Yes, that should be the intended behavior. We could fix this by including the png data as part of the widget model. |
nbviewer and nbconvert should take this into account if this gets merged: jupyter/nbconvert#1643 |
ohhh one more thing about this approach. I think we will need to call update_display on every draw call (or more parsimoniously whenever the notebook is saved) because otherwise you don't capture any updates to the figure that happen after the initial display call (panning, zooming, adding elements, manipulating with sliders, etc) Can widgets listen to notebook save events? I think updating the embedded png on saving is more reasonable than on every draw in order to avoid the flickering you described. |
Yeah. Though
Unfortunately not on the Python side. Technically, the kernel doesn't even know what a Notebook is. I'm tempted to say we could ignore this particular issue for now. As what we have is already quite a big improvement. And other Matplotlib backends are also not able to save the latest state of the plot without an |
Now using a This seems to work nicely, though there is still a bit of polishing to do. |
cc. @ianhi @SylvainCorlay @tacaswell This seems to work nicely in JupyterLab now! It makes ipympl closer to the inline backend in behavior and implementation.
We can merge this PR now and not wait for |
Let's get this in as it is a net improvement over the current situation, and tag a patch release of ipympl. |
Let's make a minor release instead, as the API changes a tiny bit: it's not |
Placing show in an output widget shoulds still work as expected though. |
Thanks for the persistence on this one! Sounds like it was tricky... |
# Figure width in pixels | ||
pwidth = (self.canvas.figure.get_figwidth() * | ||
self.canvas.figure.get_dpi()) | ||
# Scale size to match widget on HiDPI monitors. | ||
if hasattr(self.canvas, 'device_pixel_ratio'): # Matplotlib 3.5+ | ||
width = pwidth / self.canvas.device_pixel_ratio | ||
else: | ||
width = pwidth / self.canvas._dpi_ratio | ||
data = "<img src='data:image/png;base64,{0}' width={1}/>" | ||
data = data.format(b64encode(buf.getvalue()).decode('utf-8'), width) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@martinRenou why is it ok to remove this dpi scaling? It seems like we will now have imperfect behavior on hi dpi displays.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This might have been a mistake, we should open an issue to track this
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'll do it, actually. If I understand correctly, the PNG doesn't get saved at high res.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Note: we should not determine the dpi based on the browser because it could differ between clients.
It should be a fixed value.
I can see this making #290 harder because now figures aren't shown until the end of cell execution? Or maybe that can be made to work with an explicit call to |
Yes, I actually think that the interactive mode ( |
@nvaytet, I'd open a new issue - but for what it is worth, I have the same problem as you.... |
Follow-up of #59
Should fix #150, and fix #16
cc. @ianhi @SylvainCorlay @tacaswell
This seems to properly work in JupyterLab, but we need to push a fix to ipywidgets (and notebook) to have it working in classic Jupyter Notebook as well.