Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit e048b12

Browse files
committed
MNT: implement direct calls to draw_idle
This is the result of a phone discussion with @medhoon The idea is to not rely on pyplot knowing to check if the figure needs to be re-drawn, but just have the Figure object directly kick the canvas to draw_idle. This does not currently work with nbagg due to the first draw_idle being fired before it is finished building it's self. There maybe similar race conditions in the other backends.
1 parent ed5253d commit e048b12

File tree

2 files changed

+11
-98
lines changed

2 files changed

+11
-98
lines changed

lib/matplotlib/figure.py

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,11 @@ def _stale_figure_callback(self, val):
5656
self.figure.stale = val
5757

5858

59+
def _stale_canvas_callback(self, val):
60+
if rcParams['interactive'] and self.canvas is not None and val:
61+
self.canvas.draw_idle()
62+
63+
5964
class AxesStack(Stack):
6065
"""
6166
Specialization of the Stack to handle all tracking of Axes in a Figure.
@@ -352,6 +357,11 @@ def __init__(self,
352357
self._axstack = AxesStack() # track all figure axes and current axes
353358
self.clf()
354359
self._cachedRenderer = None
360+
self.stale_callback = Figure._stale_callback
361+
362+
def _stale_callback(self, val):
363+
if val and self.canvas is not None:
364+
self.canvas.stale = val
355365

356366
# TODO: I'd like to dynamically add the _repr_html_ method
357367
# to the figure in the right context, but then IPython doesn't
@@ -560,7 +570,7 @@ def set_canvas(self, canvas):
560570
ACCEPTS: a FigureCanvas instance
561571
"""
562572
self.canvas = canvas
563-
self.stale = True
573+
self.stale_callback = _stale_canvas_callback
564574

565575
def hold(self, b=None):
566576
"""

lib/matplotlib/pyplot.py

Lines changed: 0 additions & 97 deletions
Original file line numberDiff line numberDiff line change
@@ -108,84 +108,6 @@ def _backend_selection():
108108
from matplotlib.backends import pylab_setup
109109
_backend_mod, new_figure_manager, draw_if_interactive, _show = pylab_setup()
110110

111-
_IP_REGISTERED = None
112-
_INSTALL_FIG_OBSERVER = False
113-
114-
def install_repl_displayhook():
115-
"""
116-
Install a repl display hook so that any stale figure are automatically
117-
redrawn when control is returned to the repl.
118-
119-
This works with both IPython terminals and vanilla python shells.
120-
"""
121-
global _IP_REGISTERED
122-
global _INSTALL_FIG_OBSERVER
123-
124-
class _NotIPython(Exception):
125-
pass
126-
127-
# see if we have IPython hooks around, if use them
128-
129-
try:
130-
from IPython import get_ipython
131-
ip = get_ipython()
132-
if ip is None:
133-
raise _NotIPython()
134-
135-
if _IP_REGISTERED:
136-
return
137-
138-
def post_execute():
139-
if matplotlib.is_interactive():
140-
draw_all()
141-
142-
# IPython >= 2
143-
try:
144-
ip.events.register('post_execute', post_execute)
145-
except AttributeError:
146-
# IPython 1.x
147-
ip.register_post_execute(post_execute)
148-
149-
_IP_REGISTERED = post_execute
150-
_INSTALL_FIG_OBSERVER = False
151-
152-
# import failed or ipython is not running
153-
except (ImportError, _NotIPython):
154-
_INSTALL_FIG_OBSERVER = True
155-
156-
157-
def uninstall_repl_displayhook():
158-
"""
159-
Uninstalls the matplotlib display hook.
160-
161-
.. warning
162-
163-
Need IPython >= 2 for this to work. For IPython < 2 will raise a
164-
``NotImplementedError``
165-
166-
.. warning
167-
168-
If you are using vanilla python and have installed another
169-
display hook this will reset ``sys.displayhook`` to what ever
170-
function was there when matplotlib installed it's displayhook,
171-
possibly discarding your changes.
172-
"""
173-
global _IP_REGISTERED
174-
global _INSTALL_FIG_OBSERVER
175-
if _IP_REGISTERED:
176-
from IPython import get_ipython
177-
ip = get_ipython()
178-
try:
179-
ip.events.unregister('post_execute', _IP_REGISTERED)
180-
except AttributeError:
181-
raise NotImplementedError("Can not unregister events "
182-
"in IPython < 2.0")
183-
_IP_REGISTERED = None
184-
185-
if _INSTALL_FIG_OBSERVER:
186-
_INSTALL_FIG_OBSERVER = False
187-
188-
189111
draw_all = _pylab_helpers.Gcf.draw_all
190112

191113

@@ -245,13 +167,11 @@ def isinteractive():
245167
def ioff():
246168
'Turn interactive mode off.'
247169
matplotlib.interactive(False)
248-
uninstall_repl_displayhook()
249170

250171

251172
def ion():
252173
'Turn interactive mode on.'
253174
matplotlib.interactive(True)
254-
install_repl_displayhook()
255175

256176

257177
def pause(interval):
@@ -532,16 +452,6 @@ def make_active(event):
532452
fig = figManager.canvas.figure
533453
fig.number = num
534454

535-
# make sure backends (inline) that we don't ship that expect this
536-
# to be called in plotting commands to make the figure call show
537-
# still work. There is probably a better way to do this in the
538-
# FigureManager base class.
539-
if matplotlib.is_interactive():
540-
draw_if_interactive()
541-
542-
if _INSTALL_FIG_OBSERVER:
543-
fig.stale_callback = _auto_draw_if_interactive
544-
545455
return figManager.canvas.figure
546456

547457

@@ -2494,13 +2404,6 @@ def spy(Z, precision=0, marker=None, markersize=None, aspect='equal', hold=None,
24942404
sci(ret)
24952405
return ret
24962406

2497-
# just to be safe. Interactive mode can be turned on without
2498-
# calling `plt.ion()` so register it again here.
2499-
# This is safe because multiple calls to `install_repl_displayhook`
2500-
# are no-ops and the registered function respect `mpl.is_interactive()`
2501-
# to determine if they should trigger a draw.
2502-
install_repl_displayhook()
2503-
25042407
################# REMAINING CONTENT GENERATED BY boilerplate.py ##############
25052408

25062409

0 commit comments

Comments
 (0)