##// END OF EJS Templates
Merge pull request #10818 from takluyver/img-format-elif...
Min RK -
r23945:345d5113 merge
parent child Browse files
Show More
@@ -1,1399 +1,1399
1 1 # -*- coding: utf-8 -*-
2 2 """Top-level display functions for displaying object in different formats."""
3 3
4 4 # Copyright (c) IPython Development Team.
5 5 # Distributed under the terms of the Modified BSD License.
6 6
7 7
8 8 from binascii import b2a_hex, b2a_base64, hexlify
9 9 import json
10 10 import mimetypes
11 11 import os
12 12 import struct
13 13 import sys
14 14 import warnings
15 15 from copy import deepcopy
16 16
17 17 from IPython.utils.py3compat import cast_unicode
18 18 from IPython.testing.skipdoctest import skip_doctest
19 19
20 20 __all__ = ['display', 'display_pretty', 'display_html', 'display_markdown',
21 21 'display_svg', 'display_png', 'display_jpeg', 'display_latex', 'display_json',
22 22 'display_javascript', 'display_pdf', 'DisplayObject', 'TextDisplayObject',
23 23 'Pretty', 'HTML', 'Markdown', 'Math', 'Latex', 'SVG', 'ProgressBar', 'JSON',
24 24 'GeoJSON', 'Javascript', 'Image', 'clear_output', 'set_matplotlib_formats',
25 25 'set_matplotlib_close', 'publish_display_data', 'update_display', 'DisplayHandle',
26 26 'Video']
27 27
28 28 #-----------------------------------------------------------------------------
29 29 # utility functions
30 30 #-----------------------------------------------------------------------------
31 31
32 32 def _safe_exists(path):
33 33 """Check path, but don't let exceptions raise"""
34 34 try:
35 35 return os.path.exists(path)
36 36 except Exception:
37 37 return False
38 38
39 39 def _merge(d1, d2):
40 40 """Like update, but merges sub-dicts instead of clobbering at the top level.
41 41
42 42 Updates d1 in-place
43 43 """
44 44
45 45 if not isinstance(d2, dict) or not isinstance(d1, dict):
46 46 return d2
47 47 for key, value in d2.items():
48 48 d1[key] = _merge(d1.get(key), value)
49 49 return d1
50 50
51 51 def _display_mimetype(mimetype, objs, raw=False, metadata=None):
52 52 """internal implementation of all display_foo methods
53 53
54 54 Parameters
55 55 ----------
56 56 mimetype : str
57 57 The mimetype to be published (e.g. 'image/png')
58 58 objs : tuple of objects
59 59 The Python objects to display, or if raw=True raw text data to
60 60 display.
61 61 raw : bool
62 62 Are the data objects raw data or Python objects that need to be
63 63 formatted before display? [default: False]
64 64 metadata : dict (optional)
65 65 Metadata to be associated with the specific mimetype output.
66 66 """
67 67 if metadata:
68 68 metadata = {mimetype: metadata}
69 69 if raw:
70 70 # turn list of pngdata into list of { 'image/png': pngdata }
71 71 objs = [ {mimetype: obj} for obj in objs ]
72 72 display(*objs, raw=raw, metadata=metadata, include=[mimetype])
73 73
74 74 #-----------------------------------------------------------------------------
75 75 # Main functions
76 76 #-----------------------------------------------------------------------------
77 77
78 78 # use * to indicate transient is keyword-only
79 79 def publish_display_data(data, metadata=None, source=None, *, transient=None, **kwargs):
80 80 """Publish data and metadata to all frontends.
81 81
82 82 See the ``display_data`` message in the messaging documentation for
83 83 more details about this message type.
84 84
85 85 Keys of data and metadata can be any mime-type.
86 86
87 87 Parameters
88 88 ----------
89 89 data : dict
90 90 A dictionary having keys that are valid MIME types (like
91 91 'text/plain' or 'image/svg+xml') and values that are the data for
92 92 that MIME type. The data itself must be a JSON'able data
93 93 structure. Minimally all data should have the 'text/plain' data,
94 94 which can be displayed by all frontends. If more than the plain
95 95 text is given, it is up to the frontend to decide which
96 96 representation to use.
97 97 metadata : dict
98 98 A dictionary for metadata related to the data. This can contain
99 99 arbitrary key, value pairs that frontends can use to interpret
100 100 the data. mime-type keys matching those in data can be used
101 101 to specify metadata about particular representations.
102 102 source : str, deprecated
103 103 Unused.
104 104 transient : dict, keyword-only
105 105 A dictionary of transient data, such as display_id.
106 106 """
107 107 from IPython.core.interactiveshell import InteractiveShell
108 108
109 109 display_pub = InteractiveShell.instance().display_pub
110 110
111 111 # only pass transient if supplied,
112 112 # to avoid errors with older ipykernel.
113 113 # TODO: We could check for ipykernel version and provide a detailed upgrade message.
114 114 if transient:
115 115 kwargs['transient'] = transient
116 116
117 117 display_pub.publish(
118 118 data=data,
119 119 metadata=metadata,
120 120 **kwargs
121 121 )
122 122
123 123
124 124 def _new_id():
125 125 """Generate a new random text id with urandom"""
126 126 return b2a_hex(os.urandom(16)).decode('ascii')
127 127
128 128
129 129 def display(*objs, include=None, exclude=None, metadata=None, transient=None, display_id=None, **kwargs):
130 130 """Display a Python object in all frontends.
131 131
132 132 By default all representations will be computed and sent to the frontends.
133 133 Frontends can decide which representation is used and how.
134 134
135 135 In terminal IPython this will be similar to using :func:`print`, for use in richer
136 136 frontends see Jupyter notebook examples with rich display logic.
137 137
138 138 Parameters
139 139 ----------
140 140 objs : tuple of objects
141 141 The Python objects to display.
142 142 raw : bool, optional
143 143 Are the objects to be displayed already mimetype-keyed dicts of raw display data,
144 144 or Python objects that need to be formatted before display? [default: False]
145 145 include : list, tuple or set, optional
146 146 A list of format type strings (MIME types) to include in the
147 147 format data dict. If this is set *only* the format types included
148 148 in this list will be computed.
149 149 exclude : list, tuple or set, optional
150 150 A list of format type strings (MIME types) to exclude in the format
151 151 data dict. If this is set all format types will be computed,
152 152 except for those included in this argument.
153 153 metadata : dict, optional
154 154 A dictionary of metadata to associate with the output.
155 155 mime-type keys in this dictionary will be associated with the individual
156 156 representation formats, if they exist.
157 157 transient : dict, optional
158 158 A dictionary of transient data to associate with the output.
159 159 Data in this dict should not be persisted to files (e.g. notebooks).
160 160 display_id : str, bool optional
161 161 Set an id for the display.
162 162 This id can be used for updating this display area later via update_display.
163 163 If given as `True`, generate a new `display_id`
164 164 kwargs: additional keyword-args, optional
165 165 Additional keyword-arguments are passed through to the display publisher.
166 166
167 167 Returns
168 168 -------
169 169
170 170 handle: DisplayHandle
171 171 Returns a handle on updatable displays for use with :func:`update_display`,
172 172 if `display_id` is given. Returns :any:`None` if no `display_id` is given
173 173 (default).
174 174
175 175 Examples
176 176 --------
177 177
178 178 >>> class Json(object):
179 179 ... def __init__(self, json):
180 180 ... self.json = json
181 181 ... def _repr_pretty_(self, pp, cycle):
182 182 ... import json
183 183 ... pp.text(json.dumps(self.json, indent=2))
184 184 ... def __repr__(self):
185 185 ... return str(self.json)
186 186 ...
187 187
188 188 >>> d = Json({1:2, 3: {4:5}})
189 189
190 190 >>> print(d)
191 191 {1: 2, 3: {4: 5}}
192 192
193 193 >>> display(d)
194 194 {
195 195 "1": 2,
196 196 "3": {
197 197 "4": 5
198 198 }
199 199 }
200 200
201 201 >>> def int_formatter(integer, pp, cycle):
202 202 ... pp.text('I'*integer)
203 203
204 204 >>> plain = get_ipython().display_formatter.formatters['text/plain']
205 205 >>> plain.for_type(int, int_formatter)
206 206 <function _repr_pprint at 0x...>
207 207 >>> display(7-5)
208 208 II
209 209
210 210 >>> del plain.type_printers[int]
211 211 >>> display(7-5)
212 212 2
213 213
214 214 See Also
215 215 --------
216 216
217 217 :func:`update_display`
218 218
219 219 Notes
220 220 -----
221 221
222 222 In Python, objects can declare their textual representation using the
223 223 `__repr__` method. IPython expands on this idea and allows objects to declare
224 224 other, rich representations including:
225 225
226 226 - HTML
227 227 - JSON
228 228 - PNG
229 229 - JPEG
230 230 - SVG
231 231 - LaTeX
232 232
233 233 A single object can declare some or all of these representations; all are
234 234 handled by IPython's display system.
235 235
236 236 The main idea of the first approach is that you have to implement special
237 237 display methods when you define your class, one for each representation you
238 238 want to use. Here is a list of the names of the special methods and the
239 239 values they must return:
240 240
241 241 - `_repr_html_`: return raw HTML as a string
242 242 - `_repr_json_`: return a JSONable dict
243 243 - `_repr_jpeg_`: return raw JPEG data
244 244 - `_repr_png_`: return raw PNG data
245 245 - `_repr_svg_`: return raw SVG data as a string
246 246 - `_repr_latex_`: return LaTeX commands in a string surrounded by "$".
247 247 - `_repr_mimebundle_`: return a full mimebundle containing the mapping
248 248 from all mimetypes to data.
249 249 Use this for any mime-type not listed above.
250 250
251 251 When you are directly writing your own classes, you can adapt them for
252 252 display in IPython by following the above approach. But in practice, you
253 253 often need to work with existing classes that you can't easily modify.
254 254
255 255 You can refer to the documentation on IPython display formatters in order to
256 256 register custom formatters for already existing types.
257 257
258 258 .. versionadded:: 5.4 display available without import
259 259 .. versionadded:: 6.1 display available without import
260 260
261 261 Since IPython 5.4 and 6.1 :func:`display` is automatically made available to
262 262 the user without import. If you are using display in a document that might
263 263 be used in a pure python context or with older version of IPython, use the
264 264 following import at the top of your file::
265 265
266 266 from IPython.display import display
267 267
268 268 """
269 269 from IPython.core.interactiveshell import InteractiveShell
270 270
271 271 if not InteractiveShell.initialized():
272 272 # Directly print objects.
273 273 print(*objs)
274 274 return
275 275
276 276 raw = kwargs.pop('raw', False)
277 277 if transient is None:
278 278 transient = {}
279 279 if metadata is None:
280 280 metadata={}
281 281 if display_id:
282 282 if display_id is True:
283 283 display_id = _new_id()
284 284 transient['display_id'] = display_id
285 285 if kwargs.get('update') and 'display_id' not in transient:
286 286 raise TypeError('display_id required for update_display')
287 287 if transient:
288 288 kwargs['transient'] = transient
289 289
290 290 if not raw:
291 291 format = InteractiveShell.instance().display_formatter.format
292 292
293 293 for obj in objs:
294 294 if raw:
295 295 publish_display_data(data=obj, metadata=metadata, **kwargs)
296 296 else:
297 297 format_dict, md_dict = format(obj, include=include, exclude=exclude)
298 298 if not format_dict:
299 299 # nothing to display (e.g. _ipython_display_ took over)
300 300 continue
301 301 if metadata:
302 302 # kwarg-specified metadata gets precedence
303 303 _merge(md_dict, metadata)
304 304 publish_display_data(data=format_dict, metadata=md_dict, **kwargs)
305 305 if display_id:
306 306 return DisplayHandle(display_id)
307 307
308 308
309 309 # use * for keyword-only display_id arg
310 310 def update_display(obj, *, display_id, **kwargs):
311 311 """Update an existing display by id
312 312
313 313 Parameters
314 314 ----------
315 315
316 316 obj:
317 317 The object with which to update the display
318 318 display_id: keyword-only
319 319 The id of the display to update
320 320
321 321 See Also
322 322 --------
323 323
324 324 :func:`display`
325 325 """
326 326 kwargs['update'] = True
327 327 display(obj, display_id=display_id, **kwargs)
328 328
329 329
330 330 class DisplayHandle(object):
331 331 """A handle on an updatable display
332 332
333 333 Call `.update(obj)` to display a new object.
334 334
335 335 Call `.display(obj`) to add a new instance of this display,
336 336 and update existing instances.
337 337
338 338 See Also
339 339 --------
340 340
341 341 :func:`display`, :func:`update_display`
342 342
343 343 """
344 344
345 345 def __init__(self, display_id=None):
346 346 if display_id is None:
347 347 display_id = _new_id()
348 348 self.display_id = display_id
349 349
350 350 def __repr__(self):
351 351 return "<%s display_id=%s>" % (self.__class__.__name__, self.display_id)
352 352
353 353 def display(self, obj, **kwargs):
354 354 """Make a new display with my id, updating existing instances.
355 355
356 356 Parameters
357 357 ----------
358 358
359 359 obj:
360 360 object to display
361 361 **kwargs:
362 362 additional keyword arguments passed to display
363 363 """
364 364 display(obj, display_id=self.display_id, **kwargs)
365 365
366 366 def update(self, obj, **kwargs):
367 367 """Update existing displays with my id
368 368
369 369 Parameters
370 370 ----------
371 371
372 372 obj:
373 373 object to display
374 374 **kwargs:
375 375 additional keyword arguments passed to update_display
376 376 """
377 377 update_display(obj, display_id=self.display_id, **kwargs)
378 378
379 379
380 380 def display_pretty(*objs, **kwargs):
381 381 """Display the pretty (default) representation of an object.
382 382
383 383 Parameters
384 384 ----------
385 385 objs : tuple of objects
386 386 The Python objects to display, or if raw=True raw text data to
387 387 display.
388 388 raw : bool
389 389 Are the data objects raw data or Python objects that need to be
390 390 formatted before display? [default: False]
391 391 metadata : dict (optional)
392 392 Metadata to be associated with the specific mimetype output.
393 393 """
394 394 _display_mimetype('text/plain', objs, **kwargs)
395 395
396 396
397 397 def display_html(*objs, **kwargs):
398 398 """Display the HTML representation of an object.
399 399
400 400 Note: If raw=False and the object does not have a HTML
401 401 representation, no HTML will be shown.
402 402
403 403 Parameters
404 404 ----------
405 405 objs : tuple of objects
406 406 The Python objects to display, or if raw=True raw HTML data to
407 407 display.
408 408 raw : bool
409 409 Are the data objects raw data or Python objects that need to be
410 410 formatted before display? [default: False]
411 411 metadata : dict (optional)
412 412 Metadata to be associated with the specific mimetype output.
413 413 """
414 414 _display_mimetype('text/html', objs, **kwargs)
415 415
416 416
417 417 def display_markdown(*objs, **kwargs):
418 418 """Displays the Markdown representation of an object.
419 419
420 420 Parameters
421 421 ----------
422 422 objs : tuple of objects
423 423 The Python objects to display, or if raw=True raw markdown data to
424 424 display.
425 425 raw : bool
426 426 Are the data objects raw data or Python objects that need to be
427 427 formatted before display? [default: False]
428 428 metadata : dict (optional)
429 429 Metadata to be associated with the specific mimetype output.
430 430 """
431 431
432 432 _display_mimetype('text/markdown', objs, **kwargs)
433 433
434 434
435 435 def display_svg(*objs, **kwargs):
436 436 """Display the SVG representation of an object.
437 437
438 438 Parameters
439 439 ----------
440 440 objs : tuple of objects
441 441 The Python objects to display, or if raw=True raw svg data to
442 442 display.
443 443 raw : bool
444 444 Are the data objects raw data or Python objects that need to be
445 445 formatted before display? [default: False]
446 446 metadata : dict (optional)
447 447 Metadata to be associated with the specific mimetype output.
448 448 """
449 449 _display_mimetype('image/svg+xml', objs, **kwargs)
450 450
451 451
452 452 def display_png(*objs, **kwargs):
453 453 """Display the PNG representation of an object.
454 454
455 455 Parameters
456 456 ----------
457 457 objs : tuple of objects
458 458 The Python objects to display, or if raw=True raw png data to
459 459 display.
460 460 raw : bool
461 461 Are the data objects raw data or Python objects that need to be
462 462 formatted before display? [default: False]
463 463 metadata : dict (optional)
464 464 Metadata to be associated with the specific mimetype output.
465 465 """
466 466 _display_mimetype('image/png', objs, **kwargs)
467 467
468 468
469 469 def display_jpeg(*objs, **kwargs):
470 470 """Display the JPEG representation of an object.
471 471
472 472 Parameters
473 473 ----------
474 474 objs : tuple of objects
475 475 The Python objects to display, or if raw=True raw JPEG data to
476 476 display.
477 477 raw : bool
478 478 Are the data objects raw data or Python objects that need to be
479 479 formatted before display? [default: False]
480 480 metadata : dict (optional)
481 481 Metadata to be associated with the specific mimetype output.
482 482 """
483 483 _display_mimetype('image/jpeg', objs, **kwargs)
484 484
485 485
486 486 def display_latex(*objs, **kwargs):
487 487 """Display the LaTeX representation of an object.
488 488
489 489 Parameters
490 490 ----------
491 491 objs : tuple of objects
492 492 The Python objects to display, or if raw=True raw latex data to
493 493 display.
494 494 raw : bool
495 495 Are the data objects raw data or Python objects that need to be
496 496 formatted before display? [default: False]
497 497 metadata : dict (optional)
498 498 Metadata to be associated with the specific mimetype output.
499 499 """
500 500 _display_mimetype('text/latex', objs, **kwargs)
501 501
502 502
503 503 def display_json(*objs, **kwargs):
504 504 """Display the JSON representation of an object.
505 505
506 506 Note that not many frontends support displaying JSON.
507 507
508 508 Parameters
509 509 ----------
510 510 objs : tuple of objects
511 511 The Python objects to display, or if raw=True raw json data to
512 512 display.
513 513 raw : bool
514 514 Are the data objects raw data or Python objects that need to be
515 515 formatted before display? [default: False]
516 516 metadata : dict (optional)
517 517 Metadata to be associated with the specific mimetype output.
518 518 """
519 519 _display_mimetype('application/json', objs, **kwargs)
520 520
521 521
522 522 def display_javascript(*objs, **kwargs):
523 523 """Display the Javascript representation of an object.
524 524
525 525 Parameters
526 526 ----------
527 527 objs : tuple of objects
528 528 The Python objects to display, or if raw=True raw javascript data to
529 529 display.
530 530 raw : bool
531 531 Are the data objects raw data or Python objects that need to be
532 532 formatted before display? [default: False]
533 533 metadata : dict (optional)
534 534 Metadata to be associated with the specific mimetype output.
535 535 """
536 536 _display_mimetype('application/javascript', objs, **kwargs)
537 537
538 538
539 539 def display_pdf(*objs, **kwargs):
540 540 """Display the PDF representation of an object.
541 541
542 542 Parameters
543 543 ----------
544 544 objs : tuple of objects
545 545 The Python objects to display, or if raw=True raw javascript data to
546 546 display.
547 547 raw : bool
548 548 Are the data objects raw data or Python objects that need to be
549 549 formatted before display? [default: False]
550 550 metadata : dict (optional)
551 551 Metadata to be associated with the specific mimetype output.
552 552 """
553 553 _display_mimetype('application/pdf', objs, **kwargs)
554 554
555 555
556 556 #-----------------------------------------------------------------------------
557 557 # Smart classes
558 558 #-----------------------------------------------------------------------------
559 559
560 560
561 561 class DisplayObject(object):
562 562 """An object that wraps data to be displayed."""
563 563
564 564 _read_flags = 'r'
565 565 _show_mem_addr = False
566 566 metadata = None
567 567
568 568 def __init__(self, data=None, url=None, filename=None, metadata=None):
569 569 """Create a display object given raw data.
570 570
571 571 When this object is returned by an expression or passed to the
572 572 display function, it will result in the data being displayed
573 573 in the frontend. The MIME type of the data should match the
574 574 subclasses used, so the Png subclass should be used for 'image/png'
575 575 data. If the data is a URL, the data will first be downloaded
576 576 and then displayed. If
577 577
578 578 Parameters
579 579 ----------
580 580 data : unicode, str or bytes
581 581 The raw data or a URL or file to load the data from
582 582 url : unicode
583 583 A URL to download the data from.
584 584 filename : unicode
585 585 Path to a local file to load the data from.
586 586 metadata : dict
587 587 Dict of metadata associated to be the object when displayed
588 588 """
589 589 if data is not None and isinstance(data, str):
590 590 if data.startswith('http') and url is None:
591 591 url = data
592 592 filename = None
593 593 data = None
594 594 elif _safe_exists(data) and filename is None:
595 595 url = None
596 596 filename = data
597 597 data = None
598 598
599 599 self.data = data
600 600 self.url = url
601 601 self.filename = filename
602 602
603 603 if metadata is not None:
604 604 self.metadata = metadata
605 605 elif self.metadata is None:
606 606 self.metadata = {}
607 607
608 608 self.reload()
609 609 self._check_data()
610 610
611 611 def __repr__(self):
612 612 if not self._show_mem_addr:
613 613 cls = self.__class__
614 614 r = "<%s.%s object>" % (cls.__module__, cls.__name__)
615 615 else:
616 616 r = super(DisplayObject, self).__repr__()
617 617 return r
618 618
619 619 def _check_data(self):
620 620 """Override in subclasses if there's something to check."""
621 621 pass
622 622
623 623 def _data_and_metadata(self):
624 624 """shortcut for returning metadata with shape information, if defined"""
625 625 if self.metadata:
626 626 return self.data, deepcopy(self.metadata)
627 627 else:
628 628 return self.data
629 629
630 630 def reload(self):
631 631 """Reload the raw data from file or URL."""
632 632 if self.filename is not None:
633 633 with open(self.filename, self._read_flags) as f:
634 634 self.data = f.read()
635 635 elif self.url is not None:
636 636 try:
637 637 # Deferred import
638 638 from urllib.request import urlopen
639 639 response = urlopen(self.url)
640 640 self.data = response.read()
641 641 # extract encoding from header, if there is one:
642 642 encoding = None
643 643 for sub in response.headers['content-type'].split(';'):
644 644 sub = sub.strip()
645 645 if sub.startswith('charset'):
646 646 encoding = sub.split('=')[-1].strip()
647 647 break
648 648 # decode data, if an encoding was specified
649 649 if encoding:
650 650 self.data = self.data.decode(encoding, 'replace')
651 651 except:
652 652 self.data = None
653 653
654 654 class TextDisplayObject(DisplayObject):
655 655 """Validate that display data is text"""
656 656 def _check_data(self):
657 657 if self.data is not None and not isinstance(self.data, str):
658 658 raise TypeError("%s expects text, not %r" % (self.__class__.__name__, self.data))
659 659
660 660 class Pretty(TextDisplayObject):
661 661
662 662 def _repr_pretty_(self, pp, cycle):
663 663 return pp.text(self.data)
664 664
665 665
666 666 class HTML(TextDisplayObject):
667 667
668 668 def _repr_html_(self):
669 669 return self.data
670 670
671 671 def __html__(self):
672 672 """
673 673 This method exists to inform other HTML-using modules (e.g. Markupsafe,
674 674 htmltag, etc) that this object is HTML and does not need things like
675 675 special characters (<>&) escaped.
676 676 """
677 677 return self._repr_html_()
678 678
679 679
680 680 class Markdown(TextDisplayObject):
681 681
682 682 def _repr_markdown_(self):
683 683 return self.data
684 684
685 685
686 686 class Math(TextDisplayObject):
687 687
688 688 def _repr_latex_(self):
689 689 s = self.data.strip('$')
690 690 return "$$%s$$" % s
691 691
692 692
693 693 class Latex(TextDisplayObject):
694 694
695 695 def _repr_latex_(self):
696 696 return self.data
697 697
698 698
699 699 class SVG(DisplayObject):
700 700
701 701 _read_flags = 'rb'
702 702 # wrap data in a property, which extracts the <svg> tag, discarding
703 703 # document headers
704 704 _data = None
705 705
706 706 @property
707 707 def data(self):
708 708 return self._data
709 709
710 710 @data.setter
711 711 def data(self, svg):
712 712 if svg is None:
713 713 self._data = None
714 714 return
715 715 # parse into dom object
716 716 from xml.dom import minidom
717 717 x = minidom.parseString(svg)
718 718 # get svg tag (should be 1)
719 719 found_svg = x.getElementsByTagName('svg')
720 720 if found_svg:
721 721 svg = found_svg[0].toxml()
722 722 else:
723 723 # fallback on the input, trust the user
724 724 # but this is probably an error.
725 725 pass
726 726 svg = cast_unicode(svg)
727 727 self._data = svg
728 728
729 729 def _repr_svg_(self):
730 730 return self._data_and_metadata()
731 731
732 732 class ProgressBar(DisplayObject):
733 733 """Progressbar supports displaying a progressbar like element
734 734 """
735 735 def __init__(self, total):
736 736 """Creates a new progressbar
737 737
738 738 Parameters
739 739 ----------
740 740 total : int
741 741 maximum size of the progressbar
742 742 """
743 743 self.total = total
744 744 self._progress = 0
745 745 self.html_width = '60ex'
746 746 self.text_width = 60
747 747 self._display_id = hexlify(os.urandom(8)).decode('ascii')
748 748
749 749 def __repr__(self):
750 750 fraction = self.progress / self.total
751 751 filled = '=' * int(fraction * self.text_width)
752 752 rest = ' ' * (self.text_width - len(filled))
753 753 return '[{}{}] {}/{}'.format(
754 754 filled, rest,
755 755 self.progress, self.total,
756 756 )
757 757
758 758 def _repr_html_(self):
759 759 return "<progress style='width:{}' max='{}' value='{}'></progress>".format(
760 760 self.html_width, self.total, self.progress)
761 761
762 762 def display(self):
763 763 display(self, display_id=self._display_id)
764 764
765 765 def update(self):
766 766 display(self, display_id=self._display_id, update=True)
767 767
768 768 @property
769 769 def progress(self):
770 770 return self._progress
771 771
772 772 @progress.setter
773 773 def progress(self, value):
774 774 self._progress = value
775 775 self.update()
776 776
777 777 class JSON(DisplayObject):
778 778 """JSON expects a JSON-able dict or list
779 779
780 780 not an already-serialized JSON string.
781 781
782 782 Scalar types (None, number, string) are not allowed, only dict or list containers.
783 783 """
784 784 # wrap data in a property, which warns about passing already-serialized JSON
785 785 _data = None
786 786 def __init__(self, data=None, url=None, filename=None, expanded=False, metadata=None, **kwargs):
787 787 """Create a JSON display object given raw data.
788 788
789 789 Parameters
790 790 ----------
791 791 data : dict or list
792 792 JSON data to display. Not an already-serialized JSON string.
793 793 Scalar types (None, number, string) are not allowed, only dict
794 794 or list containers.
795 795 url : unicode
796 796 A URL to download the data from.
797 797 filename : unicode
798 798 Path to a local file to load the data from.
799 799 expanded : boolean
800 800 Metadata to control whether a JSON display component is expanded.
801 801 metadata: dict
802 802 Specify extra metadata to attach to the json display object.
803 803 """
804 804 self.metadata = {'expanded': expanded}
805 805 if metadata:
806 806 self.metadata.update(metadata)
807 807 if kwargs:
808 808 self.metadata.update(kwargs)
809 809 super(JSON, self).__init__(data=data, url=url, filename=filename)
810 810
811 811 def _check_data(self):
812 812 if self.data is not None and not isinstance(self.data, (dict, list)):
813 813 raise TypeError("%s expects JSONable dict or list, not %r" % (self.__class__.__name__, self.data))
814 814
815 815 @property
816 816 def data(self):
817 817 return self._data
818 818
819 819 @data.setter
820 820 def data(self, data):
821 821 if isinstance(data, str):
822 822 if getattr(self, 'filename', None) is None:
823 823 warnings.warn("JSON expects JSONable dict or list, not JSON strings")
824 824 data = json.loads(data)
825 825 self._data = data
826 826
827 827 def _data_and_metadata(self):
828 828 return self.data, self.metadata
829 829
830 830 def _repr_json_(self):
831 831 return self._data_and_metadata()
832 832
833 833 _css_t = """$("head").append($("<link/>").attr({
834 834 rel: "stylesheet",
835 835 type: "text/css",
836 836 href: "%s"
837 837 }));
838 838 """
839 839
840 840 _lib_t1 = """$.getScript("%s", function () {
841 841 """
842 842 _lib_t2 = """});
843 843 """
844 844
845 845 class GeoJSON(JSON):
846 846 """GeoJSON expects JSON-able dict
847 847
848 848 not an already-serialized JSON string.
849 849
850 850 Scalar types (None, number, string) are not allowed, only dict containers.
851 851 """
852 852
853 853 def __init__(self, *args, **kwargs):
854 854 """Create a GeoJSON display object given raw data.
855 855
856 856 Parameters
857 857 ----------
858 858 data : dict or list
859 859 VegaLite data. Not an already-serialized JSON string.
860 860 Scalar types (None, number, string) are not allowed, only dict
861 861 or list containers.
862 862 url_template : string
863 863 Leaflet TileLayer URL template: http://leafletjs.com/reference.html#url-template
864 864 layer_options : dict
865 865 Leaflet TileLayer options: http://leafletjs.com/reference.html#tilelayer-options
866 866 url : unicode
867 867 A URL to download the data from.
868 868 filename : unicode
869 869 Path to a local file to load the data from.
870 870 metadata: dict
871 871 Specify extra metadata to attach to the json display object.
872 872
873 873 Examples
874 874 --------
875 875
876 876 The following will display an interactive map of Mars with a point of
877 877 interest on frontend that do support GeoJSON display.
878 878
879 879 >>> from IPython.display import GeoJSON
880 880
881 881 >>> GeoJSON(data={
882 882 ... "type": "Feature",
883 883 ... "geometry": {
884 884 ... "type": "Point",
885 885 ... "coordinates": [-81.327, 296.038]
886 886 ... }
887 887 ... },
888 888 ... url_template="http://s3-eu-west-1.amazonaws.com/whereonmars.cartodb.net/{basemap_id}/{z}/{x}/{y}.png",
889 889 ... layer_options={
890 890 ... "basemap_id": "celestia_mars-shaded-16k_global",
891 891 ... "attribution" : "Celestia/praesepe",
892 892 ... "minZoom" : 0,
893 893 ... "maxZoom" : 18,
894 894 ... })
895 895 <IPython.core.display.GeoJSON object>
896 896
897 897 In the terminal IPython, you will only see the text representation of
898 898 the GeoJSON object.
899 899
900 900 """
901 901
902 902 super(GeoJSON, self).__init__(*args, **kwargs)
903 903
904 904
905 905 def _ipython_display_(self):
906 906 bundle = {
907 907 'application/geo+json': self.data,
908 908 'text/plain': '<IPython.display.GeoJSON object>'
909 909 }
910 910 metadata = {
911 911 'application/geo+json': self.metadata
912 912 }
913 913 display(bundle, metadata=metadata, raw=True)
914 914
915 915 class Javascript(TextDisplayObject):
916 916
917 917 def __init__(self, data=None, url=None, filename=None, lib=None, css=None):
918 918 """Create a Javascript display object given raw data.
919 919
920 920 When this object is returned by an expression or passed to the
921 921 display function, it will result in the data being displayed
922 922 in the frontend. If the data is a URL, the data will first be
923 923 downloaded and then displayed.
924 924
925 925 In the Notebook, the containing element will be available as `element`,
926 926 and jQuery will be available. Content appended to `element` will be
927 927 visible in the output area.
928 928
929 929 Parameters
930 930 ----------
931 931 data : unicode, str or bytes
932 932 The Javascript source code or a URL to download it from.
933 933 url : unicode
934 934 A URL to download the data from.
935 935 filename : unicode
936 936 Path to a local file to load the data from.
937 937 lib : list or str
938 938 A sequence of Javascript library URLs to load asynchronously before
939 939 running the source code. The full URLs of the libraries should
940 940 be given. A single Javascript library URL can also be given as a
941 941 string.
942 942 css: : list or str
943 943 A sequence of css files to load before running the source code.
944 944 The full URLs of the css files should be given. A single css URL
945 945 can also be given as a string.
946 946 """
947 947 if isinstance(lib, str):
948 948 lib = [lib]
949 949 elif lib is None:
950 950 lib = []
951 951 if isinstance(css, str):
952 952 css = [css]
953 953 elif css is None:
954 954 css = []
955 955 if not isinstance(lib, (list,tuple)):
956 956 raise TypeError('expected sequence, got: %r' % lib)
957 957 if not isinstance(css, (list,tuple)):
958 958 raise TypeError('expected sequence, got: %r' % css)
959 959 self.lib = lib
960 960 self.css = css
961 961 super(Javascript, self).__init__(data=data, url=url, filename=filename)
962 962
963 963 def _repr_javascript_(self):
964 964 r = ''
965 965 for c in self.css:
966 966 r += _css_t % c
967 967 for l in self.lib:
968 968 r += _lib_t1 % l
969 969 r += self.data
970 970 r += _lib_t2*len(self.lib)
971 971 return r
972 972
973 973 # constants for identifying png/jpeg data
974 974 _PNG = b'\x89PNG\r\n\x1a\n'
975 975 _JPEG = b'\xff\xd8'
976 976
977 977 def _pngxy(data):
978 978 """read the (width, height) from a PNG header"""
979 979 ihdr = data.index(b'IHDR')
980 980 # next 8 bytes are width/height
981 981 return struct.unpack('>ii', data[ihdr+4:ihdr+12])
982 982
983 983 def _jpegxy(data):
984 984 """read the (width, height) from a JPEG header"""
985 985 # adapted from http://www.64lines.com/jpeg-width-height
986 986
987 987 idx = 4
988 988 while True:
989 989 block_size = struct.unpack('>H', data[idx:idx+2])[0]
990 990 idx = idx + block_size
991 991 if data[idx:idx+2] == b'\xFF\xC0':
992 992 # found Start of Frame
993 993 iSOF = idx
994 994 break
995 995 else:
996 996 # read another block
997 997 idx += 2
998 998
999 999 h, w = struct.unpack('>HH', data[iSOF+5:iSOF+9])
1000 1000 return w, h
1001 1001
1002 1002 def _gifxy(data):
1003 1003 """read the (width, height) from a GIF header"""
1004 1004 return struct.unpack('<HH', data[6:10])
1005 1005
1006 1006
1007 1007 class Image(DisplayObject):
1008 1008
1009 1009 _read_flags = 'rb'
1010 1010 _FMT_JPEG = u'jpeg'
1011 1011 _FMT_PNG = u'png'
1012 1012 _FMT_GIF = u'gif'
1013 1013 _ACCEPTABLE_EMBEDDINGS = [_FMT_JPEG, _FMT_PNG, _FMT_GIF]
1014 1014 _MIMETYPES = {
1015 1015 _FMT_PNG: 'image/png',
1016 1016 _FMT_JPEG: 'image/jpeg',
1017 1017 _FMT_GIF: 'image/gif',
1018 1018 }
1019 1019
1020 1020 def __init__(self, data=None, url=None, filename=None, format=None,
1021 1021 embed=None, width=None, height=None, retina=False,
1022 1022 unconfined=False, metadata=None):
1023 1023 """Create a PNG/JPEG/GIF image object given raw data.
1024 1024
1025 1025 When this object is returned by an input cell or passed to the
1026 1026 display function, it will result in the image being displayed
1027 1027 in the frontend.
1028 1028
1029 1029 Parameters
1030 1030 ----------
1031 1031 data : unicode, str or bytes
1032 1032 The raw image data or a URL or filename to load the data from.
1033 1033 This always results in embedded image data.
1034 1034 url : unicode
1035 1035 A URL to download the data from. If you specify `url=`,
1036 1036 the image data will not be embedded unless you also specify `embed=True`.
1037 1037 filename : unicode
1038 1038 Path to a local file to load the data from.
1039 1039 Images from a file are always embedded.
1040 1040 format : unicode
1041 1041 The format of the image data (png/jpeg/jpg/gif). If a filename or URL is given
1042 1042 for format will be inferred from the filename extension.
1043 1043 embed : bool
1044 1044 Should the image data be embedded using a data URI (True) or be
1045 1045 loaded using an <img> tag. Set this to True if you want the image
1046 1046 to be viewable later with no internet connection in the notebook.
1047 1047
1048 1048 Default is `True`, unless the keyword argument `url` is set, then
1049 1049 default value is `False`.
1050 1050
1051 1051 Note that QtConsole is not able to display images if `embed` is set to `False`
1052 1052 width : int
1053 1053 Width in pixels to which to constrain the image in html
1054 1054 height : int
1055 1055 Height in pixels to which to constrain the image in html
1056 1056 retina : bool
1057 1057 Automatically set the width and height to half of the measured
1058 1058 width and height.
1059 1059 This only works for embedded images because it reads the width/height
1060 1060 from image data.
1061 1061 For non-embedded images, you can just set the desired display width
1062 1062 and height directly.
1063 1063 unconfined: bool
1064 1064 Set unconfined=True to disable max-width confinement of the image.
1065 1065 metadata: dict
1066 1066 Specify extra metadata to attach to the image.
1067 1067
1068 1068 Examples
1069 1069 --------
1070 1070 # embedded image data, works in qtconsole and notebook
1071 1071 # when passed positionally, the first arg can be any of raw image data,
1072 1072 # a URL, or a filename from which to load image data.
1073 1073 # The result is always embedding image data for inline images.
1074 1074 Image('http://www.google.fr/images/srpr/logo3w.png')
1075 1075 Image('/path/to/image.jpg')
1076 1076 Image(b'RAW_PNG_DATA...')
1077 1077
1078 1078 # Specifying Image(url=...) does not embed the image data,
1079 1079 # it only generates `<img>` tag with a link to the source.
1080 1080 # This will not work in the qtconsole or offline.
1081 1081 Image(url='http://www.google.fr/images/srpr/logo3w.png')
1082 1082
1083 1083 """
1084 1084 if filename is not None:
1085 1085 ext = self._find_ext(filename)
1086 1086 elif url is not None:
1087 1087 ext = self._find_ext(url)
1088 1088 elif data is None:
1089 1089 raise ValueError("No image data found. Expecting filename, url, or data.")
1090 1090 elif isinstance(data, str) and (
1091 1091 data.startswith('http') or _safe_exists(data)
1092 1092 ):
1093 1093 ext = self._find_ext(data)
1094 1094 else:
1095 1095 ext = None
1096 1096
1097 1097 if format is None:
1098 1098 if ext is not None:
1099 1099 if ext == u'jpg' or ext == u'jpeg':
1100 1100 format = self._FMT_JPEG
1101 if ext == u'png':
1101 elif ext == u'png':
1102 1102 format = self._FMT_PNG
1103 if ext == u'gif':
1103 elif ext == u'gif':
1104 1104 format = self._FMT_GIF
1105 1105 else:
1106 1106 format = ext.lower()
1107 1107 elif isinstance(data, bytes):
1108 1108 # infer image type from image data header,
1109 1109 # only if format has not been specified.
1110 1110 if data[:2] == _JPEG:
1111 1111 format = self._FMT_JPEG
1112 1112
1113 1113 # failed to detect format, default png
1114 1114 if format is None:
1115 1115 format = self._FMT_PNG
1116 1116
1117 1117 if format.lower() == 'jpg':
1118 1118 # jpg->jpeg
1119 1119 format = self._FMT_JPEG
1120 1120
1121 1121 self.format = format.lower()
1122 1122 self.embed = embed if embed is not None else (url is None)
1123 1123
1124 1124 if self.embed and self.format not in self._ACCEPTABLE_EMBEDDINGS:
1125 1125 raise ValueError("Cannot embed the '%s' image format" % (self.format))
1126 1126 if self.embed:
1127 1127 self._mimetype = self._MIMETYPES.get(self.format)
1128 1128
1129 1129 self.width = width
1130 1130 self.height = height
1131 1131 self.retina = retina
1132 1132 self.unconfined = unconfined
1133 1133 super(Image, self).__init__(data=data, url=url, filename=filename,
1134 1134 metadata=metadata)
1135 1135
1136 1136 if self.width is None and self.metadata.get('width', {}):
1137 1137 self.width = metadata['width']
1138 1138
1139 1139 if self.height is None and self.metadata.get('height', {}):
1140 1140 self.height = metadata['height']
1141 1141
1142 1142 if retina:
1143 1143 self._retina_shape()
1144 1144
1145 1145
1146 1146 def _retina_shape(self):
1147 1147 """load pixel-doubled width and height from image data"""
1148 1148 if not self.embed:
1149 1149 return
1150 1150 if self.format == self._FMT_PNG:
1151 1151 w, h = _pngxy(self.data)
1152 1152 elif self.format == self._FMT_JPEG:
1153 1153 w, h = _jpegxy(self.data)
1154 1154 elif self.format == self._FMT_GIF:
1155 1155 w, h = _gifxy(self.data)
1156 1156 else:
1157 1157 # retina only supports png
1158 1158 return
1159 1159 self.width = w // 2
1160 1160 self.height = h // 2
1161 1161
1162 1162 def reload(self):
1163 1163 """Reload the raw data from file or URL."""
1164 1164 if self.embed:
1165 1165 super(Image,self).reload()
1166 1166 if self.retina:
1167 1167 self._retina_shape()
1168 1168
1169 1169 def _repr_html_(self):
1170 1170 if not self.embed:
1171 1171 width = height = klass = ''
1172 1172 if self.width:
1173 1173 width = ' width="%d"' % self.width
1174 1174 if self.height:
1175 1175 height = ' height="%d"' % self.height
1176 1176 if self.unconfined:
1177 1177 klass = ' class="unconfined"'
1178 1178 return u'<img src="{url}"{width}{height}{klass}/>'.format(
1179 1179 url=self.url,
1180 1180 width=width,
1181 1181 height=height,
1182 1182 klass=klass,
1183 1183 )
1184 1184
1185 1185 def _repr_mimebundle_(self, include=None, exclude=None):
1186 1186 """Return the image as a mimebundle
1187 1187
1188 1188 Any new mimetype support should be implemented here.
1189 1189 """
1190 1190 if self.embed:
1191 1191 mimetype = self._mimetype
1192 1192 data, metadata = self._data_and_metadata(always_both=True)
1193 1193 if metadata:
1194 1194 metadata = {mimetype: metadata}
1195 1195 return {mimetype: data}, metadata
1196 1196 else:
1197 1197 return {'text/html': self._repr_html_()}
1198 1198
1199 1199 def _data_and_metadata(self, always_both=False):
1200 1200 """shortcut for returning metadata with shape information, if defined"""
1201 1201 b64_data = b2a_base64(self.data).decode('ascii')
1202 1202 md = {}
1203 1203 if self.metadata:
1204 1204 md.update(self.metadata)
1205 1205 if self.width:
1206 1206 md['width'] = self.width
1207 1207 if self.height:
1208 1208 md['height'] = self.height
1209 1209 if self.unconfined:
1210 1210 md['unconfined'] = self.unconfined
1211 1211 if md or always_both:
1212 1212 return b64_data, md
1213 1213 else:
1214 1214 return b64_data
1215 1215
1216 1216 def _repr_png_(self):
1217 1217 if self.embed and self.format == self._FMT_PNG:
1218 1218 return self._data_and_metadata()
1219 1219
1220 1220 def _repr_jpeg_(self):
1221 1221 if self.embed and self.format == self._FMT_JPEG:
1222 1222 return self._data_and_metadata()
1223 1223
1224 1224 def _find_ext(self, s):
1225 1225 return s.split('.')[-1].lower()
1226 1226
1227 1227
1228 1228 class Video(DisplayObject):
1229 1229
1230 1230 def __init__(self, data=None, url=None, filename=None, embed=False, mimetype=None):
1231 1231 """Create a video object given raw data or an URL.
1232 1232
1233 1233 When this object is returned by an input cell or passed to the
1234 1234 display function, it will result in the video being displayed
1235 1235 in the frontend.
1236 1236
1237 1237 Parameters
1238 1238 ----------
1239 1239 data : unicode, str or bytes
1240 1240 The raw video data or a URL or filename to load the data from.
1241 1241 Raw data will require passing `embed=True`.
1242 1242 url : unicode
1243 1243 A URL for the video. If you specify `url=`,
1244 1244 the image data will not be embedded.
1245 1245 filename : unicode
1246 1246 Path to a local file containing the video.
1247 1247 Will be interpreted as a local URL unless `embed=True`.
1248 1248 embed : bool
1249 1249 Should the video be embedded using a data URI (True) or be
1250 1250 loaded using a <video> tag (False).
1251 1251
1252 1252 Since videos are large, embedding them should be avoided, if possible.
1253 1253 You must confirm embedding as your intention by passing `embed=True`.
1254 1254
1255 1255 Local files can be displayed with URLs without embedding the content, via::
1256 1256
1257 1257 Video('./video.mp4')
1258 1258
1259 1259 mimetype: unicode
1260 1260 Specify the mimetype for embedded videos.
1261 1261 Default will be guessed from file extension, if available.
1262 1262
1263 1263 Examples
1264 1264 --------
1265 1265
1266 1266 Video('https://archive.org/download/Sita_Sings_the_Blues/Sita_Sings_the_Blues_small.mp4')
1267 1267 Video('path/to/video.mp4')
1268 1268 Video('path/to/video.mp4', embed=True)
1269 1269 Video(b'raw-videodata', embed=True)
1270 1270 """
1271 1271 if url is None and isinstance(data, str) and data.startswith(('http:', 'https:')):
1272 1272 url = data
1273 1273 data = None
1274 1274 elif os.path.exists(data):
1275 1275 filename = data
1276 1276 data = None
1277 1277
1278 1278 if data and not embed:
1279 1279 msg = ''.join([
1280 1280 "To embed videos, you must pass embed=True ",
1281 1281 "(this may make your notebook files huge)\n",
1282 1282 "Consider passing Video(url='...')",
1283 1283 ])
1284 1284 raise ValueError(msg)
1285 1285
1286 1286 self.mimetype = mimetype
1287 1287 self.embed = embed
1288 1288 super(Video, self).__init__(data=data, url=url, filename=filename)
1289 1289
1290 1290 def _repr_html_(self):
1291 1291 # External URLs and potentially local files are not embedded into the
1292 1292 # notebook output.
1293 1293 if not self.embed:
1294 1294 url = self.url if self.url is not None else self.filename
1295 1295 output = """<video src="{0}" controls>
1296 1296 Your browser does not support the <code>video</code> element.
1297 1297 </video>""".format(url)
1298 1298 return output
1299 1299
1300 1300 # Embedded videos are base64-encoded.
1301 1301 mimetype = self.mimetype
1302 1302 if self.filename is not None:
1303 1303 if not mimetype:
1304 1304 mimetype, _ = mimetypes.guess_type(self.filename)
1305 1305
1306 1306 with open(self.filename, 'rb') as f:
1307 1307 video = f.read()
1308 1308 else:
1309 1309 video = self.data
1310 1310 if isinstance(video, str):
1311 1311 # unicode input is already b64-encoded
1312 1312 b64_video = video
1313 1313 else:
1314 1314 b64_video = b2a_base64(video).decode('ascii').rstrip()
1315 1315
1316 1316 output = """<video controls>
1317 1317 <source src="data:{0};base64,{1}" type="{0}">
1318 1318 Your browser does not support the video tag.
1319 1319 </video>""".format(mimetype, b64_video)
1320 1320 return output
1321 1321
1322 1322 def reload(self):
1323 1323 # TODO
1324 1324 pass
1325 1325
1326 1326
1327 1327 def clear_output(wait=False):
1328 1328 """Clear the output of the current cell receiving output.
1329 1329
1330 1330 Parameters
1331 1331 ----------
1332 1332 wait : bool [default: false]
1333 1333 Wait to clear the output until new output is available to replace it."""
1334 1334 from IPython.core.interactiveshell import InteractiveShell
1335 1335 if InteractiveShell.initialized():
1336 1336 InteractiveShell.instance().display_pub.clear_output(wait)
1337 1337 else:
1338 1338 print('\033[2K\r', end='')
1339 1339 sys.stdout.flush()
1340 1340 print('\033[2K\r', end='')
1341 1341 sys.stderr.flush()
1342 1342
1343 1343
1344 1344 @skip_doctest
1345 1345 def set_matplotlib_formats(*formats, **kwargs):
1346 1346 """Select figure formats for the inline backend. Optionally pass quality for JPEG.
1347 1347
1348 1348 For example, this enables PNG and JPEG output with a JPEG quality of 90%::
1349 1349
1350 1350 In [1]: set_matplotlib_formats('png', 'jpeg', quality=90)
1351 1351
1352 1352 To set this in your config files use the following::
1353 1353
1354 1354 c.InlineBackend.figure_formats = {'png', 'jpeg'}
1355 1355 c.InlineBackend.print_figure_kwargs.update({'quality' : 90})
1356 1356
1357 1357 Parameters
1358 1358 ----------
1359 1359 *formats : strs
1360 1360 One or more figure formats to enable: 'png', 'retina', 'jpeg', 'svg', 'pdf'.
1361 1361 **kwargs :
1362 1362 Keyword args will be relayed to ``figure.canvas.print_figure``.
1363 1363 """
1364 1364 from IPython.core.interactiveshell import InteractiveShell
1365 1365 from IPython.core.pylabtools import select_figure_formats
1366 1366 # build kwargs, starting with InlineBackend config
1367 1367 kw = {}
1368 1368 from ipykernel.pylab.config import InlineBackend
1369 1369 cfg = InlineBackend.instance()
1370 1370 kw.update(cfg.print_figure_kwargs)
1371 1371 kw.update(**kwargs)
1372 1372 shell = InteractiveShell.instance()
1373 1373 select_figure_formats(shell, formats, **kw)
1374 1374
1375 1375 @skip_doctest
1376 1376 def set_matplotlib_close(close=True):
1377 1377 """Set whether the inline backend closes all figures automatically or not.
1378 1378
1379 1379 By default, the inline backend used in the IPython Notebook will close all
1380 1380 matplotlib figures automatically after each cell is run. This means that
1381 1381 plots in different cells won't interfere. Sometimes, you may want to make
1382 1382 a plot in one cell and then refine it in later cells. This can be accomplished
1383 1383 by::
1384 1384
1385 1385 In [1]: set_matplotlib_close(False)
1386 1386
1387 1387 To set this in your config files use the following::
1388 1388
1389 1389 c.InlineBackend.close_figures = False
1390 1390
1391 1391 Parameters
1392 1392 ----------
1393 1393 close : bool
1394 1394 Should all matplotlib figures be automatically closed after each cell is
1395 1395 run?
1396 1396 """
1397 1397 from ipykernel.pylab.config import InlineBackend
1398 1398 cfg = InlineBackend.instance()
1399 1399 cfg.close_figures = close
General Comments 0
You need to be logged in to leave comments. Login now