##// END OF EJS Templates
FIX: ipympl does not need event loop support
Thomas A Caswell -
Show More
@@ -1,424 +1,425 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """Pylab (matplotlib) support utilities."""
2 """Pylab (matplotlib) support utilities."""
3
3
4 # Copyright (c) IPython Development Team.
4 # Copyright (c) IPython Development Team.
5 # Distributed under the terms of the Modified BSD License.
5 # Distributed under the terms of the Modified BSD License.
6
6
7 from io import BytesIO
7 from io import BytesIO
8 from binascii import b2a_base64
8 from binascii import b2a_base64
9 from functools import partial
9 from functools import partial
10 import warnings
10 import warnings
11
11
12 from IPython.core.display import _pngxy
12 from IPython.core.display import _pngxy
13 from IPython.utils.decorators import flag_calls
13 from IPython.utils.decorators import flag_calls
14
14
15 # If user specifies a GUI, that dictates the backend, otherwise we read the
15 # If user specifies a GUI, that dictates the backend, otherwise we read the
16 # user's mpl default from the mpl rc structure
16 # user's mpl default from the mpl rc structure
17 backends = {
17 backends = {
18 "tk": "TkAgg",
18 "tk": "TkAgg",
19 "gtk": "GTKAgg",
19 "gtk": "GTKAgg",
20 "gtk3": "GTK3Agg",
20 "gtk3": "GTK3Agg",
21 "gtk4": "GTK4Agg",
21 "gtk4": "GTK4Agg",
22 "wx": "WXAgg",
22 "wx": "WXAgg",
23 "qt4": "Qt4Agg",
23 "qt4": "Qt4Agg",
24 "qt5": "Qt5Agg",
24 "qt5": "Qt5Agg",
25 "qt6": "QtAgg",
25 "qt6": "QtAgg",
26 "qt": "Qt5Agg",
26 "qt": "Qt5Agg",
27 "osx": "MacOSX",
27 "osx": "MacOSX",
28 "nbagg": "nbAgg",
28 "nbagg": "nbAgg",
29 "notebook": "nbAgg",
29 "notebook": "nbAgg",
30 "agg": "agg",
30 "agg": "agg",
31 "svg": "svg",
31 "svg": "svg",
32 "pdf": "pdf",
32 "pdf": "pdf",
33 "ps": "ps",
33 "ps": "ps",
34 "inline": "module://matplotlib_inline.backend_inline",
34 "inline": "module://matplotlib_inline.backend_inline",
35 "ipympl": "module://ipympl.backend_nbagg",
35 "ipympl": "module://ipympl.backend_nbagg",
36 "widget": "module://ipympl.backend_nbagg",
36 "widget": "module://ipympl.backend_nbagg",
37 }
37 }
38
38
39 # We also need a reverse backends2guis mapping that will properly choose which
39 # We also need a reverse backends2guis mapping that will properly choose which
40 # GUI support to activate based on the desired matplotlib backend. For the
40 # GUI support to activate based on the desired matplotlib backend. For the
41 # most part it's just a reverse of the above dict, but we also need to add a
41 # most part it's just a reverse of the above dict, but we also need to add a
42 # few others that map to the same GUI manually:
42 # few others that map to the same GUI manually:
43 backend2gui = dict(zip(backends.values(), backends.keys()))
43 backend2gui = dict(zip(backends.values(), backends.keys()))
44 # In the reverse mapping, there are a few extra valid matplotlib backends that
44 # In the reverse mapping, there are a few extra valid matplotlib backends that
45 # map to the same GUI support
45 # map to the same GUI support
46 backend2gui["GTK"] = backend2gui["GTKCairo"] = "gtk"
46 backend2gui["GTK"] = backend2gui["GTKCairo"] = "gtk"
47 backend2gui["GTK3Cairo"] = "gtk3"
47 backend2gui["GTK3Cairo"] = "gtk3"
48 backend2gui["GTK4Cairo"] = "gtk4"
48 backend2gui["GTK4Cairo"] = "gtk4"
49 backend2gui["WX"] = "wx"
49 backend2gui["WX"] = "wx"
50 backend2gui["CocoaAgg"] = "osx"
50 backend2gui["CocoaAgg"] = "osx"
51 # There needs to be a hysteresis here as the new QtAgg Matplotlib backend
51 # There needs to be a hysteresis here as the new QtAgg Matplotlib backend
52 # supports either Qt5 or Qt6 and the IPython qt event loop support Qt4, Qt5,
52 # supports either Qt5 or Qt6 and the IPython qt event loop support Qt4, Qt5,
53 # and Qt6.
53 # and Qt6.
54 backend2gui["QtAgg"] = "qt"
54 backend2gui["QtAgg"] = "qt"
55 backend2gui["Qt4Agg"] = "qt"
55 backend2gui["Qt4Agg"] = "qt"
56 backend2gui["Qt5Agg"] = "qt"
56 backend2gui["Qt5Agg"] = "qt"
57
57
58 # And some backends that don't need GUI integration
58 # And some backends that don't need GUI integration
59 del backend2gui["nbAgg"]
59 del backend2gui["nbAgg"]
60 del backend2gui["agg"]
60 del backend2gui["agg"]
61 del backend2gui["svg"]
61 del backend2gui["svg"]
62 del backend2gui["pdf"]
62 del backend2gui["pdf"]
63 del backend2gui["ps"]
63 del backend2gui["ps"]
64 del backend2gui["module://matplotlib_inline.backend_inline"]
64 del backend2gui["module://matplotlib_inline.backend_inline"]
65 del backend2gui["module://ipympl.backend_nbagg"]
65
66
66 #-----------------------------------------------------------------------------
67 #-----------------------------------------------------------------------------
67 # Matplotlib utilities
68 # Matplotlib utilities
68 #-----------------------------------------------------------------------------
69 #-----------------------------------------------------------------------------
69
70
70
71
71 def getfigs(*fig_nums):
72 def getfigs(*fig_nums):
72 """Get a list of matplotlib figures by figure numbers.
73 """Get a list of matplotlib figures by figure numbers.
73
74
74 If no arguments are given, all available figures are returned. If the
75 If no arguments are given, all available figures are returned. If the
75 argument list contains references to invalid figures, a warning is printed
76 argument list contains references to invalid figures, a warning is printed
76 but the function continues pasting further figures.
77 but the function continues pasting further figures.
77
78
78 Parameters
79 Parameters
79 ----------
80 ----------
80 figs : tuple
81 figs : tuple
81 A tuple of ints giving the figure numbers of the figures to return.
82 A tuple of ints giving the figure numbers of the figures to return.
82 """
83 """
83 from matplotlib._pylab_helpers import Gcf
84 from matplotlib._pylab_helpers import Gcf
84 if not fig_nums:
85 if not fig_nums:
85 fig_managers = Gcf.get_all_fig_managers()
86 fig_managers = Gcf.get_all_fig_managers()
86 return [fm.canvas.figure for fm in fig_managers]
87 return [fm.canvas.figure for fm in fig_managers]
87 else:
88 else:
88 figs = []
89 figs = []
89 for num in fig_nums:
90 for num in fig_nums:
90 f = Gcf.figs.get(num)
91 f = Gcf.figs.get(num)
91 if f is None:
92 if f is None:
92 print('Warning: figure %s not available.' % num)
93 print('Warning: figure %s not available.' % num)
93 else:
94 else:
94 figs.append(f.canvas.figure)
95 figs.append(f.canvas.figure)
95 return figs
96 return figs
96
97
97
98
98 def figsize(sizex, sizey):
99 def figsize(sizex, sizey):
99 """Set the default figure size to be [sizex, sizey].
100 """Set the default figure size to be [sizex, sizey].
100
101
101 This is just an easy to remember, convenience wrapper that sets::
102 This is just an easy to remember, convenience wrapper that sets::
102
103
103 matplotlib.rcParams['figure.figsize'] = [sizex, sizey]
104 matplotlib.rcParams['figure.figsize'] = [sizex, sizey]
104 """
105 """
105 import matplotlib
106 import matplotlib
106 matplotlib.rcParams['figure.figsize'] = [sizex, sizey]
107 matplotlib.rcParams['figure.figsize'] = [sizex, sizey]
107
108
108
109
109 def print_figure(fig, fmt="png", bbox_inches="tight", base64=False, **kwargs):
110 def print_figure(fig, fmt="png", bbox_inches="tight", base64=False, **kwargs):
110 """Print a figure to an image, and return the resulting file data
111 """Print a figure to an image, and return the resulting file data
111
112
112 Returned data will be bytes unless ``fmt='svg'``,
113 Returned data will be bytes unless ``fmt='svg'``,
113 in which case it will be unicode.
114 in which case it will be unicode.
114
115
115 Any keyword args are passed to fig.canvas.print_figure,
116 Any keyword args are passed to fig.canvas.print_figure,
116 such as ``quality`` or ``bbox_inches``.
117 such as ``quality`` or ``bbox_inches``.
117
118
118 If `base64` is True, return base64-encoded str instead of raw bytes
119 If `base64` is True, return base64-encoded str instead of raw bytes
119 for binary-encoded image formats
120 for binary-encoded image formats
120
121
121 .. versionadded: 7.29
122 .. versionadded: 7.29
122 base64 argument
123 base64 argument
123 """
124 """
124 # When there's an empty figure, we shouldn't return anything, otherwise we
125 # When there's an empty figure, we shouldn't return anything, otherwise we
125 # get big blank areas in the qt console.
126 # get big blank areas in the qt console.
126 if not fig.axes and not fig.lines:
127 if not fig.axes and not fig.lines:
127 return
128 return
128
129
129 dpi = fig.dpi
130 dpi = fig.dpi
130 if fmt == 'retina':
131 if fmt == 'retina':
131 dpi = dpi * 2
132 dpi = dpi * 2
132 fmt = 'png'
133 fmt = 'png'
133
134
134 # build keyword args
135 # build keyword args
135 kw = {
136 kw = {
136 "format":fmt,
137 "format":fmt,
137 "facecolor":fig.get_facecolor(),
138 "facecolor":fig.get_facecolor(),
138 "edgecolor":fig.get_edgecolor(),
139 "edgecolor":fig.get_edgecolor(),
139 "dpi":dpi,
140 "dpi":dpi,
140 "bbox_inches":bbox_inches,
141 "bbox_inches":bbox_inches,
141 }
142 }
142 # **kwargs get higher priority
143 # **kwargs get higher priority
143 kw.update(kwargs)
144 kw.update(kwargs)
144
145
145 bytes_io = BytesIO()
146 bytes_io = BytesIO()
146 if fig.canvas is None:
147 if fig.canvas is None:
147 from matplotlib.backend_bases import FigureCanvasBase
148 from matplotlib.backend_bases import FigureCanvasBase
148 FigureCanvasBase(fig)
149 FigureCanvasBase(fig)
149
150
150 fig.canvas.print_figure(bytes_io, **kw)
151 fig.canvas.print_figure(bytes_io, **kw)
151 data = bytes_io.getvalue()
152 data = bytes_io.getvalue()
152 if fmt == 'svg':
153 if fmt == 'svg':
153 data = data.decode('utf-8')
154 data = data.decode('utf-8')
154 elif base64:
155 elif base64:
155 data = b2a_base64(data).decode("ascii")
156 data = b2a_base64(data).decode("ascii")
156 return data
157 return data
157
158
158 def retina_figure(fig, base64=False, **kwargs):
159 def retina_figure(fig, base64=False, **kwargs):
159 """format a figure as a pixel-doubled (retina) PNG
160 """format a figure as a pixel-doubled (retina) PNG
160
161
161 If `base64` is True, return base64-encoded str instead of raw bytes
162 If `base64` is True, return base64-encoded str instead of raw bytes
162 for binary-encoded image formats
163 for binary-encoded image formats
163
164
164 .. versionadded: 7.29
165 .. versionadded: 7.29
165 base64 argument
166 base64 argument
166 """
167 """
167 pngdata = print_figure(fig, fmt="retina", base64=False, **kwargs)
168 pngdata = print_figure(fig, fmt="retina", base64=False, **kwargs)
168 # Make sure that retina_figure acts just like print_figure and returns
169 # Make sure that retina_figure acts just like print_figure and returns
169 # None when the figure is empty.
170 # None when the figure is empty.
170 if pngdata is None:
171 if pngdata is None:
171 return
172 return
172 w, h = _pngxy(pngdata)
173 w, h = _pngxy(pngdata)
173 metadata = {"width": w//2, "height":h//2}
174 metadata = {"width": w//2, "height":h//2}
174 if base64:
175 if base64:
175 pngdata = b2a_base64(pngdata).decode("ascii")
176 pngdata = b2a_base64(pngdata).decode("ascii")
176 return pngdata, metadata
177 return pngdata, metadata
177
178
178
179
179 # We need a little factory function here to create the closure where
180 # We need a little factory function here to create the closure where
180 # safe_execfile can live.
181 # safe_execfile can live.
181 def mpl_runner(safe_execfile):
182 def mpl_runner(safe_execfile):
182 """Factory to return a matplotlib-enabled runner for %run.
183 """Factory to return a matplotlib-enabled runner for %run.
183
184
184 Parameters
185 Parameters
185 ----------
186 ----------
186 safe_execfile : function
187 safe_execfile : function
187 This must be a function with the same interface as the
188 This must be a function with the same interface as the
188 :meth:`safe_execfile` method of IPython.
189 :meth:`safe_execfile` method of IPython.
189
190
190 Returns
191 Returns
191 -------
192 -------
192 A function suitable for use as the ``runner`` argument of the %run magic
193 A function suitable for use as the ``runner`` argument of the %run magic
193 function.
194 function.
194 """
195 """
195
196
196 def mpl_execfile(fname,*where,**kw):
197 def mpl_execfile(fname,*where,**kw):
197 """matplotlib-aware wrapper around safe_execfile.
198 """matplotlib-aware wrapper around safe_execfile.
198
199
199 Its interface is identical to that of the :func:`execfile` builtin.
200 Its interface is identical to that of the :func:`execfile` builtin.
200
201
201 This is ultimately a call to execfile(), but wrapped in safeties to
202 This is ultimately a call to execfile(), but wrapped in safeties to
202 properly handle interactive rendering."""
203 properly handle interactive rendering."""
203
204
204 import matplotlib
205 import matplotlib
205 import matplotlib.pyplot as plt
206 import matplotlib.pyplot as plt
206
207
207 #print '*** Matplotlib runner ***' # dbg
208 #print '*** Matplotlib runner ***' # dbg
208 # turn off rendering until end of script
209 # turn off rendering until end of script
209 is_interactive = matplotlib.rcParams['interactive']
210 is_interactive = matplotlib.rcParams['interactive']
210 matplotlib.interactive(False)
211 matplotlib.interactive(False)
211 safe_execfile(fname,*where,**kw)
212 safe_execfile(fname,*where,**kw)
212 matplotlib.interactive(is_interactive)
213 matplotlib.interactive(is_interactive)
213 # make rendering call now, if the user tried to do it
214 # make rendering call now, if the user tried to do it
214 if plt.draw_if_interactive.called:
215 if plt.draw_if_interactive.called:
215 plt.draw()
216 plt.draw()
216 plt.draw_if_interactive.called = False
217 plt.draw_if_interactive.called = False
217
218
218 # re-draw everything that is stale
219 # re-draw everything that is stale
219 try:
220 try:
220 da = plt.draw_all
221 da = plt.draw_all
221 except AttributeError:
222 except AttributeError:
222 pass
223 pass
223 else:
224 else:
224 da()
225 da()
225
226
226 return mpl_execfile
227 return mpl_execfile
227
228
228
229
229 def _reshow_nbagg_figure(fig):
230 def _reshow_nbagg_figure(fig):
230 """reshow an nbagg figure"""
231 """reshow an nbagg figure"""
231 try:
232 try:
232 reshow = fig.canvas.manager.reshow
233 reshow = fig.canvas.manager.reshow
233 except AttributeError as e:
234 except AttributeError as e:
234 raise NotImplementedError() from e
235 raise NotImplementedError() from e
235 else:
236 else:
236 reshow()
237 reshow()
237
238
238
239
239 def select_figure_formats(shell, formats, **kwargs):
240 def select_figure_formats(shell, formats, **kwargs):
240 """Select figure formats for the inline backend.
241 """Select figure formats for the inline backend.
241
242
242 Parameters
243 Parameters
243 ==========
244 ==========
244 shell : InteractiveShell
245 shell : InteractiveShell
245 The main IPython instance.
246 The main IPython instance.
246 formats : str or set
247 formats : str or set
247 One or a set of figure formats to enable: 'png', 'retina', 'jpeg', 'svg', 'pdf'.
248 One or a set of figure formats to enable: 'png', 'retina', 'jpeg', 'svg', 'pdf'.
248 **kwargs : any
249 **kwargs : any
249 Extra keyword arguments to be passed to fig.canvas.print_figure.
250 Extra keyword arguments to be passed to fig.canvas.print_figure.
250 """
251 """
251 import matplotlib
252 import matplotlib
252 from matplotlib.figure import Figure
253 from matplotlib.figure import Figure
253
254
254 svg_formatter = shell.display_formatter.formatters['image/svg+xml']
255 svg_formatter = shell.display_formatter.formatters['image/svg+xml']
255 png_formatter = shell.display_formatter.formatters['image/png']
256 png_formatter = shell.display_formatter.formatters['image/png']
256 jpg_formatter = shell.display_formatter.formatters['image/jpeg']
257 jpg_formatter = shell.display_formatter.formatters['image/jpeg']
257 pdf_formatter = shell.display_formatter.formatters['application/pdf']
258 pdf_formatter = shell.display_formatter.formatters['application/pdf']
258
259
259 if isinstance(formats, str):
260 if isinstance(formats, str):
260 formats = {formats}
261 formats = {formats}
261 # cast in case of list / tuple
262 # cast in case of list / tuple
262 formats = set(formats)
263 formats = set(formats)
263
264
264 [ f.pop(Figure, None) for f in shell.display_formatter.formatters.values() ]
265 [ f.pop(Figure, None) for f in shell.display_formatter.formatters.values() ]
265 mplbackend = matplotlib.get_backend().lower()
266 mplbackend = matplotlib.get_backend().lower()
266 if mplbackend == 'nbagg' or mplbackend == 'module://ipympl.backend_nbagg':
267 if mplbackend == 'nbagg' or mplbackend == 'module://ipympl.backend_nbagg':
267 formatter = shell.display_formatter.ipython_display_formatter
268 formatter = shell.display_formatter.ipython_display_formatter
268 formatter.for_type(Figure, _reshow_nbagg_figure)
269 formatter.for_type(Figure, _reshow_nbagg_figure)
269
270
270 supported = {'png', 'png2x', 'retina', 'jpg', 'jpeg', 'svg', 'pdf'}
271 supported = {'png', 'png2x', 'retina', 'jpg', 'jpeg', 'svg', 'pdf'}
271 bad = formats.difference(supported)
272 bad = formats.difference(supported)
272 if bad:
273 if bad:
273 bs = "%s" % ','.join([repr(f) for f in bad])
274 bs = "%s" % ','.join([repr(f) for f in bad])
274 gs = "%s" % ','.join([repr(f) for f in supported])
275 gs = "%s" % ','.join([repr(f) for f in supported])
275 raise ValueError("supported formats are: %s not %s" % (gs, bs))
276 raise ValueError("supported formats are: %s not %s" % (gs, bs))
276
277
277 if "png" in formats:
278 if "png" in formats:
278 png_formatter.for_type(
279 png_formatter.for_type(
279 Figure, partial(print_figure, fmt="png", base64=True, **kwargs)
280 Figure, partial(print_figure, fmt="png", base64=True, **kwargs)
280 )
281 )
281 if "retina" in formats or "png2x" in formats:
282 if "retina" in formats or "png2x" in formats:
282 png_formatter.for_type(Figure, partial(retina_figure, base64=True, **kwargs))
283 png_formatter.for_type(Figure, partial(retina_figure, base64=True, **kwargs))
283 if "jpg" in formats or "jpeg" in formats:
284 if "jpg" in formats or "jpeg" in formats:
284 jpg_formatter.for_type(
285 jpg_formatter.for_type(
285 Figure, partial(print_figure, fmt="jpg", base64=True, **kwargs)
286 Figure, partial(print_figure, fmt="jpg", base64=True, **kwargs)
286 )
287 )
287 if "svg" in formats:
288 if "svg" in formats:
288 svg_formatter.for_type(Figure, partial(print_figure, fmt="svg", **kwargs))
289 svg_formatter.for_type(Figure, partial(print_figure, fmt="svg", **kwargs))
289 if "pdf" in formats:
290 if "pdf" in formats:
290 pdf_formatter.for_type(
291 pdf_formatter.for_type(
291 Figure, partial(print_figure, fmt="pdf", base64=True, **kwargs)
292 Figure, partial(print_figure, fmt="pdf", base64=True, **kwargs)
292 )
293 )
293
294
294 #-----------------------------------------------------------------------------
295 #-----------------------------------------------------------------------------
295 # Code for initializing matplotlib and importing pylab
296 # Code for initializing matplotlib and importing pylab
296 #-----------------------------------------------------------------------------
297 #-----------------------------------------------------------------------------
297
298
298
299
299 def find_gui_and_backend(gui=None, gui_select=None):
300 def find_gui_and_backend(gui=None, gui_select=None):
300 """Given a gui string return the gui and mpl backend.
301 """Given a gui string return the gui and mpl backend.
301
302
302 Parameters
303 Parameters
303 ----------
304 ----------
304 gui : str
305 gui : str
305 Can be one of ('tk','gtk','wx','qt','qt4','inline','agg').
306 Can be one of ('tk','gtk','wx','qt','qt4','inline','agg').
306 gui_select : str
307 gui_select : str
307 Can be one of ('tk','gtk','wx','qt','qt4','inline').
308 Can be one of ('tk','gtk','wx','qt','qt4','inline').
308 This is any gui already selected by the shell.
309 This is any gui already selected by the shell.
309
310
310 Returns
311 Returns
311 -------
312 -------
312 A tuple of (gui, backend) where backend is one of ('TkAgg','GTKAgg',
313 A tuple of (gui, backend) where backend is one of ('TkAgg','GTKAgg',
313 'WXAgg','Qt4Agg','module://matplotlib_inline.backend_inline','agg').
314 'WXAgg','Qt4Agg','module://matplotlib_inline.backend_inline','agg').
314 """
315 """
315
316
316 import matplotlib
317 import matplotlib
317
318
318 if gui and gui != 'auto':
319 if gui and gui != 'auto':
319 # select backend based on requested gui
320 # select backend based on requested gui
320 backend = backends[gui]
321 backend = backends[gui]
321 if gui == 'agg':
322 if gui == 'agg':
322 gui = None
323 gui = None
323 else:
324 else:
324 # We need to read the backend from the original data structure, *not*
325 # We need to read the backend from the original data structure, *not*
325 # from mpl.rcParams, since a prior invocation of %matplotlib may have
326 # from mpl.rcParams, since a prior invocation of %matplotlib may have
326 # overwritten that.
327 # overwritten that.
327 # WARNING: this assumes matplotlib 1.1 or newer!!
328 # WARNING: this assumes matplotlib 1.1 or newer!!
328 backend = matplotlib.rcParamsOrig['backend']
329 backend = matplotlib.rcParamsOrig['backend']
329 # In this case, we need to find what the appropriate gui selection call
330 # In this case, we need to find what the appropriate gui selection call
330 # should be for IPython, so we can activate inputhook accordingly
331 # should be for IPython, so we can activate inputhook accordingly
331 gui = backend2gui.get(backend, None)
332 gui = backend2gui.get(backend, None)
332
333
333 # If we have already had a gui active, we need it and inline are the
334 # If we have already had a gui active, we need it and inline are the
334 # ones allowed.
335 # ones allowed.
335 if gui_select and gui != gui_select:
336 if gui_select and gui != gui_select:
336 gui = gui_select
337 gui = gui_select
337 backend = backends[gui]
338 backend = backends[gui]
338
339
339 return gui, backend
340 return gui, backend
340
341
341
342
342 def activate_matplotlib(backend):
343 def activate_matplotlib(backend):
343 """Activate the given backend and set interactive to True."""
344 """Activate the given backend and set interactive to True."""
344
345
345 import matplotlib
346 import matplotlib
346 matplotlib.interactive(True)
347 matplotlib.interactive(True)
347
348
348 # Matplotlib had a bug where even switch_backend could not force
349 # Matplotlib had a bug where even switch_backend could not force
349 # the rcParam to update. This needs to be set *before* the module
350 # the rcParam to update. This needs to be set *before* the module
350 # magic of switch_backend().
351 # magic of switch_backend().
351 matplotlib.rcParams['backend'] = backend
352 matplotlib.rcParams['backend'] = backend
352
353
353 # Due to circular imports, pyplot may be only partially initialised
354 # Due to circular imports, pyplot may be only partially initialised
354 # when this function runs.
355 # when this function runs.
355 # So avoid needing matplotlib attribute-lookup to access pyplot.
356 # So avoid needing matplotlib attribute-lookup to access pyplot.
356 from matplotlib import pyplot as plt
357 from matplotlib import pyplot as plt
357
358
358 plt.switch_backend(backend)
359 plt.switch_backend(backend)
359
360
360 plt.show._needmain = False
361 plt.show._needmain = False
361 # We need to detect at runtime whether show() is called by the user.
362 # We need to detect at runtime whether show() is called by the user.
362 # For this, we wrap it into a decorator which adds a 'called' flag.
363 # For this, we wrap it into a decorator which adds a 'called' flag.
363 plt.draw_if_interactive = flag_calls(plt.draw_if_interactive)
364 plt.draw_if_interactive = flag_calls(plt.draw_if_interactive)
364
365
365
366
366 def import_pylab(user_ns, import_all=True):
367 def import_pylab(user_ns, import_all=True):
367 """Populate the namespace with pylab-related values.
368 """Populate the namespace with pylab-related values.
368
369
369 Imports matplotlib, pylab, numpy, and everything from pylab and numpy.
370 Imports matplotlib, pylab, numpy, and everything from pylab and numpy.
370
371
371 Also imports a few names from IPython (figsize, display, getfigs)
372 Also imports a few names from IPython (figsize, display, getfigs)
372
373
373 """
374 """
374
375
375 # Import numpy as np/pyplot as plt are conventions we're trying to
376 # Import numpy as np/pyplot as plt are conventions we're trying to
376 # somewhat standardize on. Making them available to users by default
377 # somewhat standardize on. Making them available to users by default
377 # will greatly help this.
378 # will greatly help this.
378 s = ("import numpy\n"
379 s = ("import numpy\n"
379 "import matplotlib\n"
380 "import matplotlib\n"
380 "from matplotlib import pylab, mlab, pyplot\n"
381 "from matplotlib import pylab, mlab, pyplot\n"
381 "np = numpy\n"
382 "np = numpy\n"
382 "plt = pyplot\n"
383 "plt = pyplot\n"
383 )
384 )
384 exec(s, user_ns)
385 exec(s, user_ns)
385
386
386 if import_all:
387 if import_all:
387 s = ("from matplotlib.pylab import *\n"
388 s = ("from matplotlib.pylab import *\n"
388 "from numpy import *\n")
389 "from numpy import *\n")
389 exec(s, user_ns)
390 exec(s, user_ns)
390
391
391 # IPython symbols to add
392 # IPython symbols to add
392 user_ns['figsize'] = figsize
393 user_ns['figsize'] = figsize
393 from IPython.display import display
394 from IPython.display import display
394 # Add display and getfigs to the user's namespace
395 # Add display and getfigs to the user's namespace
395 user_ns['display'] = display
396 user_ns['display'] = display
396 user_ns['getfigs'] = getfigs
397 user_ns['getfigs'] = getfigs
397
398
398
399
399 def configure_inline_support(shell, backend):
400 def configure_inline_support(shell, backend):
400 """
401 """
401 .. deprecated: 7.23
402 .. deprecated: 7.23
402
403
403 use `matplotlib_inline.backend_inline.configure_inline_support()`
404 use `matplotlib_inline.backend_inline.configure_inline_support()`
404
405
405 Configure an IPython shell object for matplotlib use.
406 Configure an IPython shell object for matplotlib use.
406
407
407 Parameters
408 Parameters
408 ----------
409 ----------
409 shell : InteractiveShell instance
410 shell : InteractiveShell instance
410
411
411 backend : matplotlib backend
412 backend : matplotlib backend
412 """
413 """
413 warnings.warn(
414 warnings.warn(
414 "`configure_inline_support` is deprecated since IPython 7.23, directly "
415 "`configure_inline_support` is deprecated since IPython 7.23, directly "
415 "use `matplotlib_inline.backend_inline.configure_inline_support()`",
416 "use `matplotlib_inline.backend_inline.configure_inline_support()`",
416 DeprecationWarning,
417 DeprecationWarning,
417 stacklevel=2,
418 stacklevel=2,
418 )
419 )
419
420
420 from matplotlib_inline.backend_inline import (
421 from matplotlib_inline.backend_inline import (
421 configure_inline_support as configure_inline_support_orig,
422 configure_inline_support as configure_inline_support_orig,
422 )
423 )
423
424
424 configure_inline_support_orig(shell, backend)
425 configure_inline_support_orig(shell, backend)
General Comments 0
You need to be logged in to leave comments. Login now