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