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