- The goal:
I am writing a function that uses Qt5Agg backend within a Jupyter notebook. The rest of the notebook mostly uses inline. The function generates an interactive plot with matplotlib widgets, and I want to make it work in a separate window. The rest of the notebook produces a bunch of figures, sometimes hundreds in a single cell that have to be generated inline, for efficiency.
I have been running %matplotlib qt just before running the function and %matplotlib inline immediately after running the function. However, I don't want to bother with these two extra lines, especially because %matplotlib inline has to be run in a separate cell. It is prone to user error - the backend will get stuck in Qt5Agg if the user forgets to run the cell after.
I would like to change the backend temporarily, by adding some code within the function. This would have the added advantage of making this function more compatible. I could transfer it to other notebooks and it would work as expected, using Qt5Agg, and won't mess with whatever backend the rest of that notebook uses (inline or something else).
Please note that I am coding on Windows, but I have to make sure that the notebook works on all operating systems.
- What I have tried so far:
The most obvious solution I could come up with was setting a temporary rc context with a decorator...
import matplotlib.pyplot as plt
@plt.rc_context({'backend': 'Qt5Agg'})
def function(foo):
...
return None
This sets a context for the backend, as expected, but Matplotlib doesn't use it! If I print the backend from within the function, it will tell me that it is Qt5Agg, while I'm staring at an inline plot below it. Other parameters can be effectively changed using the rc_context. I can easily change stuff like 'lines.linestyle' and the plot will reflect those changes. Only when it comes to backend, Matplotlib refuses to use the value I set.
Next I tried changing the 'backend' value in the rcParams dictionary (this would change the backend globally, not locally but I tried it anyway). It leads to a similar situation where the value is changed in the dictionary, but Matplotlib continues using the inline backend. I also tried using switch_backend and matplotlib.use and neither of them worked reliably. Besides, they are also supposed to change the backend globally, so not ideal for my use. Of all the methods I discovered so far, magic is the only way to properly change backend.
- Summary:
- I can't get Matplotlib to reliably change backends without using magic.
- Magic sets the backend globally, not locally within the function.
- I need to change the backend locally, for only one function.
- Matplotlib won't use the backend from
rc_context.
P.S. - This is my first post, so apologies if I haven't provided all the useful information. Let me know if you need more info.