##// END OF EJS Templates
Avoid calling inline config if no shell - per @minrk feedback on #1052
Fernando Perez -
Show More
@@ -1,345 +1,343 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:
96 96 return
97 97
98 98 fc = fig.get_facecolor()
99 99 ec = fig.get_edgecolor()
100 100 fig.set_facecolor('white')
101 101 fig.set_edgecolor('white')
102 102 try:
103 103 bytes_io = BytesIO()
104 104 fig.canvas.print_figure(bytes_io, format=fmt, bbox_inches='tight')
105 105 data = bytes_io.getvalue()
106 106 finally:
107 107 fig.set_facecolor(fc)
108 108 fig.set_edgecolor(ec)
109 109 return data
110 110
111 111
112 112 # We need a little factory function here to create the closure where
113 113 # safe_execfile can live.
114 114 def mpl_runner(safe_execfile):
115 115 """Factory to return a matplotlib-enabled runner for %run.
116 116
117 117 Parameters
118 118 ----------
119 119 safe_execfile : function
120 120 This must be a function with the same interface as the
121 121 :meth:`safe_execfile` method of IPython.
122 122
123 123 Returns
124 124 -------
125 125 A function suitable for use as the ``runner`` argument of the %run magic
126 126 function.
127 127 """
128 128
129 129 def mpl_execfile(fname,*where,**kw):
130 130 """matplotlib-aware wrapper around safe_execfile.
131 131
132 132 Its interface is identical to that of the :func:`execfile` builtin.
133 133
134 134 This is ultimately a call to execfile(), but wrapped in safeties to
135 135 properly handle interactive rendering."""
136 136
137 137 import matplotlib
138 138 import matplotlib.pylab as pylab
139 139
140 140 #print '*** Matplotlib runner ***' # dbg
141 141 # turn off rendering until end of script
142 142 is_interactive = matplotlib.rcParams['interactive']
143 143 matplotlib.interactive(False)
144 144 safe_execfile(fname,*where,**kw)
145 145 matplotlib.interactive(is_interactive)
146 146 # make rendering call now, if the user tried to do it
147 147 if pylab.draw_if_interactive.called:
148 148 pylab.draw()
149 149 pylab.draw_if_interactive.called = False
150 150
151 151 return mpl_execfile
152 152
153 153
154 154 def select_figure_format(shell, fmt):
155 155 """Select figure format for inline backend, either 'png' or 'svg'.
156 156
157 157 Using this method ensures only one figure format is active at a time.
158 158 """
159 159 from matplotlib.figure import Figure
160 160 from IPython.zmq.pylab import backend_inline
161 161
162 162 svg_formatter = shell.display_formatter.formatters['image/svg+xml']
163 163 png_formatter = shell.display_formatter.formatters['image/png']
164 164
165 165 if fmt=='png':
166 166 svg_formatter.type_printers.pop(Figure, None)
167 167 png_formatter.for_type(Figure, lambda fig: print_figure(fig, 'png'))
168 168 elif fmt=='svg':
169 169 png_formatter.type_printers.pop(Figure, None)
170 170 svg_formatter.for_type(Figure, lambda fig: print_figure(fig, 'svg'))
171 171 else:
172 172 raise ValueError("supported formats are: 'png', 'svg', not %r"%fmt)
173 173
174 174 # set the format to be used in the backend()
175 175 backend_inline._figure_format = fmt
176 176
177 177 #-----------------------------------------------------------------------------
178 178 # Code for initializing matplotlib and importing pylab
179 179 #-----------------------------------------------------------------------------
180 180
181 181
182 182 def find_gui_and_backend(gui=None):
183 183 """Given a gui string return the gui and mpl backend.
184 184
185 185 Parameters
186 186 ----------
187 187 gui : str
188 188 Can be one of ('tk','gtk','wx','qt','qt4','inline').
189 189
190 190 Returns
191 191 -------
192 192 A tuple of (gui, backend) where backend is one of ('TkAgg','GTKAgg',
193 193 'WXAgg','Qt4Agg','module://IPython.zmq.pylab.backend_inline').
194 194 """
195 195
196 196 import matplotlib
197 197
198 198 if gui and gui != 'auto':
199 199 # select backend based on requested gui
200 200 backend = backends[gui]
201 201 else:
202 202 backend = matplotlib.rcParams['backend']
203 203 # In this case, we need to find what the appropriate gui selection call
204 204 # should be for IPython, so we can activate inputhook accordingly
205 205 gui = backend2gui.get(backend, None)
206 206 return gui, backend
207 207
208 208
209 209 def activate_matplotlib(backend):
210 210 """Activate the given backend and set interactive to True."""
211 211
212 212 import matplotlib
213 213 if backend.startswith('module://'):
214 214 # Work around bug in matplotlib: matplotlib.use converts the
215 215 # backend_id to lowercase even if a module name is specified!
216 216 matplotlib.rcParams['backend'] = backend
217 217 else:
218 218 matplotlib.use(backend)
219 219 matplotlib.interactive(True)
220 220
221 221 # This must be imported last in the matplotlib series, after
222 222 # backend/interactivity choices have been made
223 223 import matplotlib.pylab as pylab
224 224
225 225 # XXX For now leave this commented out, but depending on discussions with
226 226 # mpl-dev, we may be able to allow interactive switching...
227 227 #import matplotlib.pyplot
228 228 #matplotlib.pyplot.switch_backend(backend)
229 229
230 230 pylab.show._needmain = False
231 231 # We need to detect at runtime whether show() is called by the user.
232 232 # For this, we wrap it into a decorator which adds a 'called' flag.
233 233 pylab.draw_if_interactive = flag_calls(pylab.draw_if_interactive)
234 234
235 235
236 236 def import_pylab(user_ns, import_all=True):
237 237 """Import the standard pylab symbols into user_ns."""
238 238
239 239 # Import numpy as np/pyplot as plt are conventions we're trying to
240 240 # somewhat standardize on. Making them available to users by default
241 241 # will greatly help this.
242 242 s = ("import numpy\n"
243 243 "import matplotlib\n"
244 244 "from matplotlib import pylab, mlab, pyplot\n"
245 245 "np = numpy\n"
246 246 "plt = pyplot\n"
247 247 )
248 248 exec s in user_ns
249 249
250 250 if import_all:
251 251 s = ("from matplotlib.pylab import *\n"
252 252 "from numpy import *\n")
253 253 exec s in user_ns
254 254
255 255
256 256 def configure_inline_support(shell, backend, user_ns=None):
257 257 """Configure an IPython shell object for matplotlib use.
258 258
259 259 Parameters
260 260 ----------
261 261 shell : InteractiveShell instance
262 262 If None, this function returns immediately.
263 263
264 264 backend : matplotlib backend
265 265
266 266 user_ns : dict
267 267 A namespace where all configured variables will be placed. If not given,
268 268 the `user_ns` attribute of the shell object is used.
269 269 """
270 if shell is None:
271 return
272
273 270 # If using our svg payload backend, register the post-execution
274 271 # function that will pick up the results for display. This can only be
275 272 # done with access to the real shell object.
276 273
277 274 # Note: if we can't load the inline backend, then there's no point
278 275 # continuing (such as in terminal-only shells in environments without
279 276 # zeromq available).
280 277 try:
281 278 from IPython.zmq.pylab.backend_inline import InlineBackend
282 279 except ImportError:
283 280 return
284 281
285 282 user_ns = shell.user_ns if user_ns is None else user_ns
286 283
287 284 cfg = InlineBackend.instance(config=shell.config)
288 285 cfg.shell = shell
289 286 if cfg not in shell.configurables:
290 287 shell.configurables.append(cfg)
291 288
292 289 if backend == backends['inline']:
293 290 from IPython.zmq.pylab.backend_inline import flush_figures
294 291 from matplotlib import pyplot
295 292 shell.register_post_execute(flush_figures)
296 293 # load inline_rc
297 294 pyplot.rcParams.update(cfg.rc)
298 295 # Add 'figsize' to pyplot and to the user's namespace
299 296 user_ns['figsize'] = pyplot.figsize = figsize
300 297
301 298 # Setup the default figure format
302 299 fmt = cfg.figure_format
303 300 select_figure_format(shell, fmt)
304 301
305 302 # The old pastefig function has been replaced by display
306 303 from IPython.core.display import display
307 304 # Add display and getfigs to the user's namespace
308 305 user_ns['display'] = display
309 306 user_ns['getfigs'] = getfigs
310 307
311 308
312 309 def pylab_activate(user_ns, gui=None, import_all=True, shell=None):
313 310 """Activate pylab mode in the user's namespace.
314 311
315 312 Loads and initializes numpy, matplotlib and friends for interactive use.
316 313
317 314 Parameters
318 315 ----------
319 316 user_ns : dict
320 317 Namespace where the imports will occur.
321 318
322 319 gui : optional, string
323 320 A valid gui name following the conventions of the %gui magic.
324 321
325 322 import_all : optional, boolean
326 323 If true, an 'import *' is done from numpy and pylab.
327 324
328 325 Returns
329 326 -------
330 327 The actual gui used (if not given as input, it was obtained from matplotlib
331 328 itself, and will be needed next to configure IPython's gui integration.
332 329 """
333 330 gui, backend = find_gui_and_backend(gui)
334 331 activate_matplotlib(backend)
335 332 import_pylab(user_ns, import_all)
336 configure_inline_support(shell, backend, user_ns)
333 if shell is not None:
334 configure_inline_support(shell, backend, user_ns)
337 335
338 336 print """
339 337 Welcome to pylab, a matplotlib-based Python environment [backend: %s].
340 338 For more information, type 'help(pylab)'.""" % backend
341 339 # flush stdout, just to be safe
342 340 sys.stdout.flush()
343 341
344 342 return gui
345 343
General Comments 0
You need to be logged in to leave comments. Login now