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