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