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