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