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