##// END OF EJS Templates
Add code to de-init the inline backend....
Ryan May -
Show More
@@ -1,334 +1,346 b''
1 1 # -*- coding: utf-8 -*-
2 2 """Pylab (matplotlib) support utilities.
3 3
4 4 Authors
5 5 -------
6 6
7 7 * Fernando Perez.
8 8 * Brian Granger
9 9 """
10 10
11 11 #-----------------------------------------------------------------------------
12 12 # Copyright (C) 2009-2011 The IPython Development Team
13 13 #
14 14 # Distributed under the terms of the BSD License. The full license is in
15 15 # the file COPYING, distributed as part of this software.
16 16 #-----------------------------------------------------------------------------
17 17
18 18 #-----------------------------------------------------------------------------
19 19 # Imports
20 20 #-----------------------------------------------------------------------------
21 21
22 22 import sys
23 23 from io import BytesIO
24 24
25 25 from IPython.utils.decorators import flag_calls
26 26
27 27 # If user specifies a GUI, that dictates the backend, otherwise we read the
28 28 # user's mpl default from the mpl rc structure
29 29 backends = {'tk': 'TkAgg',
30 30 'gtk': 'GTKAgg',
31 31 'wx': 'WXAgg',
32 32 'qt': 'Qt4Agg', # qt3 not supported
33 33 'qt4': 'Qt4Agg',
34 34 'osx': 'MacOSX',
35 35 'inline' : 'module://IPython.zmq.pylab.backend_inline'}
36 36
37 37 # We also need a reverse backends2guis mapping that will properly choose which
38 38 # GUI support to activate based on the desired matplotlib backend. For the
39 39 # most part it's just a reverse of the above dict, but we also need to add a
40 40 # few others that map to the same GUI manually:
41 41 backend2gui = dict(zip(backends.values(), backends.keys()))
42 42 # In the reverse mapping, there are a few extra valid matplotlib backends that
43 43 # map to the same GUI support
44 44 backend2gui['GTK'] = backend2gui['GTKCairo'] = 'gtk'
45 45 backend2gui['WX'] = 'wx'
46 46 backend2gui['CocoaAgg'] = 'osx'
47 47
48 48 #-----------------------------------------------------------------------------
49 49 # Matplotlib utilities
50 50 #-----------------------------------------------------------------------------
51 51
52 52
53 53 def getfigs(*fig_nums):
54 54 """Get a list of matplotlib figures by figure numbers.
55 55
56 56 If no arguments are given, all available figures are returned. If the
57 57 argument list contains references to invalid figures, a warning is printed
58 58 but the function continues pasting further figures.
59 59
60 60 Parameters
61 61 ----------
62 62 figs : tuple
63 63 A tuple of ints giving the figure numbers of the figures to return.
64 64 """
65 65 from matplotlib._pylab_helpers import Gcf
66 66 if not fig_nums:
67 67 fig_managers = Gcf.get_all_fig_managers()
68 68 return [fm.canvas.figure for fm in fig_managers]
69 69 else:
70 70 figs = []
71 71 for num in fig_nums:
72 72 f = Gcf.figs.get(num)
73 73 if f is None:
74 74 print('Warning: figure %s not available.' % num)
75 75 else:
76 76 figs.append(f.canvas.figure)
77 77 return figs
78 78
79 79
80 80 def figsize(sizex, sizey):
81 81 """Set the default figure size to be [sizex, sizey].
82 82
83 83 This is just an easy to remember, convenience wrapper that sets::
84 84
85 85 matplotlib.rcParams['figure.figsize'] = [sizex, sizey]
86 86 """
87 87 import matplotlib
88 88 matplotlib.rcParams['figure.figsize'] = [sizex, sizey]
89 89
90 90
91 91 def print_figure(fig, fmt='png'):
92 92 """Convert a figure to svg or png for inline display."""
93 93 # When there's an empty figure, we shouldn't return anything, otherwise we
94 94 # get big blank areas in the qt console.
95 95 if not fig.axes and not fig.lines:
96 96 return
97 97
98 98 fc = fig.get_facecolor()
99 99 ec = fig.get_edgecolor()
100 100 bytes_io = BytesIO()
101 101 fig.canvas.print_figure(bytes_io, format=fmt, bbox_inches='tight',
102 102 facecolor=fc, edgecolor=ec)
103 103 data = bytes_io.getvalue()
104 104 return data
105 105
106 106
107 107 # We need a little factory function here to create the closure where
108 108 # safe_execfile can live.
109 109 def mpl_runner(safe_execfile):
110 110 """Factory to return a matplotlib-enabled runner for %run.
111 111
112 112 Parameters
113 113 ----------
114 114 safe_execfile : function
115 115 This must be a function with the same interface as the
116 116 :meth:`safe_execfile` method of IPython.
117 117
118 118 Returns
119 119 -------
120 120 A function suitable for use as the ``runner`` argument of the %run magic
121 121 function.
122 122 """
123 123
124 124 def mpl_execfile(fname,*where,**kw):
125 125 """matplotlib-aware wrapper around safe_execfile.
126 126
127 127 Its interface is identical to that of the :func:`execfile` builtin.
128 128
129 129 This is ultimately a call to execfile(), but wrapped in safeties to
130 130 properly handle interactive rendering."""
131 131
132 132 import matplotlib
133 133 import matplotlib.pylab as pylab
134 134
135 135 #print '*** Matplotlib runner ***' # dbg
136 136 # turn off rendering until end of script
137 137 is_interactive = matplotlib.rcParams['interactive']
138 138 matplotlib.interactive(False)
139 139 safe_execfile(fname,*where,**kw)
140 140 matplotlib.interactive(is_interactive)
141 141 # make rendering call now, if the user tried to do it
142 142 if pylab.draw_if_interactive.called:
143 143 pylab.draw()
144 144 pylab.draw_if_interactive.called = False
145 145
146 146 return mpl_execfile
147 147
148 148
149 149 def select_figure_format(shell, fmt):
150 150 """Select figure format for inline backend, either 'png' or 'svg'.
151 151
152 152 Using this method ensures only one figure format is active at a time.
153 153 """
154 154 from matplotlib.figure import Figure
155 155 from IPython.zmq.pylab import backend_inline
156 156
157 157 svg_formatter = shell.display_formatter.formatters['image/svg+xml']
158 158 png_formatter = shell.display_formatter.formatters['image/png']
159 159
160 160 if fmt=='png':
161 161 svg_formatter.type_printers.pop(Figure, None)
162 162 png_formatter.for_type(Figure, lambda fig: print_figure(fig, 'png'))
163 163 elif fmt=='svg':
164 164 png_formatter.type_printers.pop(Figure, None)
165 165 svg_formatter.for_type(Figure, lambda fig: print_figure(fig, 'svg'))
166 166 else:
167 167 raise ValueError("supported formats are: 'png', 'svg', not %r"%fmt)
168 168
169 169 # set the format to be used in the backend()
170 170 backend_inline._figure_format = fmt
171 171
172 172 #-----------------------------------------------------------------------------
173 173 # Code for initializing matplotlib and importing pylab
174 174 #-----------------------------------------------------------------------------
175 175
176 176
177 177 def find_gui_and_backend(gui=None):
178 178 """Given a gui string return the gui and mpl backend.
179 179
180 180 Parameters
181 181 ----------
182 182 gui : str
183 183 Can be one of ('tk','gtk','wx','qt','qt4','inline').
184 184
185 185 Returns
186 186 -------
187 187 A tuple of (gui, backend) where backend is one of ('TkAgg','GTKAgg',
188 188 'WXAgg','Qt4Agg','module://IPython.zmq.pylab.backend_inline').
189 189 """
190 190
191 191 import matplotlib
192 192
193 193 if gui and gui != 'auto':
194 194 # select backend based on requested gui
195 195 backend = backends[gui]
196 196 else:
197 197 backend = matplotlib.rcParams['backend']
198 198 # In this case, we need to find what the appropriate gui selection call
199 199 # should be for IPython, so we can activate inputhook accordingly
200 200 gui = backend2gui.get(backend, None)
201 201 return gui, backend
202 202
203 203
204 204 def activate_matplotlib(backend):
205 205 """Activate the given backend and set interactive to True."""
206 206
207 207 import matplotlib
208 208 matplotlib.interactive(True)
209 209
210 210 # Matplotlib had a bug where even switch_backend could not force
211 211 # the rcParam to update. This needs to be set *before* the module
212 212 # magic of switch_backend().
213 213 matplotlib.rcParams['backend'] = backend
214 214
215 215 import matplotlib.pyplot
216 216 matplotlib.pyplot.switch_backend(backend)
217 217
218 218 # This must be imported last in the matplotlib series, after
219 219 # backend/interactivity choices have been made
220 220 import matplotlib.pylab as pylab
221 221
222 222 pylab.show._needmain = False
223 223 # We need to detect at runtime whether show() is called by the user.
224 224 # For this, we wrap it into a decorator which adds a 'called' flag.
225 225 pylab.draw_if_interactive = flag_calls(pylab.draw_if_interactive)
226 226
227 227
228 228 def import_pylab(user_ns, import_all=True):
229 229 """Import the standard pylab symbols into user_ns."""
230 230
231 231 # Import numpy as np/pyplot as plt are conventions we're trying to
232 232 # somewhat standardize on. Making them available to users by default
233 233 # will greatly help this.
234 234 s = ("import numpy\n"
235 235 "import matplotlib\n"
236 236 "from matplotlib import pylab, mlab, pyplot\n"
237 237 "np = numpy\n"
238 238 "plt = pyplot\n"
239 239 )
240 240 exec s in user_ns
241 241
242 242 if import_all:
243 243 s = ("from matplotlib.pylab import *\n"
244 244 "from numpy import *\n")
245 245 exec s in user_ns
246 246
247 247
248 248 def configure_inline_support(shell, backend, user_ns=None):
249 249 """Configure an IPython shell object for matplotlib use.
250 250
251 251 Parameters
252 252 ----------
253 253 shell : InteractiveShell instance
254 254
255 255 backend : matplotlib backend
256 256
257 257 user_ns : dict
258 258 A namespace where all configured variables will be placed. If not given,
259 259 the `user_ns` attribute of the shell object is used.
260 260 """
261 261 # If using our svg payload backend, register the post-execution
262 262 # function that will pick up the results for display. This can only be
263 263 # done with access to the real shell object.
264 264
265 265 # Note: if we can't load the inline backend, then there's no point
266 266 # continuing (such as in terminal-only shells in environments without
267 267 # zeromq available).
268 268 try:
269 269 from IPython.zmq.pylab.backend_inline import InlineBackend
270 270 except ImportError:
271 271 return
272 from matplotlib import pyplot
272 273
273 274 user_ns = shell.user_ns if user_ns is None else user_ns
274 275
275 276 cfg = InlineBackend.instance(config=shell.config)
276 277 cfg.shell = shell
277 278 if cfg not in shell.configurables:
278 279 shell.configurables.append(cfg)
279 280
280 281 if backend == backends['inline']:
281 282 from IPython.zmq.pylab.backend_inline import flush_figures
282 from matplotlib import pyplot
283 283 shell.register_post_execute(flush_figures)
284
285 # Save rcParams that will be overwrittern
286 shell._saved_rcParams = dict()
287 for k in cfg.rc:
288 shell._saved_rcParams[k] = pyplot.rcParams[k]
284 289 # load inline_rc
285 290 pyplot.rcParams.update(cfg.rc)
286 291 # Add 'figsize' to pyplot and to the user's namespace
287 292 user_ns['figsize'] = pyplot.figsize = figsize
293 else:
294 from IPython.zmq.pylab.backend_inline import flush_figures
295 if flush_figures in shell._post_execute:
296 shell._post_execute.pop(flush_figures)
297 if hasattr(shell, '_saved_rcParams'):
298 pyplot.rcParams.update(shell._saved_rcParams)
299 del shell._saved_rcParams
288 300
289 301 # Setup the default figure format
290 302 fmt = cfg.figure_format
291 303 select_figure_format(shell, fmt)
292 304
293 305 # The old pastefig function has been replaced by display
294 306 from IPython.core.display import display
295 307 # Add display and getfigs to the user's namespace
296 308 user_ns['display'] = display
297 309 user_ns['getfigs'] = getfigs
298 310
299 311
300 312 def pylab_activate(user_ns, gui=None, import_all=True, shell=None):
301 313 """Activate pylab mode in the user's namespace.
302 314
303 315 Loads and initializes numpy, matplotlib and friends for interactive use.
304 316
305 317 Parameters
306 318 ----------
307 319 user_ns : dict
308 320 Namespace where the imports will occur.
309 321
310 322 gui : optional, string
311 323 A valid gui name following the conventions of the %gui magic.
312 324
313 325 import_all : optional, boolean
314 326 If true, an 'import *' is done from numpy and pylab.
315 327
316 328 Returns
317 329 -------
318 330 The actual gui used (if not given as input, it was obtained from matplotlib
319 331 itself, and will be needed next to configure IPython's gui integration.
320 332 """
321 333 gui, backend = find_gui_and_backend(gui)
322 334 activate_matplotlib(backend)
323 335 import_pylab(user_ns, import_all)
324 336 if shell is not None:
325 337 configure_inline_support(shell, backend, user_ns)
326 338
327 339 print """
328 340 Welcome to pylab, a matplotlib-based Python environment [backend: %s].
329 341 For more information, type 'help(pylab)'.""" % backend
330 342 # flush stdout, just to be safe
331 343 sys.stdout.flush()
332 344
333 345 return gui
334 346
General Comments 0
You need to be logged in to leave comments. Login now