-
-
Notifications
You must be signed in to change notification settings - Fork 7.9k
Existing FigureCanvasQT objects destroyed by call to plt.figure #14426
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
Comments
This bisects to #12637, and is essentially due to the fact that we now initialize ipython/matplotlib support when the first canvas is created (here, by I think we can actually remove the In the meantime you can probably get away with creating a figure and immediately closing it -- we only initialize ipython/matplotlib support once. |
Thanks for the information. I am subclassing FigureCanvasQT, so I would prefer to preempt the |
|
I think removing that |
It looks like the following workaround does suffice: add a call to (I still do think that we should not call |
Thanks for the suggestion, which I think would work. In the past few minutes, I have just found an alternative solution. I just have to monkey-patch the IPython InteractiveShell class to do nothing when there is a call to I haven't thought about this issue nearly as long as you, but I get the impression that the ultimate solution would have to come from IPython allowing alternative backends to be registered in some well-documented way. |
The way we are registering backends with IPython definitely borders API abuse, sorry for breaking things on your side. On the other hand, I would rather have as much of that code as possible living on Matplotlib's side, as cross-project coordination is a much harder problem... |
I remilestone to 3.2 as we have a workaround now, although I do think the API needs to be revisited on our side. |
I think the simplest short-term fix would be to add an optional keyword argument to the FigureCanvasBase to allow instances to skip the call to |
That doesn't seem much better than just documenting "call |
I am a little rushed at the moment, so I may be wrong about this, but I think the problem with calling |
As it is written right now, |
I must admit that I had been puzzled about how subsequent calls were suppressed. I didn't know what the |
I propose #14471 as a fix which avoids closing the figures if the backend switch is a no-op. @anntzer Documenting that import / instantiation order seems a bit brittle. @rayosborn I would much rather not have you monkey patching (some what selfishly as I suspect I'll be on both sides of that interaction sooner or later ;) ). |
I agree it's brittle. The problem of #14471 is that I could possibly imaging some people are actually (implicitly?) relying on switch_backend() to call close("all"), but I'll trust your judgment that the backcompat break is fine. |
Hmm, I may have miss-understood the source of the behavior change between 3.0 and 3.1. I thought it was a change to Could we put a guard in @rayosborn do you actually want your figures to be known to pyplot? |
(an important point is that ip.enable_matplotlib calls switch_backend) |
@tacaswell the NeXpy figures use a subclass of FigureCanvasQT, which ensures that pyplot at least knows they exist, e.g., they are included in |
My monkey patch is just to disable the redundant IPython call to |
But do you want this behavior? |
https://github.com/nexpy/nexpy/blob/8e83badf6d38092cfc6abaf5d53e1a162db8830c/src/nexpy/gui/plotview.py#L289 are the lines that let pyplot know your figures exist. If you dropped those lines the nexpy plots and the |
That's an interesting point. I'll think about that. It might be worth cutting the cord. |
@tacaswell, thanks for the suggestion. As you have seen, I already merged a NeXpy PR where I separate the NXPlotView and pyplot figures, and I think it's a big improvement, even without this issue, so it's had a very useful outcome. |
Bug report
Bug summary
For a number of years, I have been maintaining an interactive application that embeds subclassed FigureCanvasQT objects within a PyQt application. Up until Matplotlib v3.0.3., it was possible to create standard Matplotlib PyQt figures, i.e., using
plt.figure
within an embedded IPython shell, that coexist with the subclassed canvas objects. Now in Matplotlib v3.1.0, a call toplt.figure()
destroys all the other canvas objects.Unfortunately, I cannot debug this within Visual Studio since I am currently unable to install Matplotlib from the source. By going through the
new_figure_manager
code line by line, I can confirm that the windows are destroyed when callingFigureCanvasQT.__init__(figure)
, but not when callingFigureCanvasBase.__init__(figure)
, but I can't work out what triggers the destruction of the other windows. I presume the subclassed canvasses are not being registered somewhere, andpyplot
assumes they are no longer active, but I am hoping someone will show me where to look. This may not be a Matplotlib bug, but it's certainly an unwelcome side effect in my application.Code for reproduction
If you have
nexpy
installed (pip install nexpy
) and launch it, you can reproduce this from within the embedded IPython shell with the following, which creates a new subclassed window and then attempts to open a regularpyplot
window.:There are two figure numbers, because NeXpy automatically creates a window with a figure number of 1 when it is launched.
Actual outcome
A new window with an updated figure number is created but all other windows not created by
pyplot
are destroyed.Expected outcome
In Matplotlib v3.0.3, a new
pyplot
window is created by the PyQt5 backend without destroying anything else.Matplotlib version
The text was updated successfully, but these errors were encountered: