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