##// END OF EJS Templates
Display figures with no axes but lines, which are also valid.
Fernando Perez -
Show More
@@ -1,342 +1,342 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 if not fig.axes:
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 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
263 263 backend : matplotlib backend
264 264
265 265 user_ns : dict
266 266 A namespace where all configured variables will be placed. If not given,
267 267 the `user_ns` attribute of the shell object is used.
268 268 """
269 269 # If using our svg payload backend, register the post-execution
270 270 # function that will pick up the results for display. This can only be
271 271 # done with access to the real shell object.
272 272
273 273 # Note: if we can't load the inline backend, then there's no point
274 274 # continuing (such as in terminal-only shells in environments without
275 275 # zeromq available).
276 276 try:
277 277 from IPython.zmq.pylab.backend_inline import InlineBackend
278 278 except ImportError:
279 279 return
280 280
281 281 user_ns = shell.user_ns if user_ns is None else user_ns
282 282
283 283 cfg = InlineBackend.instance(config=shell.config)
284 284 cfg.shell = shell
285 285 if cfg not in shell.configurables:
286 286 shell.configurables.append(cfg)
287 287
288 288 if backend == backends['inline']:
289 289 from IPython.zmq.pylab.backend_inline import flush_figures
290 290 from matplotlib import pyplot
291 291 shell.register_post_execute(flush_figures)
292 292 # load inline_rc
293 293 pyplot.rcParams.update(cfg.rc)
294 294 # Add 'figsize' to pyplot and to the user's namespace
295 295 user_ns['figsize'] = pyplot.figsize = figsize
296 296
297 297 # Setup the default figure format
298 298 fmt = cfg.figure_format
299 299 select_figure_format(shell, fmt)
300 300
301 301 # The old pastefig function has been replaced by display
302 302 from IPython.core.display import display
303 303 # Add display and getfigs to the user's namespace
304 304 user_ns['display'] = display
305 305 user_ns['getfigs'] = getfigs
306 306
307 307
308 308 def pylab_activate(user_ns, gui=None, import_all=True, shell=None):
309 309 """Activate pylab mode in the user's namespace.
310 310
311 311 Loads and initializes numpy, matplotlib and friends for interactive use.
312 312
313 313 Parameters
314 314 ----------
315 315 user_ns : dict
316 316 Namespace where the imports will occur.
317 317
318 318 gui : optional, string
319 319 A valid gui name following the conventions of the %gui magic.
320 320
321 321 import_all : optional, boolean
322 322 If true, an 'import *' is done from numpy and pylab.
323 323
324 324 Returns
325 325 -------
326 326 The actual gui used (if not given as input, it was obtained from matplotlib
327 327 itself, and will be needed next to configure IPython's gui integration.
328 328 """
329 329 gui, backend = find_gui_and_backend(gui)
330 330 activate_matplotlib(backend)
331 331 import_pylab(user_ns, import_all)
332 332 if shell is not None:
333 333 configure_inline_support(shell, backend, user_ns)
334 334
335 335 print """
336 336 Welcome to pylab, a matplotlib-based Python environment [backend: %s].
337 337 For more information, type 'help(pylab)'.""" % backend
338 338 # flush stdout, just to be safe
339 339 sys.stdout.flush()
340 340
341 341 return gui
342 342
General Comments 0
You need to be logged in to leave comments. Login now