##// END OF EJS Templates
add InlineBackend.print_figure_kwargs...
MinRK -
Show More
@@ -1,358 +1,373 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """Pylab (matplotlib) support utilities.
2 """Pylab (matplotlib) support utilities.
3
3
4 Authors
4 Authors
5 -------
5 -------
6
6
7 * Fernando Perez.
7 * Fernando Perez.
8 * Brian Granger
8 * Brian Granger
9 """
9 """
10 from __future__ import print_function
10 from __future__ import print_function
11
11
12 #-----------------------------------------------------------------------------
12 #-----------------------------------------------------------------------------
13 # Copyright (C) 2009 The IPython Development Team
13 # Copyright (C) 2009 The IPython Development Team
14 #
14 #
15 # Distributed under the terms of the BSD License. The full license is in
15 # Distributed under the terms of the BSD License. The full license is in
16 # the file COPYING, distributed as part of this software.
16 # the file COPYING, distributed as part of this software.
17 #-----------------------------------------------------------------------------
17 #-----------------------------------------------------------------------------
18
18
19 #-----------------------------------------------------------------------------
19 #-----------------------------------------------------------------------------
20 # Imports
20 # Imports
21 #-----------------------------------------------------------------------------
21 #-----------------------------------------------------------------------------
22
22
23 import sys
23 import sys
24 from io import BytesIO
24 from io import BytesIO
25
25
26 from IPython.core.display import _pngxy
26 from IPython.core.display import _pngxy
27 from IPython.utils.decorators import flag_calls
27 from IPython.utils.decorators import flag_calls
28 from IPython.utils import py3compat
28 from IPython.utils import py3compat
29
29
30 # If user specifies a GUI, that dictates the backend, otherwise we read the
30 # If user specifies a GUI, that dictates the backend, otherwise we read the
31 # user's mpl default from the mpl rc structure
31 # user's mpl default from the mpl rc structure
32 backends = {'tk': 'TkAgg',
32 backends = {'tk': 'TkAgg',
33 'gtk': 'GTKAgg',
33 'gtk': 'GTKAgg',
34 'gtk3': 'GTK3Agg',
34 'gtk3': 'GTK3Agg',
35 'wx': 'WXAgg',
35 'wx': 'WXAgg',
36 'qt': 'Qt4Agg', # qt3 not supported
36 'qt': 'Qt4Agg', # qt3 not supported
37 'qt4': 'Qt4Agg',
37 'qt4': 'Qt4Agg',
38 'osx': 'MacOSX',
38 'osx': 'MacOSX',
39 'inline' : 'module://IPython.kernel.zmq.pylab.backend_inline'}
39 'inline' : 'module://IPython.kernel.zmq.pylab.backend_inline'}
40
40
41 # We also need a reverse backends2guis mapping that will properly choose which
41 # We also need a reverse backends2guis mapping that will properly choose which
42 # GUI support to activate based on the desired matplotlib backend. For the
42 # GUI support to activate based on the desired matplotlib backend. For the
43 # most part it's just a reverse of the above dict, but we also need to add a
43 # most part it's just a reverse of the above dict, but we also need to add a
44 # few others that map to the same GUI manually:
44 # few others that map to the same GUI manually:
45 backend2gui = dict(zip(backends.values(), backends.keys()))
45 backend2gui = dict(zip(backends.values(), backends.keys()))
46 # Our tests expect backend2gui to just return 'qt'
46 # Our tests expect backend2gui to just return 'qt'
47 backend2gui['Qt4Agg'] = 'qt'
47 backend2gui['Qt4Agg'] = 'qt'
48 # In the reverse mapping, there are a few extra valid matplotlib backends that
48 # In the reverse mapping, there are a few extra valid matplotlib backends that
49 # map to the same GUI support
49 # map to the same GUI support
50 backend2gui['GTK'] = backend2gui['GTKCairo'] = 'gtk'
50 backend2gui['GTK'] = backend2gui['GTKCairo'] = 'gtk'
51 backend2gui['GTK3Cairo'] = 'gtk3'
51 backend2gui['GTK3Cairo'] = 'gtk3'
52 backend2gui['WX'] = 'wx'
52 backend2gui['WX'] = 'wx'
53 backend2gui['CocoaAgg'] = 'osx'
53 backend2gui['CocoaAgg'] = 'osx'
54
54
55 #-----------------------------------------------------------------------------
55 #-----------------------------------------------------------------------------
56 # Matplotlib utilities
56 # Matplotlib utilities
57 #-----------------------------------------------------------------------------
57 #-----------------------------------------------------------------------------
58
58
59
59
60 def getfigs(*fig_nums):
60 def getfigs(*fig_nums):
61 """Get a list of matplotlib figures by figure numbers.
61 """Get a list of matplotlib figures by figure numbers.
62
62
63 If no arguments are given, all available figures are returned. If the
63 If no arguments are given, all available figures are returned. If the
64 argument list contains references to invalid figures, a warning is printed
64 argument list contains references to invalid figures, a warning is printed
65 but the function continues pasting further figures.
65 but the function continues pasting further figures.
66
66
67 Parameters
67 Parameters
68 ----------
68 ----------
69 figs : tuple
69 figs : tuple
70 A tuple of ints giving the figure numbers of the figures to return.
70 A tuple of ints giving the figure numbers of the figures to return.
71 """
71 """
72 from matplotlib._pylab_helpers import Gcf
72 from matplotlib._pylab_helpers import Gcf
73 if not fig_nums:
73 if not fig_nums:
74 fig_managers = Gcf.get_all_fig_managers()
74 fig_managers = Gcf.get_all_fig_managers()
75 return [fm.canvas.figure for fm in fig_managers]
75 return [fm.canvas.figure for fm in fig_managers]
76 else:
76 else:
77 figs = []
77 figs = []
78 for num in fig_nums:
78 for num in fig_nums:
79 f = Gcf.figs.get(num)
79 f = Gcf.figs.get(num)
80 if f is None:
80 if f is None:
81 print('Warning: figure %s not available.' % num)
81 print('Warning: figure %s not available.' % num)
82 else:
82 else:
83 figs.append(f.canvas.figure)
83 figs.append(f.canvas.figure)
84 return figs
84 return figs
85
85
86
86
87 def figsize(sizex, sizey):
87 def figsize(sizex, sizey):
88 """Set the default figure size to be [sizex, sizey].
88 """Set the default figure size to be [sizex, sizey].
89
89
90 This is just an easy to remember, convenience wrapper that sets::
90 This is just an easy to remember, convenience wrapper that sets::
91
91
92 matplotlib.rcParams['figure.figsize'] = [sizex, sizey]
92 matplotlib.rcParams['figure.figsize'] = [sizex, sizey]
93 """
93 """
94 import matplotlib
94 import matplotlib
95 matplotlib.rcParams['figure.figsize'] = [sizex, sizey]
95 matplotlib.rcParams['figure.figsize'] = [sizex, sizey]
96
96
97
97
98 def print_figure(fig, fmt='png', quality=90):
98 def print_figure(fig, fmt='png', **kwargs):
99 """Convert a figure to svg, png or jpg for inline display.
99 """Print a figure to an image, and return the resulting bytes
100 Quality is only relevant for jpg.
100
101 Any extra keyword args are passed to fig.canvas.print_figure,
102 such as ``quality`` or ``bbox_inches``.
101 """
103 """
102 from matplotlib import rcParams
104 from matplotlib import rcParams
103 # When there's an empty figure, we shouldn't return anything, otherwise we
105 # When there's an empty figure, we shouldn't return anything, otherwise we
104 # get big blank areas in the qt console.
106 # get big blank areas in the qt console.
105 if not fig.axes and not fig.lines:
107 if not fig.axes and not fig.lines:
106 return
108 return
107
109
108 fc = fig.get_facecolor()
109 ec = fig.get_edgecolor()
110 bytes_io = BytesIO()
111 dpi = rcParams['savefig.dpi']
110 dpi = rcParams['savefig.dpi']
112 if fmt == 'retina':
111 if fmt == 'retina':
113 dpi = dpi * 2
112 dpi = dpi * 2
114 fmt = 'png'
113 fmt = 'png'
115 fig.canvas.print_figure(bytes_io, format=fmt, bbox_inches='tight',
116 facecolor=fc, edgecolor=ec, dpi=dpi, quality=quality)
117 data = bytes_io.getvalue()
118 return data
119
114
120 def retina_figure(fig):
115 # build keyword args
116 kw = dict(
117 format=fmt,
118 fc=fig.get_facecolor(),
119 ec=fig.get_edgecolor(),
120 dpi=dpi,
121 )
122 # **kwargs get higher priority
123 kw.update(kwargs)
124 print(kw)
125
126 bytes_io = BytesIO()
127 fig.canvas.print_figure(bytes_io, **kw)
128 return bytes_io.getvalue()
129
130 def retina_figure(fig, **kwargs):
121 """format a figure as a pixel-doubled (retina) PNG"""
131 """format a figure as a pixel-doubled (retina) PNG"""
122 pngdata = print_figure(fig, fmt='retina')
132 pngdata = print_figure(fig, fmt='retina', **kwargs)
123 w, h = _pngxy(pngdata)
133 w, h = _pngxy(pngdata)
124 metadata = dict(width=w//2, height=h//2)
134 metadata = dict(width=w//2, height=h//2)
125 return pngdata, metadata
135 return pngdata, metadata
126
136
127 # We need a little factory function here to create the closure where
137 # We need a little factory function here to create the closure where
128 # safe_execfile can live.
138 # safe_execfile can live.
129 def mpl_runner(safe_execfile):
139 def mpl_runner(safe_execfile):
130 """Factory to return a matplotlib-enabled runner for %run.
140 """Factory to return a matplotlib-enabled runner for %run.
131
141
132 Parameters
142 Parameters
133 ----------
143 ----------
134 safe_execfile : function
144 safe_execfile : function
135 This must be a function with the same interface as the
145 This must be a function with the same interface as the
136 :meth:`safe_execfile` method of IPython.
146 :meth:`safe_execfile` method of IPython.
137
147
138 Returns
148 Returns
139 -------
149 -------
140 A function suitable for use as the ``runner`` argument of the %run magic
150 A function suitable for use as the ``runner`` argument of the %run magic
141 function.
151 function.
142 """
152 """
143
153
144 def mpl_execfile(fname,*where,**kw):
154 def mpl_execfile(fname,*where,**kw):
145 """matplotlib-aware wrapper around safe_execfile.
155 """matplotlib-aware wrapper around safe_execfile.
146
156
147 Its interface is identical to that of the :func:`execfile` builtin.
157 Its interface is identical to that of the :func:`execfile` builtin.
148
158
149 This is ultimately a call to execfile(), but wrapped in safeties to
159 This is ultimately a call to execfile(), but wrapped in safeties to
150 properly handle interactive rendering."""
160 properly handle interactive rendering."""
151
161
152 import matplotlib
162 import matplotlib
153 import matplotlib.pylab as pylab
163 import matplotlib.pylab as pylab
154
164
155 #print '*** Matplotlib runner ***' # dbg
165 #print '*** Matplotlib runner ***' # dbg
156 # turn off rendering until end of script
166 # turn off rendering until end of script
157 is_interactive = matplotlib.rcParams['interactive']
167 is_interactive = matplotlib.rcParams['interactive']
158 matplotlib.interactive(False)
168 matplotlib.interactive(False)
159 safe_execfile(fname,*where,**kw)
169 safe_execfile(fname,*where,**kw)
160 matplotlib.interactive(is_interactive)
170 matplotlib.interactive(is_interactive)
161 # make rendering call now, if the user tried to do it
171 # make rendering call now, if the user tried to do it
162 if pylab.draw_if_interactive.called:
172 if pylab.draw_if_interactive.called:
163 pylab.draw()
173 pylab.draw()
164 pylab.draw_if_interactive.called = False
174 pylab.draw_if_interactive.called = False
165
175
166 return mpl_execfile
176 return mpl_execfile
167
177
168
178
169 def select_figure_formats(shell, formats, quality=90):
179 def select_figure_formats(shell, formats, **kwargs):
170 """Select figure formats for the inline backend.
180 """Select figure formats for the inline backend.
171
181
172 Parameters
182 Parameters
173 ==========
183 ==========
174 shell : InteractiveShell
184 shell : InteractiveShell
175 The main IPython instance.
185 The main IPython instance.
176 formats : list
186 formats : str or set
177 One or a set of figure formats to enable: 'png', 'retina', 'jpeg', 'svg', 'pdf'.
187 One or a set of figure formats to enable: 'png', 'retina', 'jpeg', 'svg', 'pdf'.
178 quality : int
188 **kwargs : any
179 A percentage for the quality of JPEG figures.
189 Extra keyword arguments to be passed to fig.canvas.print_figure.
180 """
190 """
181 from matplotlib.figure import Figure
191 from matplotlib.figure import Figure
182 from IPython.kernel.zmq.pylab import backend_inline
192 from IPython.kernel.zmq.pylab import backend_inline
183
193
184 svg_formatter = shell.display_formatter.formatters['image/svg+xml']
194 svg_formatter = shell.display_formatter.formatters['image/svg+xml']
185 png_formatter = shell.display_formatter.formatters['image/png']
195 png_formatter = shell.display_formatter.formatters['image/png']
186 jpg_formatter = shell.display_formatter.formatters['image/jpeg']
196 jpg_formatter = shell.display_formatter.formatters['image/jpeg']
187 pdf_formatter = shell.display_formatter.formatters['application/pdf']
197 pdf_formatter = shell.display_formatter.formatters['application/pdf']
188
198
189 if isinstance(formats, py3compat.string_types):
199 if isinstance(formats, py3compat.string_types):
190 formats = {formats}
200 formats = {formats}
201 # cast in case of list / tuple
202 formats = set(formats)
191
203
192 [ f.type_printers.pop(Figure, None) for f in {svg_formatter, png_formatter, jpg_formatter} ]
204 [ f.pop(Figure, None) for f in shell.display_formatter.formatters.values() ]
193
205
194 for fmt in formats:
206 supported = {'png', 'png2x', 'retina', 'jpg', 'jpeg', 'svg', 'pdf'}
195 if fmt == 'png':
207 bad = formats.difference(supported)
196 png_formatter.for_type(Figure, lambda fig: print_figure(fig, 'png'))
208 if bad:
197 elif fmt in ('png2x', 'retina'):
209 s = "{%s}" % ",".join([repr(f) for f in bad])
198 png_formatter.for_type(Figure, retina_figure)
210 raise ValueError("supported formats are: 'png', 'retina', 'svg', 'jpg', 'pdf' not %s" % s)
199 elif fmt in ('jpg', 'jpeg'):
211
200 jpg_formatter.for_type(Figure, lambda fig: print_figure(fig, 'jpg', quality))
212 if 'png' in formats:
201 elif fmt == 'svg':
213 png_formatter.for_type(Figure, lambda fig: print_figure(fig, 'png', **kwargs))
202 svg_formatter.for_type(Figure, lambda fig: print_figure(fig, 'svg'))
214 if 'retina' in formats or 'png2x' in formats:
203 elif fmt == 'pdf':
215 png_formatter.for_type(Figure, lambda fig: retina_figure(fig, **kwargs))
204 pdf_formatter.for_type(Figure, lambda fig: print_figure(fig, 'pdf'))
216 if 'jpg' in formats or 'jpeg' in formats:
205 else:
217 jpg_formatter.for_type(Figure, lambda fig: print_figure(fig, 'jpg', **kwargs))
206 raise ValueError("supported formats are: 'png', 'retina', 'svg', 'jpg', 'pdf' not %r" % fmt)
218 if 'svg' in formats:
219 svg_formatter.for_type(Figure, lambda fig: print_figure(fig, 'svg', **kwargs))
220 if 'pdf' in formats:
221 pdf_formatter.for_type(Figure, lambda fig: print_figure(fig, 'pdf', **kwargs))
207
222
208 #-----------------------------------------------------------------------------
223 #-----------------------------------------------------------------------------
209 # Code for initializing matplotlib and importing pylab
224 # Code for initializing matplotlib and importing pylab
210 #-----------------------------------------------------------------------------
225 #-----------------------------------------------------------------------------
211
226
212
227
213 def find_gui_and_backend(gui=None, gui_select=None):
228 def find_gui_and_backend(gui=None, gui_select=None):
214 """Given a gui string return the gui and mpl backend.
229 """Given a gui string return the gui and mpl backend.
215
230
216 Parameters
231 Parameters
217 ----------
232 ----------
218 gui : str
233 gui : str
219 Can be one of ('tk','gtk','wx','qt','qt4','inline').
234 Can be one of ('tk','gtk','wx','qt','qt4','inline').
220 gui_select : str
235 gui_select : str
221 Can be one of ('tk','gtk','wx','qt','qt4','inline').
236 Can be one of ('tk','gtk','wx','qt','qt4','inline').
222 This is any gui already selected by the shell.
237 This is any gui already selected by the shell.
223
238
224 Returns
239 Returns
225 -------
240 -------
226 A tuple of (gui, backend) where backend is one of ('TkAgg','GTKAgg',
241 A tuple of (gui, backend) where backend is one of ('TkAgg','GTKAgg',
227 'WXAgg','Qt4Agg','module://IPython.kernel.zmq.pylab.backend_inline').
242 'WXAgg','Qt4Agg','module://IPython.kernel.zmq.pylab.backend_inline').
228 """
243 """
229
244
230 import matplotlib
245 import matplotlib
231
246
232 if gui and gui != 'auto':
247 if gui and gui != 'auto':
233 # select backend based on requested gui
248 # select backend based on requested gui
234 backend = backends[gui]
249 backend = backends[gui]
235 else:
250 else:
236 # We need to read the backend from the original data structure, *not*
251 # We need to read the backend from the original data structure, *not*
237 # from mpl.rcParams, since a prior invocation of %matplotlib may have
252 # from mpl.rcParams, since a prior invocation of %matplotlib may have
238 # overwritten that.
253 # overwritten that.
239 # WARNING: this assumes matplotlib 1.1 or newer!!
254 # WARNING: this assumes matplotlib 1.1 or newer!!
240 backend = matplotlib.rcParamsOrig['backend']
255 backend = matplotlib.rcParamsOrig['backend']
241 # In this case, we need to find what the appropriate gui selection call
256 # In this case, we need to find what the appropriate gui selection call
242 # should be for IPython, so we can activate inputhook accordingly
257 # should be for IPython, so we can activate inputhook accordingly
243 gui = backend2gui.get(backend, None)
258 gui = backend2gui.get(backend, None)
244
259
245 # If we have already had a gui active, we need it and inline are the
260 # If we have already had a gui active, we need it and inline are the
246 # ones allowed.
261 # ones allowed.
247 if gui_select and gui != gui_select:
262 if gui_select and gui != gui_select:
248 gui = gui_select
263 gui = gui_select
249 backend = backends[gui]
264 backend = backends[gui]
250
265
251 return gui, backend
266 return gui, backend
252
267
253
268
254 def activate_matplotlib(backend):
269 def activate_matplotlib(backend):
255 """Activate the given backend and set interactive to True."""
270 """Activate the given backend and set interactive to True."""
256
271
257 import matplotlib
272 import matplotlib
258 matplotlib.interactive(True)
273 matplotlib.interactive(True)
259
274
260 # Matplotlib had a bug where even switch_backend could not force
275 # Matplotlib had a bug where even switch_backend could not force
261 # the rcParam to update. This needs to be set *before* the module
276 # the rcParam to update. This needs to be set *before* the module
262 # magic of switch_backend().
277 # magic of switch_backend().
263 matplotlib.rcParams['backend'] = backend
278 matplotlib.rcParams['backend'] = backend
264
279
265 import matplotlib.pyplot
280 import matplotlib.pyplot
266 matplotlib.pyplot.switch_backend(backend)
281 matplotlib.pyplot.switch_backend(backend)
267
282
268 # This must be imported last in the matplotlib series, after
283 # This must be imported last in the matplotlib series, after
269 # backend/interactivity choices have been made
284 # backend/interactivity choices have been made
270 import matplotlib.pylab as pylab
285 import matplotlib.pylab as pylab
271
286
272 pylab.show._needmain = False
287 pylab.show._needmain = False
273 # We need to detect at runtime whether show() is called by the user.
288 # We need to detect at runtime whether show() is called by the user.
274 # For this, we wrap it into a decorator which adds a 'called' flag.
289 # For this, we wrap it into a decorator which adds a 'called' flag.
275 pylab.draw_if_interactive = flag_calls(pylab.draw_if_interactive)
290 pylab.draw_if_interactive = flag_calls(pylab.draw_if_interactive)
276
291
277
292
278 def import_pylab(user_ns, import_all=True):
293 def import_pylab(user_ns, import_all=True):
279 """Populate the namespace with pylab-related values.
294 """Populate the namespace with pylab-related values.
280
295
281 Imports matplotlib, pylab, numpy, and everything from pylab and numpy.
296 Imports matplotlib, pylab, numpy, and everything from pylab and numpy.
282
297
283 Also imports a few names from IPython (figsize, display, getfigs)
298 Also imports a few names from IPython (figsize, display, getfigs)
284
299
285 """
300 """
286
301
287 # Import numpy as np/pyplot as plt are conventions we're trying to
302 # Import numpy as np/pyplot as plt are conventions we're trying to
288 # somewhat standardize on. Making them available to users by default
303 # somewhat standardize on. Making them available to users by default
289 # will greatly help this.
304 # will greatly help this.
290 s = ("import numpy\n"
305 s = ("import numpy\n"
291 "import matplotlib\n"
306 "import matplotlib\n"
292 "from matplotlib import pylab, mlab, pyplot\n"
307 "from matplotlib import pylab, mlab, pyplot\n"
293 "np = numpy\n"
308 "np = numpy\n"
294 "plt = pyplot\n"
309 "plt = pyplot\n"
295 )
310 )
296 exec(s, user_ns)
311 exec(s, user_ns)
297
312
298 if import_all:
313 if import_all:
299 s = ("from matplotlib.pylab import *\n"
314 s = ("from matplotlib.pylab import *\n"
300 "from numpy import *\n")
315 "from numpy import *\n")
301 exec(s, user_ns)
316 exec(s, user_ns)
302
317
303 # IPython symbols to add
318 # IPython symbols to add
304 user_ns['figsize'] = figsize
319 user_ns['figsize'] = figsize
305 from IPython.core.display import display
320 from IPython.core.display import display
306 # Add display and getfigs to the user's namespace
321 # Add display and getfigs to the user's namespace
307 user_ns['display'] = display
322 user_ns['display'] = display
308 user_ns['getfigs'] = getfigs
323 user_ns['getfigs'] = getfigs
309
324
310
325
311 def configure_inline_support(shell, backend):
326 def configure_inline_support(shell, backend):
312 """Configure an IPython shell object for matplotlib use.
327 """Configure an IPython shell object for matplotlib use.
313
328
314 Parameters
329 Parameters
315 ----------
330 ----------
316 shell : InteractiveShell instance
331 shell : InteractiveShell instance
317
332
318 backend : matplotlib backend
333 backend : matplotlib backend
319 """
334 """
320 # If using our svg payload backend, register the post-execution
335 # If using our svg payload backend, register the post-execution
321 # function that will pick up the results for display. This can only be
336 # function that will pick up the results for display. This can only be
322 # done with access to the real shell object.
337 # done with access to the real shell object.
323
338
324 # Note: if we can't load the inline backend, then there's no point
339 # Note: if we can't load the inline backend, then there's no point
325 # continuing (such as in terminal-only shells in environments without
340 # continuing (such as in terminal-only shells in environments without
326 # zeromq available).
341 # zeromq available).
327 try:
342 try:
328 from IPython.kernel.zmq.pylab.backend_inline import InlineBackend
343 from IPython.kernel.zmq.pylab.backend_inline import InlineBackend
329 except ImportError:
344 except ImportError:
330 return
345 return
331 from matplotlib import pyplot
346 from matplotlib import pyplot
332
347
333 cfg = InlineBackend.instance(parent=shell)
348 cfg = InlineBackend.instance(parent=shell)
334 cfg.shell = shell
349 cfg.shell = shell
335 if cfg not in shell.configurables:
350 if cfg not in shell.configurables:
336 shell.configurables.append(cfg)
351 shell.configurables.append(cfg)
337
352
338 if backend == backends['inline']:
353 if backend == backends['inline']:
339 from IPython.kernel.zmq.pylab.backend_inline import flush_figures
354 from IPython.kernel.zmq.pylab.backend_inline import flush_figures
340 shell.register_post_execute(flush_figures)
355 shell.register_post_execute(flush_figures)
341
356
342 # Save rcParams that will be overwrittern
357 # Save rcParams that will be overwrittern
343 shell._saved_rcParams = dict()
358 shell._saved_rcParams = dict()
344 for k in cfg.rc:
359 for k in cfg.rc:
345 shell._saved_rcParams[k] = pyplot.rcParams[k]
360 shell._saved_rcParams[k] = pyplot.rcParams[k]
346 # load inline_rc
361 # load inline_rc
347 pyplot.rcParams.update(cfg.rc)
362 pyplot.rcParams.update(cfg.rc)
348 else:
363 else:
349 from IPython.kernel.zmq.pylab.backend_inline import flush_figures
364 from IPython.kernel.zmq.pylab.backend_inline import flush_figures
350 if flush_figures in shell._post_execute:
365 if flush_figures in shell._post_execute:
351 shell._post_execute.pop(flush_figures)
366 shell._post_execute.pop(flush_figures)
352 if hasattr(shell, '_saved_rcParams'):
367 if hasattr(shell, '_saved_rcParams'):
353 pyplot.rcParams.update(shell._saved_rcParams)
368 pyplot.rcParams.update(shell._saved_rcParams)
354 del shell._saved_rcParams
369 del shell._saved_rcParams
355
370
356 # Setup the default figure format
371 # Setup the default figure format
357 select_figure_formats(shell, cfg.figure_formats, cfg.quality)
372 select_figure_formats(shell, cfg.figure_formats, **cfg.print_figure_kwargs)
358
373
@@ -1,115 +1,120 b''
1 """Configurable for configuring the IPython inline backend
1 """Configurable for configuring the IPython inline backend
2
2
3 This module does not import anything from matplotlib.
3 This module does not import anything from matplotlib.
4 """
4 """
5 #-----------------------------------------------------------------------------
5 #-----------------------------------------------------------------------------
6 # Copyright (C) 2011 The IPython Development Team
6 # Copyright (C) 2011 The IPython Development Team
7 #
7 #
8 # Distributed under the terms of the BSD License. The full license is in
8 # Distributed under the terms of the BSD License. The full license is in
9 # the file COPYING, distributed as part of this software.
9 # the file COPYING, distributed as part of this software.
10 #-----------------------------------------------------------------------------
10 #-----------------------------------------------------------------------------
11
11
12 #-----------------------------------------------------------------------------
12 #-----------------------------------------------------------------------------
13 # Imports
13 # Imports
14 #-----------------------------------------------------------------------------
14 #-----------------------------------------------------------------------------
15
15
16 from IPython.config.configurable import SingletonConfigurable
16 from IPython.config.configurable import SingletonConfigurable
17 from IPython.utils.traitlets import (
17 from IPython.utils.traitlets import (
18 Dict, Instance, CaselessStrEnum, Set, Bool, Int, TraitError, Unicode
18 Dict, Instance, CaselessStrEnum, Set, Bool, Int, TraitError, Unicode
19 )
19 )
20 from IPython.utils.warn import warn
20 from IPython.utils.warn import warn
21
21
22 #-----------------------------------------------------------------------------
22 #-----------------------------------------------------------------------------
23 # Configurable for inline backend options
23 # Configurable for inline backend options
24 #-----------------------------------------------------------------------------
24 #-----------------------------------------------------------------------------
25
25
26 def pil_available():
26 def pil_available():
27 """Test if PIL/Pillow is available"""
27 """Test if PIL/Pillow is available"""
28 out = False
28 out = False
29 try:
29 try:
30 from PIL import Image
30 from PIL import Image
31 out = True
31 out = True
32 except:
32 except:
33 pass
33 pass
34 return out
34 return out
35
35
36 # inherit from InlineBackendConfig for deprecation purposes
36 # inherit from InlineBackendConfig for deprecation purposes
37 class InlineBackendConfig(SingletonConfigurable):
37 class InlineBackendConfig(SingletonConfigurable):
38 pass
38 pass
39
39
40 class InlineBackend(InlineBackendConfig):
40 class InlineBackend(InlineBackendConfig):
41 """An object to store configuration of the inline backend."""
41 """An object to store configuration of the inline backend."""
42
42
43 def _config_changed(self, name, old, new):
43 def _config_changed(self, name, old, new):
44 # warn on change of renamed config section
44 # warn on change of renamed config section
45 if new.InlineBackendConfig != old.InlineBackendConfig:
45 if new.InlineBackendConfig != old.InlineBackendConfig:
46 warn("InlineBackendConfig has been renamed to InlineBackend")
46 warn("InlineBackendConfig has been renamed to InlineBackend")
47 super(InlineBackend, self)._config_changed(name, old, new)
47 super(InlineBackend, self)._config_changed(name, old, new)
48
48
49 # The typical default figure size is too large for inline use,
49 # The typical default figure size is too large for inline use,
50 # so we shrink the figure size to 6x4, and tweak fonts to
50 # so we shrink the figure size to 6x4, and tweak fonts to
51 # make that fit.
51 # make that fit.
52 rc = Dict({'figure.figsize': (6.0,4.0),
52 rc = Dict({'figure.figsize': (6.0,4.0),
53 # play nicely with white background in the Qt and notebook frontend
53 # play nicely with white background in the Qt and notebook frontend
54 'figure.facecolor': (1,1,1,0),
54 'figure.facecolor': (1,1,1,0),
55 'figure.edgecolor': (1,1,1,0),
55 'figure.edgecolor': (1,1,1,0),
56 # 12pt labels get cutoff on 6x4 logplots, so use 10pt.
56 # 12pt labels get cutoff on 6x4 logplots, so use 10pt.
57 'font.size': 10,
57 'font.size': 10,
58 # 72 dpi matches SVG/qtconsole
58 # 72 dpi matches SVG/qtconsole
59 # this only affects PNG export, as SVG has no dpi setting
59 # this only affects PNG export, as SVG has no dpi setting
60 'savefig.dpi': 72,
60 'savefig.dpi': 72,
61 # 10pt still needs a little more room on the xlabel:
61 # 10pt still needs a little more room on the xlabel:
62 'figure.subplot.bottom' : .125
62 'figure.subplot.bottom' : .125
63 }, config=True,
63 }, config=True,
64 help="""Subset of matplotlib rcParams that should be different for the
64 help="""Subset of matplotlib rcParams that should be different for the
65 inline backend."""
65 inline backend."""
66 )
66 )
67
67
68 figure_formats = Set({'png'}, config=True,
68 figure_formats = Set({'png'}, config=True,
69 help="""A set of figure formats to enable: 'png',
69 help="""A set of figure formats to enable: 'png',
70 'retina', 'jpeg', 'svg', 'pdf'.""")
70 'retina', 'jpeg', 'svg', 'pdf'.""")
71
71
72 def _update_figure_formatters(self):
73 if self.shell is not None:
74 select_figure_formats(self.shell, self.figure_formats, **self.print_figure_kwargs)
75
72 def _figure_formats_changed(self, name, old, new):
76 def _figure_formats_changed(self, name, old, new):
73 from IPython.core.pylabtools import select_figure_formats
77 from IPython.core.pylabtools import select_figure_formats
74 if 'jpg' in new or 'jpeg' in new:
78 if 'jpg' in new or 'jpeg' in new:
75 if not pil_available():
79 if not pil_available():
76 raise TraitError("Requires PIL/Pillow for JPG figures")
80 raise TraitError("Requires PIL/Pillow for JPG figures")
77 if self.shell is None:
81 if self.shell is None:
78 return
82 return
79 else:
83 else:
80 select_figure_formats(self.shell, new)
84 self._update_figure_formatters()
81
85
82 figure_format = Unicode(config=True, help="""The figure format to enable (deprecated
86 figure_format = Unicode(config=True, help="""The figure format to enable (deprecated
83 use `figure_formats` instead)""")
87 use `figure_formats` instead)""")
84
88
85 def _figure_format_changed(self, name, old, new):
89 def _figure_format_changed(self, name, old, new):
86 if new:
90 if new:
87 self.figure_formats = {new}
91 self.figure_formats = {new}
88
92
89 quality = Int(default_value=90, config=True,
93 print_figure_kwargs = Dict({'bbox_inches' : 'tight'}, config=True,
90 help="Quality of compression [10-100], currently for lossy JPEG only.")
94 help="""Extra kwargs to be passed to fig.canvas.print_figure.
91
95
92 def _quality_changed(self, name, old, new):
96 Logical examples include: bbox_inches, quality (for jpeg figures), etc.
93 if new < 10 or new > 100:
97 """
94 raise TraitError("figure JPEG quality must be in [10-100] range.")
98 )
99 _print_figure_kwargs_changed = _update_figure_formatters
95
100
96 close_figures = Bool(True, config=True,
101 close_figures = Bool(True, config=True,
97 help="""Close all figures at the end of each cell.
102 help="""Close all figures at the end of each cell.
98
103
99 When True, ensures that each cell starts with no active figures, but it
104 When True, ensures that each cell starts with no active figures, but it
100 also means that one must keep track of references in order to edit or
105 also means that one must keep track of references in order to edit or
101 redraw figures in subsequent cells. This mode is ideal for the notebook,
106 redraw figures in subsequent cells. This mode is ideal for the notebook,
102 where residual plots from other cells might be surprising.
107 where residual plots from other cells might be surprising.
103
108
104 When False, one must call figure() to create new figures. This means
109 When False, one must call figure() to create new figures. This means
105 that gcf() and getfigs() can reference figures created in other cells,
110 that gcf() and getfigs() can reference figures created in other cells,
106 and the active figure can continue to be edited with pylab/pyplot
111 and the active figure can continue to be edited with pylab/pyplot
107 methods that reference the current active figure. This mode facilitates
112 methods that reference the current active figure. This mode facilitates
108 iterative editing of figures, and behaves most consistently with
113 iterative editing of figures, and behaves most consistently with
109 other matplotlib backends, but figure barriers between cells must
114 other matplotlib backends, but figure barriers between cells must
110 be explicit.
115 be explicit.
111 """)
116 """)
112
117
113 shell = Instance('IPython.core.interactiveshell.InteractiveShellABC')
118 shell = Instance('IPython.core.interactiveshell.InteractiveShellABC')
114
119
115
120
General Comments 0
You need to be logged in to leave comments. Login now