##// END OF EJS Templates
enable retina display of Image objects...
MinRK -
Show More
@@ -1,635 +1,689
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """Top-level display functions for displaying object in different formats.
2 """Top-level display functions for displaying object in different formats.
3
3
4 Authors:
4 Authors:
5
5
6 * Brian Granger
6 * Brian Granger
7 """
7 """
8
8
9 #-----------------------------------------------------------------------------
9 #-----------------------------------------------------------------------------
10 # Copyright (C) 2013 The IPython Development Team
10 # Copyright (C) 2013 The IPython Development Team
11 #
11 #
12 # Distributed under the terms of the BSD License. The full license is in
12 # Distributed under the terms of the BSD License. The full license is in
13 # the file COPYING, distributed as part of this software.
13 # the file COPYING, distributed as part of this software.
14 #-----------------------------------------------------------------------------
14 #-----------------------------------------------------------------------------
15
15
16 #-----------------------------------------------------------------------------
16 #-----------------------------------------------------------------------------
17 # Imports
17 # Imports
18 #-----------------------------------------------------------------------------
18 #-----------------------------------------------------------------------------
19
19
20 from __future__ import print_function
20 from __future__ import print_function
21
21
22 import os
22 import os
23 import struct
23
24
24 from IPython.utils.py3compat import string_types
25 from IPython.utils.py3compat import string_types
25
26
26 from .displaypub import publish_display_data
27 from .displaypub import publish_display_data
27
28
28 #-----------------------------------------------------------------------------
29 #-----------------------------------------------------------------------------
29 # utility functions
30 # utility functions
30 #-----------------------------------------------------------------------------
31 #-----------------------------------------------------------------------------
31
32
32 def _safe_exists(path):
33 def _safe_exists(path):
33 """Check path, but don't let exceptions raise"""
34 """Check path, but don't let exceptions raise"""
34 try:
35 try:
35 return os.path.exists(path)
36 return os.path.exists(path)
36 except Exception:
37 except Exception:
37 return False
38 return False
38
39
39 def _merge(d1, d2):
40 def _merge(d1, d2):
40 """Like update, but merges sub-dicts instead of clobbering at the top level.
41 """Like update, but merges sub-dicts instead of clobbering at the top level.
41
42
42 Updates d1 in-place
43 Updates d1 in-place
43 """
44 """
44
45
45 if not isinstance(d2, dict) or not isinstance(d1, dict):
46 if not isinstance(d2, dict) or not isinstance(d1, dict):
46 return d2
47 return d2
47 for key, value in d2.items():
48 for key, value in d2.items():
48 d1[key] = _merge(d1.get(key), value)
49 d1[key] = _merge(d1.get(key), value)
49 return d1
50 return d1
50
51
51 def _display_mimetype(mimetype, objs, raw=False, metadata=None):
52 def _display_mimetype(mimetype, objs, raw=False, metadata=None):
52 """internal implementation of all display_foo methods
53 """internal implementation of all display_foo methods
53
54
54 Parameters
55 Parameters
55 ----------
56 ----------
56 mimetype : str
57 mimetype : str
57 The mimetype to be published (e.g. 'image/png')
58 The mimetype to be published (e.g. 'image/png')
58 objs : tuple of objects
59 objs : tuple of objects
59 The Python objects to display, or if raw=True raw text data to
60 The Python objects to display, or if raw=True raw text data to
60 display.
61 display.
61 raw : bool
62 raw : bool
62 Are the data objects raw data or Python objects that need to be
63 Are the data objects raw data or Python objects that need to be
63 formatted before display? [default: False]
64 formatted before display? [default: False]
64 metadata : dict (optional)
65 metadata : dict (optional)
65 Metadata to be associated with the specific mimetype output.
66 Metadata to be associated with the specific mimetype output.
66 """
67 """
67 if metadata:
68 if metadata:
68 metadata = {mimetype: metadata}
69 metadata = {mimetype: metadata}
69 if raw:
70 if raw:
70 # turn list of pngdata into list of { 'image/png': pngdata }
71 # turn list of pngdata into list of { 'image/png': pngdata }
71 objs = [ {mimetype: obj} for obj in objs ]
72 objs = [ {mimetype: obj} for obj in objs ]
72 display(*objs, raw=raw, metadata=metadata, include=[mimetype])
73 display(*objs, raw=raw, metadata=metadata, include=[mimetype])
73
74
74 #-----------------------------------------------------------------------------
75 #-----------------------------------------------------------------------------
75 # Main functions
76 # Main functions
76 #-----------------------------------------------------------------------------
77 #-----------------------------------------------------------------------------
77
78
78 def display(*objs, **kwargs):
79 def display(*objs, **kwargs):
79 """Display a Python object in all frontends.
80 """Display a Python object in all frontends.
80
81
81 By default all representations will be computed and sent to the frontends.
82 By default all representations will be computed and sent to the frontends.
82 Frontends can decide which representation is used and how.
83 Frontends can decide which representation is used and how.
83
84
84 Parameters
85 Parameters
85 ----------
86 ----------
86 objs : tuple of objects
87 objs : tuple of objects
87 The Python objects to display.
88 The Python objects to display.
88 raw : bool, optional
89 raw : bool, optional
89 Are the objects to be displayed already mimetype-keyed dicts of raw display data,
90 Are the objects to be displayed already mimetype-keyed dicts of raw display data,
90 or Python objects that need to be formatted before display? [default: False]
91 or Python objects that need to be formatted before display? [default: False]
91 include : list or tuple, optional
92 include : list or tuple, optional
92 A list of format type strings (MIME types) to include in the
93 A list of format type strings (MIME types) to include in the
93 format data dict. If this is set *only* the format types included
94 format data dict. If this is set *only* the format types included
94 in this list will be computed.
95 in this list will be computed.
95 exclude : list or tuple, optional
96 exclude : list or tuple, optional
96 A list of format type strings (MIME types) to exclude in the format
97 A list of format type strings (MIME types) to exclude in the format
97 data dict. If this is set all format types will be computed,
98 data dict. If this is set all format types will be computed,
98 except for those included in this argument.
99 except for those included in this argument.
99 metadata : dict, optional
100 metadata : dict, optional
100 A dictionary of metadata to associate with the output.
101 A dictionary of metadata to associate with the output.
101 mime-type keys in this dictionary will be associated with the individual
102 mime-type keys in this dictionary will be associated with the individual
102 representation formats, if they exist.
103 representation formats, if they exist.
103 """
104 """
104 raw = kwargs.get('raw', False)
105 raw = kwargs.get('raw', False)
105 include = kwargs.get('include')
106 include = kwargs.get('include')
106 exclude = kwargs.get('exclude')
107 exclude = kwargs.get('exclude')
107 metadata = kwargs.get('metadata')
108 metadata = kwargs.get('metadata')
108
109
109 from IPython.core.interactiveshell import InteractiveShell
110 from IPython.core.interactiveshell import InteractiveShell
110
111
111 if raw:
112 if raw:
112 for obj in objs:
113 for obj in objs:
113 publish_display_data('display', obj, metadata)
114 publish_display_data('display', obj, metadata)
114 else:
115 else:
115 format = InteractiveShell.instance().display_formatter.format
116 format = InteractiveShell.instance().display_formatter.format
116 for obj in objs:
117 for obj in objs:
117 format_dict, md_dict = format(obj, include=include, exclude=exclude)
118 format_dict, md_dict = format(obj, include=include, exclude=exclude)
118 if metadata:
119 if metadata:
119 # kwarg-specified metadata gets precedence
120 # kwarg-specified metadata gets precedence
120 _merge(md_dict, metadata)
121 _merge(md_dict, metadata)
121 publish_display_data('display', format_dict, md_dict)
122 publish_display_data('display', format_dict, md_dict)
122
123
123
124
124 def display_pretty(*objs, **kwargs):
125 def display_pretty(*objs, **kwargs):
125 """Display the pretty (default) representation of an object.
126 """Display the pretty (default) representation of an object.
126
127
127 Parameters
128 Parameters
128 ----------
129 ----------
129 objs : tuple of objects
130 objs : tuple of objects
130 The Python objects to display, or if raw=True raw text data to
131 The Python objects to display, or if raw=True raw text data to
131 display.
132 display.
132 raw : bool
133 raw : bool
133 Are the data objects raw data or Python objects that need to be
134 Are the data objects raw data or Python objects that need to be
134 formatted before display? [default: False]
135 formatted before display? [default: False]
135 metadata : dict (optional)
136 metadata : dict (optional)
136 Metadata to be associated with the specific mimetype output.
137 Metadata to be associated with the specific mimetype output.
137 """
138 """
138 _display_mimetype('text/plain', objs, **kwargs)
139 _display_mimetype('text/plain', objs, **kwargs)
139
140
140
141
141 def display_html(*objs, **kwargs):
142 def display_html(*objs, **kwargs):
142 """Display the HTML representation of an object.
143 """Display the HTML representation of an object.
143
144
144 Parameters
145 Parameters
145 ----------
146 ----------
146 objs : tuple of objects
147 objs : tuple of objects
147 The Python objects to display, or if raw=True raw HTML data to
148 The Python objects to display, or if raw=True raw HTML data to
148 display.
149 display.
149 raw : bool
150 raw : bool
150 Are the data objects raw data or Python objects that need to be
151 Are the data objects raw data or Python objects that need to be
151 formatted before display? [default: False]
152 formatted before display? [default: False]
152 metadata : dict (optional)
153 metadata : dict (optional)
153 Metadata to be associated with the specific mimetype output.
154 Metadata to be associated with the specific mimetype output.
154 """
155 """
155 _display_mimetype('text/html', objs, **kwargs)
156 _display_mimetype('text/html', objs, **kwargs)
156
157
157
158
158 def display_svg(*objs, **kwargs):
159 def display_svg(*objs, **kwargs):
159 """Display the SVG representation of an object.
160 """Display the SVG representation of an object.
160
161
161 Parameters
162 Parameters
162 ----------
163 ----------
163 objs : tuple of objects
164 objs : tuple of objects
164 The Python objects to display, or if raw=True raw svg data to
165 The Python objects to display, or if raw=True raw svg data to
165 display.
166 display.
166 raw : bool
167 raw : bool
167 Are the data objects raw data or Python objects that need to be
168 Are the data objects raw data or Python objects that need to be
168 formatted before display? [default: False]
169 formatted before display? [default: False]
169 metadata : dict (optional)
170 metadata : dict (optional)
170 Metadata to be associated with the specific mimetype output.
171 Metadata to be associated with the specific mimetype output.
171 """
172 """
172 _display_mimetype('image/svg+xml', objs, **kwargs)
173 _display_mimetype('image/svg+xml', objs, **kwargs)
173
174
174
175
175 def display_png(*objs, **kwargs):
176 def display_png(*objs, **kwargs):
176 """Display the PNG representation of an object.
177 """Display the PNG representation of an object.
177
178
178 Parameters
179 Parameters
179 ----------
180 ----------
180 objs : tuple of objects
181 objs : tuple of objects
181 The Python objects to display, or if raw=True raw png data to
182 The Python objects to display, or if raw=True raw png data to
182 display.
183 display.
183 raw : bool
184 raw : bool
184 Are the data objects raw data or Python objects that need to be
185 Are the data objects raw data or Python objects that need to be
185 formatted before display? [default: False]
186 formatted before display? [default: False]
186 metadata : dict (optional)
187 metadata : dict (optional)
187 Metadata to be associated with the specific mimetype output.
188 Metadata to be associated with the specific mimetype output.
188 """
189 """
189 _display_mimetype('image/png', objs, **kwargs)
190 _display_mimetype('image/png', objs, **kwargs)
190
191
191
192
192 def display_jpeg(*objs, **kwargs):
193 def display_jpeg(*objs, **kwargs):
193 """Display the JPEG representation of an object.
194 """Display the JPEG representation of an object.
194
195
195 Parameters
196 Parameters
196 ----------
197 ----------
197 objs : tuple of objects
198 objs : tuple of objects
198 The Python objects to display, or if raw=True raw JPEG data to
199 The Python objects to display, or if raw=True raw JPEG data to
199 display.
200 display.
200 raw : bool
201 raw : bool
201 Are the data objects raw data or Python objects that need to be
202 Are the data objects raw data or Python objects that need to be
202 formatted before display? [default: False]
203 formatted before display? [default: False]
203 metadata : dict (optional)
204 metadata : dict (optional)
204 Metadata to be associated with the specific mimetype output.
205 Metadata to be associated with the specific mimetype output.
205 """
206 """
206 _display_mimetype('image/jpeg', objs, **kwargs)
207 _display_mimetype('image/jpeg', objs, **kwargs)
207
208
208
209
209 def display_latex(*objs, **kwargs):
210 def display_latex(*objs, **kwargs):
210 """Display the LaTeX representation of an object.
211 """Display the LaTeX representation of an object.
211
212
212 Parameters
213 Parameters
213 ----------
214 ----------
214 objs : tuple of objects
215 objs : tuple of objects
215 The Python objects to display, or if raw=True raw latex data to
216 The Python objects to display, or if raw=True raw latex data to
216 display.
217 display.
217 raw : bool
218 raw : bool
218 Are the data objects raw data or Python objects that need to be
219 Are the data objects raw data or Python objects that need to be
219 formatted before display? [default: False]
220 formatted before display? [default: False]
220 metadata : dict (optional)
221 metadata : dict (optional)
221 Metadata to be associated with the specific mimetype output.
222 Metadata to be associated with the specific mimetype output.
222 """
223 """
223 _display_mimetype('text/latex', objs, **kwargs)
224 _display_mimetype('text/latex', objs, **kwargs)
224
225
225
226
226 def display_json(*objs, **kwargs):
227 def display_json(*objs, **kwargs):
227 """Display the JSON representation of an object.
228 """Display the JSON representation of an object.
228
229
229 Note that not many frontends support displaying JSON.
230 Note that not many frontends support displaying JSON.
230
231
231 Parameters
232 Parameters
232 ----------
233 ----------
233 objs : tuple of objects
234 objs : tuple of objects
234 The Python objects to display, or if raw=True raw json data to
235 The Python objects to display, or if raw=True raw json data to
235 display.
236 display.
236 raw : bool
237 raw : bool
237 Are the data objects raw data or Python objects that need to be
238 Are the data objects raw data or Python objects that need to be
238 formatted before display? [default: False]
239 formatted before display? [default: False]
239 metadata : dict (optional)
240 metadata : dict (optional)
240 Metadata to be associated with the specific mimetype output.
241 Metadata to be associated with the specific mimetype output.
241 """
242 """
242 _display_mimetype('application/json', objs, **kwargs)
243 _display_mimetype('application/json', objs, **kwargs)
243
244
244
245
245 def display_javascript(*objs, **kwargs):
246 def display_javascript(*objs, **kwargs):
246 """Display the Javascript representation of an object.
247 """Display the Javascript representation of an object.
247
248
248 Parameters
249 Parameters
249 ----------
250 ----------
250 objs : tuple of objects
251 objs : tuple of objects
251 The Python objects to display, or if raw=True raw javascript data to
252 The Python objects to display, or if raw=True raw javascript data to
252 display.
253 display.
253 raw : bool
254 raw : bool
254 Are the data objects raw data or Python objects that need to be
255 Are the data objects raw data or Python objects that need to be
255 formatted before display? [default: False]
256 formatted before display? [default: False]
256 metadata : dict (optional)
257 metadata : dict (optional)
257 Metadata to be associated with the specific mimetype output.
258 Metadata to be associated with the specific mimetype output.
258 """
259 """
259 _display_mimetype('application/javascript', objs, **kwargs)
260 _display_mimetype('application/javascript', objs, **kwargs)
260
261
261 #-----------------------------------------------------------------------------
262 #-----------------------------------------------------------------------------
262 # Smart classes
263 # Smart classes
263 #-----------------------------------------------------------------------------
264 #-----------------------------------------------------------------------------
264
265
265
266
266 class DisplayObject(object):
267 class DisplayObject(object):
267 """An object that wraps data to be displayed."""
268 """An object that wraps data to be displayed."""
268
269
269 _read_flags = 'r'
270 _read_flags = 'r'
270
271
271 def __init__(self, data=None, url=None, filename=None):
272 def __init__(self, data=None, url=None, filename=None):
272 """Create a display object given raw data.
273 """Create a display object given raw data.
273
274
274 When this object is returned by an expression or passed to the
275 When this object is returned by an expression or passed to the
275 display function, it will result in the data being displayed
276 display function, it will result in the data being displayed
276 in the frontend. The MIME type of the data should match the
277 in the frontend. The MIME type of the data should match the
277 subclasses used, so the Png subclass should be used for 'image/png'
278 subclasses used, so the Png subclass should be used for 'image/png'
278 data. If the data is a URL, the data will first be downloaded
279 data. If the data is a URL, the data will first be downloaded
279 and then displayed. If
280 and then displayed. If
280
281
281 Parameters
282 Parameters
282 ----------
283 ----------
283 data : unicode, str or bytes
284 data : unicode, str or bytes
284 The raw data or a URL or file to load the data from
285 The raw data or a URL or file to load the data from
285 url : unicode
286 url : unicode
286 A URL to download the data from.
287 A URL to download the data from.
287 filename : unicode
288 filename : unicode
288 Path to a local file to load the data from.
289 Path to a local file to load the data from.
289 """
290 """
290 if data is not None and isinstance(data, string_types):
291 if data is not None and isinstance(data, string_types):
291 if data.startswith('http') and url is None:
292 if data.startswith('http') and url is None:
292 url = data
293 url = data
293 filename = None
294 filename = None
294 data = None
295 data = None
295 elif _safe_exists(data) and filename is None:
296 elif _safe_exists(data) and filename is None:
296 url = None
297 url = None
297 filename = data
298 filename = data
298 data = None
299 data = None
299
300
300 self.data = data
301 self.data = data
301 self.url = url
302 self.url = url
302 self.filename = None if filename is None else unicode(filename)
303 self.filename = None if filename is None else unicode(filename)
303
304
304 self.reload()
305 self.reload()
305
306
306 def reload(self):
307 def reload(self):
307 """Reload the raw data from file or URL."""
308 """Reload the raw data from file or URL."""
308 if self.filename is not None:
309 if self.filename is not None:
309 with open(self.filename, self._read_flags) as f:
310 with open(self.filename, self._read_flags) as f:
310 self.data = f.read()
311 self.data = f.read()
311 elif self.url is not None:
312 elif self.url is not None:
312 try:
313 try:
313 import urllib2
314 import urllib2
314 response = urllib2.urlopen(self.url)
315 response = urllib2.urlopen(self.url)
315 self.data = response.read()
316 self.data = response.read()
316 # extract encoding from header, if there is one:
317 # extract encoding from header, if there is one:
317 encoding = None
318 encoding = None
318 for sub in response.headers['content-type'].split(';'):
319 for sub in response.headers['content-type'].split(';'):
319 sub = sub.strip()
320 sub = sub.strip()
320 if sub.startswith('charset'):
321 if sub.startswith('charset'):
321 encoding = sub.split('=')[-1].strip()
322 encoding = sub.split('=')[-1].strip()
322 break
323 break
323 # decode data, if an encoding was specified
324 # decode data, if an encoding was specified
324 if encoding:
325 if encoding:
325 self.data = self.data.decode(encoding, 'replace')
326 self.data = self.data.decode(encoding, 'replace')
326 except:
327 except:
327 self.data = None
328 self.data = None
328
329
329 class Pretty(DisplayObject):
330 class Pretty(DisplayObject):
330
331
331 def _repr_pretty_(self):
332 def _repr_pretty_(self):
332 return self.data
333 return self.data
333
334
334
335
335 class HTML(DisplayObject):
336 class HTML(DisplayObject):
336
337
337 def _repr_html_(self):
338 def _repr_html_(self):
338 return self.data
339 return self.data
339
340
340 def __html__(self):
341 def __html__(self):
341 """
342 """
342 This method exists to inform other HTML-using modules (e.g. Markupsafe,
343 This method exists to inform other HTML-using modules (e.g. Markupsafe,
343 htmltag, etc) that this object is HTML and does not need things like
344 htmltag, etc) that this object is HTML and does not need things like
344 special characters (<>&) escaped.
345 special characters (<>&) escaped.
345 """
346 """
346 return self._repr_html_()
347 return self._repr_html_()
347
348
348
349
349 class Math(DisplayObject):
350 class Math(DisplayObject):
350
351
351 def _repr_latex_(self):
352 def _repr_latex_(self):
352 s = self.data.strip('$')
353 s = self.data.strip('$')
353 return "$$%s$$" % s
354 return "$$%s$$" % s
354
355
355
356
356 class Latex(DisplayObject):
357 class Latex(DisplayObject):
357
358
358 def _repr_latex_(self):
359 def _repr_latex_(self):
359 return self.data
360 return self.data
360
361
361
362
362 class SVG(DisplayObject):
363 class SVG(DisplayObject):
363
364
364 # wrap data in a property, which extracts the <svg> tag, discarding
365 # wrap data in a property, which extracts the <svg> tag, discarding
365 # document headers
366 # document headers
366 _data = None
367 _data = None
367
368
368 @property
369 @property
369 def data(self):
370 def data(self):
370 return self._data
371 return self._data
371
372
372 @data.setter
373 @data.setter
373 def data(self, svg):
374 def data(self, svg):
374 if svg is None:
375 if svg is None:
375 self._data = None
376 self._data = None
376 return
377 return
377 # parse into dom object
378 # parse into dom object
378 from xml.dom import minidom
379 from xml.dom import minidom
379 x = minidom.parseString(svg)
380 x = minidom.parseString(svg)
380 # get svg tag (should be 1)
381 # get svg tag (should be 1)
381 found_svg = x.getElementsByTagName('svg')
382 found_svg = x.getElementsByTagName('svg')
382 if found_svg:
383 if found_svg:
383 svg = found_svg[0].toxml()
384 svg = found_svg[0].toxml()
384 else:
385 else:
385 # fallback on the input, trust the user
386 # fallback on the input, trust the user
386 # but this is probably an error.
387 # but this is probably an error.
387 pass
388 pass
388 self._data = svg
389 self._data = svg
389
390
390 def _repr_svg_(self):
391 def _repr_svg_(self):
391 return self.data
392 return self.data
392
393
393
394
394 class JSON(DisplayObject):
395 class JSON(DisplayObject):
395
396
396 def _repr_json_(self):
397 def _repr_json_(self):
397 return self.data
398 return self.data
398
399
399 css_t = """$("head").append($("<link/>").attr({
400 css_t = """$("head").append($("<link/>").attr({
400 rel: "stylesheet",
401 rel: "stylesheet",
401 type: "text/css",
402 type: "text/css",
402 href: "%s"
403 href: "%s"
403 }));
404 }));
404 """
405 """
405
406
406 lib_t1 = """$.getScript("%s", function () {
407 lib_t1 = """$.getScript("%s", function () {
407 """
408 """
408 lib_t2 = """});
409 lib_t2 = """});
409 """
410 """
410
411
411 class Javascript(DisplayObject):
412 class Javascript(DisplayObject):
412
413
413 def __init__(self, data=None, url=None, filename=None, lib=None, css=None):
414 def __init__(self, data=None, url=None, filename=None, lib=None, css=None):
414 """Create a Javascript display object given raw data.
415 """Create a Javascript display object given raw data.
415
416
416 When this object is returned by an expression or passed to the
417 When this object is returned by an expression or passed to the
417 display function, it will result in the data being displayed
418 display function, it will result in the data being displayed
418 in the frontend. If the data is a URL, the data will first be
419 in the frontend. If the data is a URL, the data will first be
419 downloaded and then displayed.
420 downloaded and then displayed.
420
421
421 In the Notebook, the containing element will be available as `element`,
422 In the Notebook, the containing element will be available as `element`,
422 and jQuery will be available. The output area starts hidden, so if
423 and jQuery will be available. The output area starts hidden, so if
423 the js appends content to `element` that should be visible, then
424 the js appends content to `element` that should be visible, then
424 it must call `container.show()` to unhide the area.
425 it must call `container.show()` to unhide the area.
425
426
426 Parameters
427 Parameters
427 ----------
428 ----------
428 data : unicode, str or bytes
429 data : unicode, str or bytes
429 The Javascript source code or a URL to download it from.
430 The Javascript source code or a URL to download it from.
430 url : unicode
431 url : unicode
431 A URL to download the data from.
432 A URL to download the data from.
432 filename : unicode
433 filename : unicode
433 Path to a local file to load the data from.
434 Path to a local file to load the data from.
434 lib : list or str
435 lib : list or str
435 A sequence of Javascript library URLs to load asynchronously before
436 A sequence of Javascript library URLs to load asynchronously before
436 running the source code. The full URLs of the libraries should
437 running the source code. The full URLs of the libraries should
437 be given. A single Javascript library URL can also be given as a
438 be given. A single Javascript library URL can also be given as a
438 string.
439 string.
439 css: : list or str
440 css: : list or str
440 A sequence of css files to load before running the source code.
441 A sequence of css files to load before running the source code.
441 The full URLs of the css files should be given. A single css URL
442 The full URLs of the css files should be given. A single css URL
442 can also be given as a string.
443 can also be given as a string.
443 """
444 """
444 if isinstance(lib, basestring):
445 if isinstance(lib, basestring):
445 lib = [lib]
446 lib = [lib]
446 elif lib is None:
447 elif lib is None:
447 lib = []
448 lib = []
448 if isinstance(css, basestring):
449 if isinstance(css, basestring):
449 css = [css]
450 css = [css]
450 elif css is None:
451 elif css is None:
451 css = []
452 css = []
452 if not isinstance(lib, (list,tuple)):
453 if not isinstance(lib, (list,tuple)):
453 raise TypeError('expected sequence, got: %r' % lib)
454 raise TypeError('expected sequence, got: %r' % lib)
454 if not isinstance(css, (list,tuple)):
455 if not isinstance(css, (list,tuple)):
455 raise TypeError('expected sequence, got: %r' % css)
456 raise TypeError('expected sequence, got: %r' % css)
456 self.lib = lib
457 self.lib = lib
457 self.css = css
458 self.css = css
458 super(Javascript, self).__init__(data=data, url=url, filename=filename)
459 super(Javascript, self).__init__(data=data, url=url, filename=filename)
459
460
460 def _repr_javascript_(self):
461 def _repr_javascript_(self):
461 r = ''
462 r = ''
462 for c in self.css:
463 for c in self.css:
463 r += css_t % c
464 r += css_t % c
464 for l in self.lib:
465 for l in self.lib:
465 r += lib_t1 % l
466 r += lib_t1 % l
466 r += self.data
467 r += self.data
467 r += lib_t2*len(self.lib)
468 r += lib_t2*len(self.lib)
468 return r
469 return r
469
470
470 # constants for identifying png/jpeg data
471 # constants for identifying png/jpeg data
471 _PNG = b'\x89PNG\r\n\x1a\n'
472 _PNG = b'\x89PNG\r\n\x1a\n'
472 _JPEG = b'\xff\xd8'
473 _JPEG = b'\xff\xd8'
473
474
475 def _pngxy(data):
476 """read the (width, height) from a PNG header"""
477 ihdr = data.index(b'IHDR')
478 # next 8 bytes are width/height
479 w4h4 = data[ihdr+4:ihdr+12]
480 return struct.unpack('>ii', w4h4)
481
482 def _jpegxy(data):
483 """read the (width, height) from a JPEG header"""
484 # adapted from http://www.64lines.com/jpeg-width-height
485
486 idx = 4
487 while True:
488 block_size = struct.unpack('>H', data[idx:idx+2])[0]
489 idx = idx + block_size
490 if data[idx:idx+2] == b'\xFF\xC0':
491 # found Start of Frame
492 iSOF = idx
493 break
494 else:
495 # read another block
496 idx += 2
497
498 h, w = struct.unpack('>HH', data[iSOF+5:iSOF+9])
499 return w, h
500
474 class Image(DisplayObject):
501 class Image(DisplayObject):
475
502
476 _read_flags = 'rb'
503 _read_flags = 'rb'
477 _FMT_JPEG = u'jpeg'
504 _FMT_JPEG = u'jpeg'
478 _FMT_PNG = u'png'
505 _FMT_PNG = u'png'
479 _ACCEPTABLE_EMBEDDINGS = [_FMT_JPEG, _FMT_PNG]
506 _ACCEPTABLE_EMBEDDINGS = [_FMT_JPEG, _FMT_PNG]
480
507
481 def __init__(self, data=None, url=None, filename=None, format=u'png', embed=None, width=None, height=None):
508 def __init__(self, data=None, url=None, filename=None, format=u'png', embed=None, width=None, height=None, retina=False):
482 """Create a display an PNG/JPEG image given raw data.
509 """Create a display an PNG/JPEG image given raw data.
483
510
484 When this object is returned by an expression or passed to the
511 When this object is returned by an expression or passed to the
485 display function, it will result in the image being displayed
512 display function, it will result in the image being displayed
486 in the frontend.
513 in the frontend.
487
514
488 Parameters
515 Parameters
489 ----------
516 ----------
490 data : unicode, str or bytes
517 data : unicode, str or bytes
491 The raw image data or a URL or filename to load the data from.
518 The raw image data or a URL or filename to load the data from.
492 This always results in embedded image data.
519 This always results in embedded image data.
493 url : unicode
520 url : unicode
494 A URL to download the data from. If you specify `url=`,
521 A URL to download the data from. If you specify `url=`,
495 the image data will not be embedded unless you also specify `embed=True`.
522 the image data will not be embedded unless you also specify `embed=True`.
496 filename : unicode
523 filename : unicode
497 Path to a local file to load the data from.
524 Path to a local file to load the data from.
498 Images from a file are always embedded.
525 Images from a file are always embedded.
499 format : unicode
526 format : unicode
500 The format of the image data (png/jpeg/jpg). If a filename or URL is given
527 The format of the image data (png/jpeg/jpg). If a filename or URL is given
501 for format will be inferred from the filename extension.
528 for format will be inferred from the filename extension.
502 embed : bool
529 embed : bool
503 Should the image data be embedded using a data URI (True) or be
530 Should the image data be embedded using a data URI (True) or be
504 loaded using an <img> tag. Set this to True if you want the image
531 loaded using an <img> tag. Set this to True if you want the image
505 to be viewable later with no internet connection in the notebook.
532 to be viewable later with no internet connection in the notebook.
506
533
507 Default is `True`, unless the keyword argument `url` is set, then
534 Default is `True`, unless the keyword argument `url` is set, then
508 default value is `False`.
535 default value is `False`.
509
536
510 Note that QtConsole is not able to display images if `embed` is set to `False`
537 Note that QtConsole is not able to display images if `embed` is set to `False`
511 width : int
538 width : int
512 Width to which to constrain the image in html
539 Width to which to constrain the image in html
513 height : int
540 height : int
514 Height to which to constrain the image in html
541 Height to which to constrain the image in html
542 retina : bool
543 Automatically set the width and height to half of the measured
544 width and height.
545 This only works for embedded images because it reads the width/height
546 from image data.
547 For non-embedded images, you can just set the desired display width
548 and height directly.
515
549
516 Examples
550 Examples
517 --------
551 --------
518 # embedded image data, works in qtconsole and notebook
552 # embedded image data, works in qtconsole and notebook
519 # when passed positionally, the first arg can be any of raw image data,
553 # when passed positionally, the first arg can be any of raw image data,
520 # a URL, or a filename from which to load image data.
554 # a URL, or a filename from which to load image data.
521 # The result is always embedding image data for inline images.
555 # The result is always embedding image data for inline images.
522 Image('http://www.google.fr/images/srpr/logo3w.png')
556 Image('http://www.google.fr/images/srpr/logo3w.png')
523 Image('/path/to/image.jpg')
557 Image('/path/to/image.jpg')
524 Image(b'RAW_PNG_DATA...')
558 Image(b'RAW_PNG_DATA...')
525
559
526 # Specifying Image(url=...) does not embed the image data,
560 # Specifying Image(url=...) does not embed the image data,
527 # it only generates `<img>` tag with a link to the source.
561 # it only generates `<img>` tag with a link to the source.
528 # This will not work in the qtconsole or offline.
562 # This will not work in the qtconsole or offline.
529 Image(url='http://www.google.fr/images/srpr/logo3w.png')
563 Image(url='http://www.google.fr/images/srpr/logo3w.png')
530
564
531 """
565 """
532 if filename is not None:
566 if filename is not None:
533 ext = self._find_ext(filename)
567 ext = self._find_ext(filename)
534 elif url is not None:
568 elif url is not None:
535 ext = self._find_ext(url)
569 ext = self._find_ext(url)
536 elif data is None:
570 elif data is None:
537 raise ValueError("No image data found. Expecting filename, url, or data.")
571 raise ValueError("No image data found. Expecting filename, url, or data.")
538 elif isinstance(data, string_types) and (
572 elif isinstance(data, string_types) and (
539 data.startswith('http') or _safe_exists(data)
573 data.startswith('http') or _safe_exists(data)
540 ):
574 ):
541 ext = self._find_ext(data)
575 ext = self._find_ext(data)
542 else:
576 else:
543 ext = None
577 ext = None
544
578
545 if ext is not None:
579 if ext is not None:
546 format = ext.lower()
580 format = ext.lower()
547 if ext == u'jpg' or ext == u'jpeg':
581 if ext == u'jpg' or ext == u'jpeg':
548 format = self._FMT_JPEG
582 format = self._FMT_JPEG
549 if ext == u'png':
583 if ext == u'png':
550 format = self._FMT_PNG
584 format = self._FMT_PNG
551 elif isinstance(data, bytes) and format == 'png':
585 elif isinstance(data, bytes) and format == 'png':
552 # infer image type from image data header,
586 # infer image type from image data header,
553 # only if format might not have been specified.
587 # only if format might not have been specified.
554 if data[:2] == _JPEG:
588 if data[:2] == _JPEG:
555 format = 'jpeg'
589 format = 'jpeg'
556
590
557 self.format = unicode(format).lower()
591 self.format = unicode(format).lower()
558 self.embed = embed if embed is not None else (url is None)
592 self.embed = embed if embed is not None else (url is None)
559
593
560 if self.embed and self.format not in self._ACCEPTABLE_EMBEDDINGS:
594 if self.embed and self.format not in self._ACCEPTABLE_EMBEDDINGS:
561 raise ValueError("Cannot embed the '%s' image format" % (self.format))
595 raise ValueError("Cannot embed the '%s' image format" % (self.format))
562 self.width = width
596 self.width = width
563 self.height = height
597 self.height = height
598 self.retina = retina
564 super(Image, self).__init__(data=data, url=url, filename=filename)
599 super(Image, self).__init__(data=data, url=url, filename=filename)
565
600
601 if retina:
602 self._retina_shape()
603
604 def _retina_shape(self):
605 """load pixel-doubled width and height from image data"""
606 if not self.embed:
607 return
608 if self.format == 'png':
609 w, h = _pngxy(self.data)
610 elif self.format == 'jpeg':
611 w, h = _jpegxy(self.data)
612 else:
613 # retina only supports png
614 return
615 self.width = w // 2
616 self.height = h // 2
617
566 def reload(self):
618 def reload(self):
567 """Reload the raw data from file or URL."""
619 """Reload the raw data from file or URL."""
568 if self.embed:
620 if self.embed:
569 super(Image,self).reload()
621 super(Image,self).reload()
622 if self.retina:
623 self._retina_shape()
570
624
571 def _repr_html_(self):
625 def _repr_html_(self):
572 if not self.embed:
626 if not self.embed:
573 width = height = ''
627 width = height = ''
574 if self.width:
628 if self.width:
575 width = ' width="%d"' % self.width
629 width = ' width="%d"' % self.width
576 if self.height:
630 if self.height:
577 height = ' height="%d"' % self.height
631 height = ' height="%d"' % self.height
578 return u'<img src="%s"%s%s/>' % (self.url, width, height)
632 return u'<img src="%s"%s%s/>' % (self.url, width, height)
579
633
580 def _data_and_metadata(self):
634 def _data_and_metadata(self):
581 """shortcut for returning metadata with shape information, if defined"""
635 """shortcut for returning metadata with shape information, if defined"""
582 md = {}
636 md = {}
583 if self.width:
637 if self.width:
584 md['width'] = self.width
638 md['width'] = self.width
585 if self.height:
639 if self.height:
586 md['height'] = self.height
640 md['height'] = self.height
587 if md:
641 if md:
588 return self.data, md
642 return self.data, md
589 else:
643 else:
590 return self.data
644 return self.data
591
645
592 def _repr_png_(self):
646 def _repr_png_(self):
593 if self.embed and self.format == u'png':
647 if self.embed and self.format == u'png':
594 return self._data_and_metadata()
648 return self._data_and_metadata()
595
649
596 def _repr_jpeg_(self):
650 def _repr_jpeg_(self):
597 if self.embed and (self.format == u'jpeg' or self.format == u'jpg'):
651 if self.embed and (self.format == u'jpeg' or self.format == u'jpg'):
598 return self._data_and_metadata()
652 return self._data_and_metadata()
599
653
600 def _find_ext(self, s):
654 def _find_ext(self, s):
601 return unicode(s.split('.')[-1].lower())
655 return unicode(s.split('.')[-1].lower())
602
656
603
657
604 def clear_output(stdout=True, stderr=True, other=True):
658 def clear_output(stdout=True, stderr=True, other=True):
605 """Clear the output of the current cell receiving output.
659 """Clear the output of the current cell receiving output.
606
660
607 Optionally, each of stdout/stderr or other non-stream data (e.g. anything
661 Optionally, each of stdout/stderr or other non-stream data (e.g. anything
608 produced by display()) can be excluded from the clear event.
662 produced by display()) can be excluded from the clear event.
609
663
610 By default, everything is cleared.
664 By default, everything is cleared.
611
665
612 Parameters
666 Parameters
613 ----------
667 ----------
614 stdout : bool [default: True]
668 stdout : bool [default: True]
615 Whether to clear stdout.
669 Whether to clear stdout.
616 stderr : bool [default: True]
670 stderr : bool [default: True]
617 Whether to clear stderr.
671 Whether to clear stderr.
618 other : bool [default: True]
672 other : bool [default: True]
619 Whether to clear everything else that is not stdout/stderr
673 Whether to clear everything else that is not stdout/stderr
620 (e.g. figures,images,HTML, any result of display()).
674 (e.g. figures,images,HTML, any result of display()).
621 """
675 """
622 from IPython.core.interactiveshell import InteractiveShell
676 from IPython.core.interactiveshell import InteractiveShell
623 if InteractiveShell.initialized():
677 if InteractiveShell.initialized():
624 InteractiveShell.instance().display_pub.clear_output(
678 InteractiveShell.instance().display_pub.clear_output(
625 stdout=stdout, stderr=stderr, other=other,
679 stdout=stdout, stderr=stderr, other=other,
626 )
680 )
627 else:
681 else:
628 from IPython.utils import io
682 from IPython.utils import io
629 if stdout:
683 if stdout:
630 print('\033[2K\r', file=io.stdout, end='')
684 print('\033[2K\r', file=io.stdout, end='')
631 io.stdout.flush()
685 io.stdout.flush()
632 if stderr:
686 if stderr:
633 print('\033[2K\r', file=io.stderr, end='')
687 print('\033[2K\r', file=io.stderr, end='')
634 io.stderr.flush()
688 io.stderr.flush()
635
689
@@ -1,391 +1,385
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """Pylab (matplotlib) support utilities.
2 """Pylab (matplotlib) support utilities.
3
3
4 Authors
4 Authors
5 -------
5 -------
6
6
7 * Fernando Perez.
7 * Fernando Perez.
8 * Brian Granger
8 * Brian Granger
9 """
9 """
10
10
11 #-----------------------------------------------------------------------------
11 #-----------------------------------------------------------------------------
12 # Copyright (C) 2009-2011 The IPython Development Team
12 # Copyright (C) 2009 The IPython Development Team
13 #
13 #
14 # Distributed under the terms of the BSD License. The full license is in
14 # Distributed under the terms of the BSD License. The full license is in
15 # the file COPYING, distributed as part of this software.
15 # the file COPYING, distributed as part of this software.
16 #-----------------------------------------------------------------------------
16 #-----------------------------------------------------------------------------
17
17
18 #-----------------------------------------------------------------------------
18 #-----------------------------------------------------------------------------
19 # Imports
19 # Imports
20 #-----------------------------------------------------------------------------
20 #-----------------------------------------------------------------------------
21
21
22 import struct
23 import sys
22 import sys
24 from io import BytesIO
23 from io import BytesIO
25
24
25 from IPython.core.display import _pngxy
26 from IPython.utils.decorators import flag_calls
26 from IPython.utils.decorators import flag_calls
27
27
28 # If user specifies a GUI, that dictates the backend, otherwise we read the
28 # If user specifies a GUI, that dictates the backend, otherwise we read the
29 # user's mpl default from the mpl rc structure
29 # user's mpl default from the mpl rc structure
30 backends = {'tk': 'TkAgg',
30 backends = {'tk': 'TkAgg',
31 'gtk': 'GTKAgg',
31 'gtk': 'GTKAgg',
32 'wx': 'WXAgg',
32 'wx': 'WXAgg',
33 'qt': 'Qt4Agg', # qt3 not supported
33 'qt': 'Qt4Agg', # qt3 not supported
34 'qt4': 'Qt4Agg',
34 'qt4': 'Qt4Agg',
35 'osx': 'MacOSX',
35 'osx': 'MacOSX',
36 'inline' : 'module://IPython.kernel.zmq.pylab.backend_inline'}
36 'inline' : 'module://IPython.kernel.zmq.pylab.backend_inline'}
37
37
38 # We also need a reverse backends2guis mapping that will properly choose which
38 # We also need a reverse backends2guis mapping that will properly choose which
39 # GUI support to activate based on the desired matplotlib backend. For the
39 # GUI support to activate based on the desired matplotlib backend. For the
40 # most part it's just a reverse of the above dict, but we also need to add a
40 # most part it's just a reverse of the above dict, but we also need to add a
41 # few others that map to the same GUI manually:
41 # few others that map to the same GUI manually:
42 backend2gui = dict(zip(backends.values(), backends.keys()))
42 backend2gui = dict(zip(backends.values(), backends.keys()))
43 # In the reverse mapping, there are a few extra valid matplotlib backends that
43 # In the reverse mapping, there are a few extra valid matplotlib backends that
44 # map to the same GUI support
44 # map to the same GUI support
45 backend2gui['GTK'] = backend2gui['GTKCairo'] = 'gtk'
45 backend2gui['GTK'] = backend2gui['GTKCairo'] = 'gtk'
46 backend2gui['WX'] = 'wx'
46 backend2gui['WX'] = 'wx'
47 backend2gui['CocoaAgg'] = 'osx'
47 backend2gui['CocoaAgg'] = 'osx'
48
48
49 #-----------------------------------------------------------------------------
49 #-----------------------------------------------------------------------------
50 # Matplotlib utilities
50 # Matplotlib utilities
51 #-----------------------------------------------------------------------------
51 #-----------------------------------------------------------------------------
52
52
53
53
54 def getfigs(*fig_nums):
54 def getfigs(*fig_nums):
55 """Get a list of matplotlib figures by figure numbers.
55 """Get a list of matplotlib figures by figure numbers.
56
56
57 If no arguments are given, all available figures are returned. If the
57 If no arguments are given, all available figures are returned. If the
58 argument list contains references to invalid figures, a warning is printed
58 argument list contains references to invalid figures, a warning is printed
59 but the function continues pasting further figures.
59 but the function continues pasting further figures.
60
60
61 Parameters
61 Parameters
62 ----------
62 ----------
63 figs : tuple
63 figs : tuple
64 A tuple of ints giving the figure numbers of the figures to return.
64 A tuple of ints giving the figure numbers of the figures to return.
65 """
65 """
66 from matplotlib._pylab_helpers import Gcf
66 from matplotlib._pylab_helpers import Gcf
67 if not fig_nums:
67 if not fig_nums:
68 fig_managers = Gcf.get_all_fig_managers()
68 fig_managers = Gcf.get_all_fig_managers()
69 return [fm.canvas.figure for fm in fig_managers]
69 return [fm.canvas.figure for fm in fig_managers]
70 else:
70 else:
71 figs = []
71 figs = []
72 for num in fig_nums:
72 for num in fig_nums:
73 f = Gcf.figs.get(num)
73 f = Gcf.figs.get(num)
74 if f is None:
74 if f is None:
75 print('Warning: figure %s not available.' % num)
75 print('Warning: figure %s not available.' % num)
76 else:
76 else:
77 figs.append(f.canvas.figure)
77 figs.append(f.canvas.figure)
78 return figs
78 return figs
79
79
80
80
81 def figsize(sizex, sizey):
81 def figsize(sizex, sizey):
82 """Set the default figure size to be [sizex, sizey].
82 """Set the default figure size to be [sizex, sizey].
83
83
84 This is just an easy to remember, convenience wrapper that sets::
84 This is just an easy to remember, convenience wrapper that sets::
85
85
86 matplotlib.rcParams['figure.figsize'] = [sizex, sizey]
86 matplotlib.rcParams['figure.figsize'] = [sizex, sizey]
87 """
87 """
88 import matplotlib
88 import matplotlib
89 matplotlib.rcParams['figure.figsize'] = [sizex, sizey]
89 matplotlib.rcParams['figure.figsize'] = [sizex, sizey]
90
90
91
91
92 def print_figure(fig, fmt='png'):
92 def print_figure(fig, fmt='png'):
93 """Convert a figure to svg or png for inline display."""
93 """Convert a figure to svg or png for inline display."""
94 from matplotlib import rcParams
94 from matplotlib import rcParams
95 # When there's an empty figure, we shouldn't return anything, otherwise we
95 # When there's an empty figure, we shouldn't return anything, otherwise we
96 # get big blank areas in the qt console.
96 # get big blank areas in the qt console.
97 if not fig.axes and not fig.lines:
97 if not fig.axes and not fig.lines:
98 return
98 return
99
99
100 fc = fig.get_facecolor()
100 fc = fig.get_facecolor()
101 ec = fig.get_edgecolor()
101 ec = fig.get_edgecolor()
102 bytes_io = BytesIO()
102 bytes_io = BytesIO()
103 dpi = rcParams['savefig.dpi']
103 dpi = rcParams['savefig.dpi']
104 if fmt == 'retina':
104 if fmt == 'retina':
105 dpi = dpi * 2
105 dpi = dpi * 2
106 fmt = 'png'
106 fig.canvas.print_figure(bytes_io, format=fmt, bbox_inches='tight',
107 fig.canvas.print_figure(bytes_io, format=fmt, bbox_inches='tight',
107 facecolor=fc, edgecolor=ec, dpi=dpi)
108 facecolor=fc, edgecolor=ec, dpi=dpi)
108 data = bytes_io.getvalue()
109 data = bytes_io.getvalue()
109 return data
110 return data
110
111
111 def pngxy(data):
112 """read the width/height from a PNG header"""
113 ihdr = data.index(b'IHDR')
114 # next 8 bytes are width/height
115 w4h4 = data[ihdr+4:ihdr+12]
116 return struct.unpack('>ii', w4h4)
117
118 def retina_figure(fig):
112 def retina_figure(fig):
119 """format a figure as a pixel-doubled (retina) PNG"""
113 """format a figure as a pixel-doubled (retina) PNG"""
120 pngdata = print_figure(fig, fmt='retina')
114 pngdata = print_figure(fig, fmt='retina')
121 w, h = pngxy(pngdata)
115 w, h = _pngxy(pngdata)
122 metadata = dict(width=w//2, height=h//2)
116 metadata = dict(width=w//2, height=h//2)
123 return pngdata, metadata
117 return pngdata, metadata
124
118
125 # We need a little factory function here to create the closure where
119 # We need a little factory function here to create the closure where
126 # safe_execfile can live.
120 # safe_execfile can live.
127 def mpl_runner(safe_execfile):
121 def mpl_runner(safe_execfile):
128 """Factory to return a matplotlib-enabled runner for %run.
122 """Factory to return a matplotlib-enabled runner for %run.
129
123
130 Parameters
124 Parameters
131 ----------
125 ----------
132 safe_execfile : function
126 safe_execfile : function
133 This must be a function with the same interface as the
127 This must be a function with the same interface as the
134 :meth:`safe_execfile` method of IPython.
128 :meth:`safe_execfile` method of IPython.
135
129
136 Returns
130 Returns
137 -------
131 -------
138 A function suitable for use as the ``runner`` argument of the %run magic
132 A function suitable for use as the ``runner`` argument of the %run magic
139 function.
133 function.
140 """
134 """
141
135
142 def mpl_execfile(fname,*where,**kw):
136 def mpl_execfile(fname,*where,**kw):
143 """matplotlib-aware wrapper around safe_execfile.
137 """matplotlib-aware wrapper around safe_execfile.
144
138
145 Its interface is identical to that of the :func:`execfile` builtin.
139 Its interface is identical to that of the :func:`execfile` builtin.
146
140
147 This is ultimately a call to execfile(), but wrapped in safeties to
141 This is ultimately a call to execfile(), but wrapped in safeties to
148 properly handle interactive rendering."""
142 properly handle interactive rendering."""
149
143
150 import matplotlib
144 import matplotlib
151 import matplotlib.pylab as pylab
145 import matplotlib.pylab as pylab
152
146
153 #print '*** Matplotlib runner ***' # dbg
147 #print '*** Matplotlib runner ***' # dbg
154 # turn off rendering until end of script
148 # turn off rendering until end of script
155 is_interactive = matplotlib.rcParams['interactive']
149 is_interactive = matplotlib.rcParams['interactive']
156 matplotlib.interactive(False)
150 matplotlib.interactive(False)
157 safe_execfile(fname,*where,**kw)
151 safe_execfile(fname,*where,**kw)
158 matplotlib.interactive(is_interactive)
152 matplotlib.interactive(is_interactive)
159 # make rendering call now, if the user tried to do it
153 # make rendering call now, if the user tried to do it
160 if pylab.draw_if_interactive.called:
154 if pylab.draw_if_interactive.called:
161 pylab.draw()
155 pylab.draw()
162 pylab.draw_if_interactive.called = False
156 pylab.draw_if_interactive.called = False
163
157
164 return mpl_execfile
158 return mpl_execfile
165
159
166
160
167 def select_figure_format(shell, fmt):
161 def select_figure_format(shell, fmt):
168 """Select figure format for inline backend, can be 'png', 'retina', or 'svg'.
162 """Select figure format for inline backend, can be 'png', 'retina', or 'svg'.
169
163
170 Using this method ensures only one figure format is active at a time.
164 Using this method ensures only one figure format is active at a time.
171 """
165 """
172 from matplotlib.figure import Figure
166 from matplotlib.figure import Figure
173 from IPython.kernel.zmq.pylab import backend_inline
167 from IPython.kernel.zmq.pylab import backend_inline
174
168
175 svg_formatter = shell.display_formatter.formatters['image/svg+xml']
169 svg_formatter = shell.display_formatter.formatters['image/svg+xml']
176 png_formatter = shell.display_formatter.formatters['image/png']
170 png_formatter = shell.display_formatter.formatters['image/png']
177
171
178 if fmt == 'png':
172 if fmt == 'png':
179 svg_formatter.type_printers.pop(Figure, None)
173 svg_formatter.type_printers.pop(Figure, None)
180 png_formatter.for_type(Figure, lambda fig: print_figure(fig, 'png'))
174 png_formatter.for_type(Figure, lambda fig: print_figure(fig, 'png'))
181 elif fmt in ('png2x', 'retina'):
175 elif fmt in ('png2x', 'retina'):
182 svg_formatter.type_printers.pop(Figure, None)
176 svg_formatter.type_printers.pop(Figure, None)
183 png_formatter.for_type(Figure, retina_figure)
177 png_formatter.for_type(Figure, retina_figure)
184 elif fmt == 'svg':
178 elif fmt == 'svg':
185 png_formatter.type_printers.pop(Figure, None)
179 png_formatter.type_printers.pop(Figure, None)
186 svg_formatter.for_type(Figure, lambda fig: print_figure(fig, 'svg'))
180 svg_formatter.for_type(Figure, lambda fig: print_figure(fig, 'svg'))
187 else:
181 else:
188 raise ValueError("supported formats are: 'png', 'retina', 'svg', not %r" % fmt)
182 raise ValueError("supported formats are: 'png', 'retina', 'svg', not %r" % fmt)
189
183
190 # set the format to be used in the backend()
184 # set the format to be used in the backend()
191 backend_inline._figure_format = fmt
185 backend_inline._figure_format = fmt
192
186
193 #-----------------------------------------------------------------------------
187 #-----------------------------------------------------------------------------
194 # Code for initializing matplotlib and importing pylab
188 # Code for initializing matplotlib and importing pylab
195 #-----------------------------------------------------------------------------
189 #-----------------------------------------------------------------------------
196
190
197
191
198 def find_gui_and_backend(gui=None, gui_select=None):
192 def find_gui_and_backend(gui=None, gui_select=None):
199 """Given a gui string return the gui and mpl backend.
193 """Given a gui string return the gui and mpl backend.
200
194
201 Parameters
195 Parameters
202 ----------
196 ----------
203 gui : str
197 gui : str
204 Can be one of ('tk','gtk','wx','qt','qt4','inline').
198 Can be one of ('tk','gtk','wx','qt','qt4','inline').
205 gui_select : str
199 gui_select : str
206 Can be one of ('tk','gtk','wx','qt','qt4','inline').
200 Can be one of ('tk','gtk','wx','qt','qt4','inline').
207 This is any gui already selected by the shell.
201 This is any gui already selected by the shell.
208
202
209 Returns
203 Returns
210 -------
204 -------
211 A tuple of (gui, backend) where backend is one of ('TkAgg','GTKAgg',
205 A tuple of (gui, backend) where backend is one of ('TkAgg','GTKAgg',
212 'WXAgg','Qt4Agg','module://IPython.kernel.zmq.pylab.backend_inline').
206 'WXAgg','Qt4Agg','module://IPython.kernel.zmq.pylab.backend_inline').
213 """
207 """
214
208
215 import matplotlib
209 import matplotlib
216
210
217 if gui and gui != 'auto':
211 if gui and gui != 'auto':
218 # select backend based on requested gui
212 # select backend based on requested gui
219 backend = backends[gui]
213 backend = backends[gui]
220 else:
214 else:
221 backend = matplotlib.rcParams['backend']
215 backend = matplotlib.rcParams['backend']
222 # In this case, we need to find what the appropriate gui selection call
216 # In this case, we need to find what the appropriate gui selection call
223 # should be for IPython, so we can activate inputhook accordingly
217 # should be for IPython, so we can activate inputhook accordingly
224 gui = backend2gui.get(backend, None)
218 gui = backend2gui.get(backend, None)
225
219
226 # If we have already had a gui active, we need it and inline are the
220 # If we have already had a gui active, we need it and inline are the
227 # ones allowed.
221 # ones allowed.
228 if gui_select and gui != gui_select:
222 if gui_select and gui != gui_select:
229 gui = gui_select
223 gui = gui_select
230 backend = backends[gui]
224 backend = backends[gui]
231
225
232 return gui, backend
226 return gui, backend
233
227
234
228
235 def activate_matplotlib(backend):
229 def activate_matplotlib(backend):
236 """Activate the given backend and set interactive to True."""
230 """Activate the given backend and set interactive to True."""
237
231
238 import matplotlib
232 import matplotlib
239 matplotlib.interactive(True)
233 matplotlib.interactive(True)
240
234
241 # Matplotlib had a bug where even switch_backend could not force
235 # Matplotlib had a bug where even switch_backend could not force
242 # the rcParam to update. This needs to be set *before* the module
236 # the rcParam to update. This needs to be set *before* the module
243 # magic of switch_backend().
237 # magic of switch_backend().
244 matplotlib.rcParams['backend'] = backend
238 matplotlib.rcParams['backend'] = backend
245
239
246 import matplotlib.pyplot
240 import matplotlib.pyplot
247 matplotlib.pyplot.switch_backend(backend)
241 matplotlib.pyplot.switch_backend(backend)
248
242
249 # This must be imported last in the matplotlib series, after
243 # This must be imported last in the matplotlib series, after
250 # backend/interactivity choices have been made
244 # backend/interactivity choices have been made
251 import matplotlib.pylab as pylab
245 import matplotlib.pylab as pylab
252
246
253 pylab.show._needmain = False
247 pylab.show._needmain = False
254 # We need to detect at runtime whether show() is called by the user.
248 # We need to detect at runtime whether show() is called by the user.
255 # For this, we wrap it into a decorator which adds a 'called' flag.
249 # For this, we wrap it into a decorator which adds a 'called' flag.
256 pylab.draw_if_interactive = flag_calls(pylab.draw_if_interactive)
250 pylab.draw_if_interactive = flag_calls(pylab.draw_if_interactive)
257
251
258
252
259 def import_pylab(user_ns, import_all=True):
253 def import_pylab(user_ns, import_all=True):
260 """Import the standard pylab symbols into user_ns."""
254 """Import the standard pylab symbols into user_ns."""
261
255
262 # Import numpy as np/pyplot as plt are conventions we're trying to
256 # Import numpy as np/pyplot as plt are conventions we're trying to
263 # somewhat standardize on. Making them available to users by default
257 # somewhat standardize on. Making them available to users by default
264 # will greatly help this.
258 # will greatly help this.
265 s = ("import numpy\n"
259 s = ("import numpy\n"
266 "import matplotlib\n"
260 "import matplotlib\n"
267 "from matplotlib import pylab, mlab, pyplot\n"
261 "from matplotlib import pylab, mlab, pyplot\n"
268 "np = numpy\n"
262 "np = numpy\n"
269 "plt = pyplot\n"
263 "plt = pyplot\n"
270 )
264 )
271 exec s in user_ns
265 exec s in user_ns
272
266
273 if import_all:
267 if import_all:
274 s = ("from matplotlib.pylab import *\n"
268 s = ("from matplotlib.pylab import *\n"
275 "from numpy import *\n")
269 "from numpy import *\n")
276 exec s in user_ns
270 exec s in user_ns
277
271
278
272
279 def configure_inline_support(shell, backend, user_ns=None):
273 def configure_inline_support(shell, backend, user_ns=None):
280 """Configure an IPython shell object for matplotlib use.
274 """Configure an IPython shell object for matplotlib use.
281
275
282 Parameters
276 Parameters
283 ----------
277 ----------
284 shell : InteractiveShell instance
278 shell : InteractiveShell instance
285
279
286 backend : matplotlib backend
280 backend : matplotlib backend
287
281
288 user_ns : dict
282 user_ns : dict
289 A namespace where all configured variables will be placed. If not given,
283 A namespace where all configured variables will be placed. If not given,
290 the `user_ns` attribute of the shell object is used.
284 the `user_ns` attribute of the shell object is used.
291 """
285 """
292 # If using our svg payload backend, register the post-execution
286 # If using our svg payload backend, register the post-execution
293 # function that will pick up the results for display. This can only be
287 # function that will pick up the results for display. This can only be
294 # done with access to the real shell object.
288 # done with access to the real shell object.
295
289
296 # Note: if we can't load the inline backend, then there's no point
290 # Note: if we can't load the inline backend, then there's no point
297 # continuing (such as in terminal-only shells in environments without
291 # continuing (such as in terminal-only shells in environments without
298 # zeromq available).
292 # zeromq available).
299 try:
293 try:
300 from IPython.kernel.zmq.pylab.backend_inline import InlineBackend
294 from IPython.kernel.zmq.pylab.backend_inline import InlineBackend
301 except ImportError:
295 except ImportError:
302 return
296 return
303 from matplotlib import pyplot
297 from matplotlib import pyplot
304
298
305 user_ns = shell.user_ns if user_ns is None else user_ns
299 user_ns = shell.user_ns if user_ns is None else user_ns
306
300
307 cfg = InlineBackend.instance(config=shell.config)
301 cfg = InlineBackend.instance(config=shell.config)
308 cfg.shell = shell
302 cfg.shell = shell
309 if cfg not in shell.configurables:
303 if cfg not in shell.configurables:
310 shell.configurables.append(cfg)
304 shell.configurables.append(cfg)
311
305
312 if backend == backends['inline']:
306 if backend == backends['inline']:
313 from IPython.kernel.zmq.pylab.backend_inline import flush_figures
307 from IPython.kernel.zmq.pylab.backend_inline import flush_figures
314 shell.register_post_execute(flush_figures)
308 shell.register_post_execute(flush_figures)
315
309
316 # Save rcParams that will be overwrittern
310 # Save rcParams that will be overwrittern
317 shell._saved_rcParams = dict()
311 shell._saved_rcParams = dict()
318 for k in cfg.rc:
312 for k in cfg.rc:
319 shell._saved_rcParams[k] = pyplot.rcParams[k]
313 shell._saved_rcParams[k] = pyplot.rcParams[k]
320 # load inline_rc
314 # load inline_rc
321 pyplot.rcParams.update(cfg.rc)
315 pyplot.rcParams.update(cfg.rc)
322 # Add 'figsize' to pyplot and to the user's namespace
316 # Add 'figsize' to pyplot and to the user's namespace
323 user_ns['figsize'] = pyplot.figsize = figsize
317 user_ns['figsize'] = pyplot.figsize = figsize
324 else:
318 else:
325 from IPython.kernel.zmq.pylab.backend_inline import flush_figures
319 from IPython.kernel.zmq.pylab.backend_inline import flush_figures
326 if flush_figures in shell._post_execute:
320 if flush_figures in shell._post_execute:
327 shell._post_execute.pop(flush_figures)
321 shell._post_execute.pop(flush_figures)
328 if hasattr(shell, '_saved_rcParams'):
322 if hasattr(shell, '_saved_rcParams'):
329 pyplot.rcParams.update(shell._saved_rcParams)
323 pyplot.rcParams.update(shell._saved_rcParams)
330 del shell._saved_rcParams
324 del shell._saved_rcParams
331
325
332 # Setup the default figure format
326 # Setup the default figure format
333 fmt = cfg.figure_format
327 fmt = cfg.figure_format
334 select_figure_format(shell, fmt)
328 select_figure_format(shell, fmt)
335
329
336 # The old pastefig function has been replaced by display
330 # The old pastefig function has been replaced by display
337 from IPython.core.display import display
331 from IPython.core.display import display
338 # Add display and getfigs to the user's namespace
332 # Add display and getfigs to the user's namespace
339 user_ns['display'] = display
333 user_ns['display'] = display
340 user_ns['getfigs'] = getfigs
334 user_ns['getfigs'] = getfigs
341
335
342
336
343 def pylab_activate(user_ns, gui=None, import_all=True, shell=None, welcome_message=False):
337 def pylab_activate(user_ns, gui=None, import_all=True, shell=None, welcome_message=False):
344 """Activate pylab mode in the user's namespace.
338 """Activate pylab mode in the user's namespace.
345
339
346 Loads and initializes numpy, matplotlib and friends for interactive use.
340 Loads and initializes numpy, matplotlib and friends for interactive use.
347
341
348 Parameters
342 Parameters
349 ----------
343 ----------
350 user_ns : dict
344 user_ns : dict
351 Namespace where the imports will occur.
345 Namespace where the imports will occur.
352
346
353 gui : optional, string
347 gui : optional, string
354 A valid gui name following the conventions of the %gui magic.
348 A valid gui name following the conventions of the %gui magic.
355
349
356 import_all : optional, boolean
350 import_all : optional, boolean
357 If true, an 'import *' is done from numpy and pylab.
351 If true, an 'import *' is done from numpy and pylab.
358
352
359 welcome_message : optional, boolean
353 welcome_message : optional, boolean
360 If true, print a welcome message about pylab, which includes the backend
354 If true, print a welcome message about pylab, which includes the backend
361 being used.
355 being used.
362
356
363 Returns
357 Returns
364 -------
358 -------
365 The actual gui used (if not given as input, it was obtained from matplotlib
359 The actual gui used (if not given as input, it was obtained from matplotlib
366 itself, and will be needed next to configure IPython's gui integration.
360 itself, and will be needed next to configure IPython's gui integration.
367 """
361 """
368 pylab_gui_select = shell.pylab_gui_select if shell is not None else None
362 pylab_gui_select = shell.pylab_gui_select if shell is not None else None
369 # Try to find the appropriate gui and backend for the settings
363 # Try to find the appropriate gui and backend for the settings
370 gui, backend = find_gui_and_backend(gui, pylab_gui_select)
364 gui, backend = find_gui_and_backend(gui, pylab_gui_select)
371 if shell is not None and gui != 'inline':
365 if shell is not None and gui != 'inline':
372 # If we have our first gui selection, store it
366 # If we have our first gui selection, store it
373 if pylab_gui_select is None:
367 if pylab_gui_select is None:
374 shell.pylab_gui_select = gui
368 shell.pylab_gui_select = gui
375 # Otherwise if they are different
369 # Otherwise if they are different
376 elif gui != pylab_gui_select:
370 elif gui != pylab_gui_select:
377 print ('Warning: Cannot change to a different GUI toolkit: %s.'
371 print ('Warning: Cannot change to a different GUI toolkit: %s.'
378 ' Using %s instead.' % (gui, pylab_gui_select))
372 ' Using %s instead.' % (gui, pylab_gui_select))
379 gui, backend = find_gui_and_backend(pylab_gui_select)
373 gui, backend = find_gui_and_backend(pylab_gui_select)
380 activate_matplotlib(backend)
374 activate_matplotlib(backend)
381 import_pylab(user_ns, import_all)
375 import_pylab(user_ns, import_all)
382 if shell is not None:
376 if shell is not None:
383 configure_inline_support(shell, backend, user_ns)
377 configure_inline_support(shell, backend, user_ns)
384 if welcome_message:
378 if welcome_message:
385 print """
379 print """
386 Welcome to pylab, a matplotlib-based Python environment [backend: %s].
380 Welcome to pylab, a matplotlib-based Python environment [backend: %s].
387 For more information, type 'help(pylab)'.""" % backend
381 For more information, type 'help(pylab)'.""" % backend
388 # flush stdout, just to be safe
382 # flush stdout, just to be safe
389 sys.stdout.flush()
383 sys.stdout.flush()
390
384
391 return gui
385 return gui
General Comments 0
You need to be logged in to leave comments. Login now