Repository navigation
Description
Bug summary
A regression between release versions 3.5.1 and 3.5.2 causes figures to fail to redraw after an initial plot is added using the pyplot interface in an interactive IPython session. This has been observed with both pyplot.plot and pyplot.tripcolor. The figure will show the first plot drawn, but subsequent calls to pyplot.plot and pyplot.tripcolor fail to update an on-screen figure until pyplot.draw is invoked. This has been observed with IPython versions 8.3.0 (current) and 8.2.0.
Both the Qt5 and Tk backends exhibit the same issues.
Code for reproduction
# Install matplotlib and ipython in a virtualenv
python3 -m venv ~/mpl.venv
. ~/mpl.venv/bin/activate
pip install matplotlib ipython
# Make sure to start with a clean config
mv ~/.ipython ~/.ipython.backup
mv ~/.config/matplotlib .config/matplotlib.backup
# Run `pylab`
ipython --pylab=tk
# ... the following are commands issues in the ipython prompt
plot(arange(10))
plot(-arange(10))
draw()Actual outcome
- After the first
plotcommand, a figure appears with ay = xline shown. - After the second
plotcommand, the figure does not update. - After the
drawcommand, the figure updates to show both they = xandy = -xlines.
Expected outcome
- After the first
plotcommand, a figure appears with ay = xline shown. (This is as expected.) - After the second
plotcommand, the figure updates with the addition of ay = -xline. (This is the deviation.) - The
drawcommand should produce no visible change in the figure.
Additional information
This regression has been bisected to commit f937b0a.
The testbed is a current Void Linux system running Python 3.10.4, including the system python3-tkinter package for a GUI. (As noted above, this bug is also present with the Qt5 backend.) All packages were installed in a virtual environment. The output of pip freeze is:
asttokens==2.0.5
backcall==0.2.0
cycler==0.11.0
decorator==5.1.1
executing==0.8.3
fonttools==4.33.3
ipython==8.3.0
jedi==0.18.1
kiwisolver==1.4.2
matplotlib==3.6.0.dev155+gf937b0ab5e
matplotlib-inline==0.1.3
numpy==1.22.3
packaging==21.3
parso==0.8.3
pexpect==4.8.0
pickleshare==0.7.5
Pillow==9.1.0
prompt-toolkit==3.0.29
ptyprocess==0.7.0
pure-eval==0.2.2
Pygments==2.12.0
pyparsing==3.0.9
python-dateutil==2.8.2
setuptools-scm==6.4.2
six==1.16.0
stack-data==0.2.0
tk==0.1.0
tomli==2.0.1
traitlets==5.2.0
wcwidth==0.2.5
(Note that the funny matplotlib version comes from a local git repo checked out to the problematic commit.)
Operating system
Void Linux x86_64
Matplotlib Version
3.5.2
Matplotlib Backend
TkAgg, Qt5Agg
Python version
3.10.4
Jupyter version
None
Installation
pip
Activity
tacaswell commentedon May 13, 2022
On the bright side, there is a very easy fix, an explicit call to
ion(akaplt.ionakamatplotlib.pyplot.ion()) will fix the behavior.I suspect that this is more fallout from deferring actually loading the backend until it is actually needed.
tacaswell commentedon May 13, 2022
@ahesford Thank you for reporting this and sorry we broke this.
Please forgive my last message if it came across as too terse.
ahesford commentedon May 13, 2022
No worries. I'm glad there's a simple workaround. In the meantime, I reverted the version shipped in Void pending a release with a permanent fix.
oscargus commentedon May 13, 2022
I'm not really sure how the backend solution works with the
--pylab=tkswitch, but it seems like a solution would be to doionas part of that as the backend is actually selected then.ahesford commentedon May 13, 2022
I can confirm that
ionresolves the issue. Should IPython assume responsibility for activating interactive mode when importing matplotlib, or should matplotlib attempt to figure out whether to enable interactive mode by default by some suitable means?tacaswell commentedon May 13, 2022
This is something that has historically been done by IPython (it is a side effect of
--pylab(who's use is discouraged but we are never going to deprecate it)). However, with #22005 we delayed resolving and configuring the backend until it is actually needed (which is the first time you create a Figure, could actually be pushed back to "first time you show a figure", but that is off in https://github.com/matplotlib/mpl-gui land).There is something going wrong in the (brittle) dance between IPython and Matplotlib. Given that it is as change on the mpl side that broke this I assume it it our fault and can (and should) fix it, but we still need to sort out why which will likely require chasing through the code on both sides. It is complicated because both side have extensive "work with old versions of the other" code.
Related, I observed in some cases at NSLS-II that if we had
pylab = autoin the IPython config files we saw a similar issue (it was a bit worse, the input hook did not get installed 😱 ) and this was with earlier version of the 3.5 series.harripj commentedon May 17, 2022
I am also experiencing this, and
plt.ion()fixed it for me. Thanks for the suggestion @tacaswell!It would be nice if this line was not necessary as I will have to update all of my notebooks!
FIX: ensure switching the backend while interactive is interactive
FIX: enable install_repl_displayhook when switching backends
FIX: enable install_repl_displayhook when switching backends
FIX: enable install_repl_displayhook when switching backends
oscargus commentedon May 23, 2022
@harripj see #11283 for a discussion about having
ionon by default.FIX: enable install_repl_displayhook when switching backends
FIX: enable install_repl_displayhook when switching backends