##// END OF EJS Templates
use get_ipython API function, not builtin injection, to detect IPython.
MinRK -
Show More
@@ -1,153 +1,151 b''
1 1 """A matplotlib backend for publishing figures via display_data"""
2 2 #-----------------------------------------------------------------------------
3 3 # Copyright (C) 2011 The IPython Development Team
4 4 #
5 5 # Distributed under the terms of the BSD License. The full license is in
6 6 # the file COPYING, distributed as part of this software.
7 7 #-----------------------------------------------------------------------------
8 8
9 9 #-----------------------------------------------------------------------------
10 10 # Imports
11 11 #-----------------------------------------------------------------------------
12 12 from __future__ import print_function
13 13
14 14 # Third-party imports
15 15 import matplotlib
16 16 from matplotlib.backends.backend_agg import FigureCanvasAgg
17 17 from matplotlib._pylab_helpers import Gcf
18 18
19 19 # Local imports
20 20 from IPython.core.getipython import get_ipython
21 21 from IPython.core.display import display
22 22
23 23 from .config import InlineBackend
24 24
25 25 #-----------------------------------------------------------------------------
26 26 # Functions
27 27 #-----------------------------------------------------------------------------
28 28
29 29 def show(close=None):
30 30 """Show all figures as SVG/PNG payloads sent to the IPython clients.
31 31
32 32 Parameters
33 33 ----------
34 34 close : bool, optional
35 35 If true, a ``plt.close('all')`` call is automatically issued after
36 36 sending all the figures. If this is set, the figures will entirely
37 37 removed from the internal list of figures.
38 38 """
39 39 if close is None:
40 40 close = InlineBackend.instance().close_figures
41 41 try:
42 42 for figure_manager in Gcf.get_all_fig_managers():
43 43 display(figure_manager.canvas.figure)
44 44 finally:
45 45 show._to_draw = []
46 46 if close:
47 47 matplotlib.pyplot.close('all')
48 48
49 49
50 50 # This flag will be reset by draw_if_interactive when called
51 51 show._draw_called = False
52 52 # list of figures to draw when flush_figures is called
53 53 show._to_draw = []
54 54
55 55
56 56 def draw_if_interactive():
57 57 """
58 58 Is called after every pylab drawing command
59 59 """
60 60 # signal that the current active figure should be sent at the end of
61 61 # execution. Also sets the _draw_called flag, signaling that there will be
62 62 # something to send. At the end of the code execution, a separate call to
63 63 # flush_figures() will act upon these values
64 64 manager = Gcf.get_active()
65 65 if manager is None:
66 66 return
67 67 fig = manager.canvas.figure
68 68
69 69 # Hack: matplotlib FigureManager objects in interacive backends (at least
70 70 # in some of them) monkeypatch the figure object and add a .show() method
71 71 # to it. This applies the same monkeypatch in order to support user code
72 72 # that might expect `.show()` to be part of the official API of figure
73 73 # objects.
74 74 # For further reference:
75 75 # https://github.com/ipython/ipython/issues/1612
76 76 # https://github.com/matplotlib/matplotlib/issues/835
77 77
78 78 if not hasattr(fig, 'show'):
79 79 # Queue up `fig` for display
80 80 fig.show = lambda *a: display(fig)
81 81
82 82 # If matplotlib was manually set to non-interactive mode, this function
83 83 # should be a no-op (otherwise we'll generate duplicate plots, since a user
84 84 # who set ioff() manually expects to make separate draw/show calls).
85 85 if not matplotlib.is_interactive():
86 86 return
87 87
88 88 # ensure current figure will be drawn, and each subsequent call
89 89 # of draw_if_interactive() moves the active figure to ensure it is
90 90 # drawn last
91 91 try:
92 92 show._to_draw.remove(fig)
93 93 except ValueError:
94 94 # ensure it only appears in the draw list once
95 95 pass
96 96 # Queue up the figure for drawing in next show() call
97 97 show._to_draw.append(fig)
98 98 show._draw_called = True
99 99
100 100
101 101 def flush_figures():
102 102 """Send all figures that changed
103 103
104 104 This is meant to be called automatically and will call show() if, during
105 105 prior code execution, there had been any calls to draw_if_interactive.
106 106
107 107 This function is meant to be used as a post_execute callback in IPython,
108 108 so user-caused errors are handled with showtraceback() instead of being
109 109 allowed to raise. If this function is not called from within IPython,
110 110 then these exceptions will raise.
111 111 """
112 112 if not show._draw_called:
113 113 return
114 114
115 115 if InlineBackend.instance().close_figures:
116 116 # ignore the tracking, just draw and close all figures
117 117 try:
118 118 return show(True)
119 119 except Exception as e:
120 120 # safely show traceback if in IPython, else raise
121 try:
122 get_ipython
123 except NameError:
121 ip = get_ipython()
122 if ip is None:
124 123 raise e
125 124 else:
126 get_ipython().showtraceback()
125 ip.showtraceback()
127 126 return
128 127 try:
129 128 # exclude any figures that were closed:
130 129 active = set([fm.canvas.figure for fm in Gcf.get_all_fig_managers()])
131 130 for fig in [ fig for fig in show._to_draw if fig in active ]:
132 131 try:
133 132 display(fig)
134 133 except Exception as e:
135 134 # safely show traceback if in IPython, else raise
136 try:
137 get_ipython
138 except NameError:
135 ip = get_ipython()
136 if ip is None:
139 137 raise e
140 138 else:
141 get_ipython().showtraceback()
142 break
139 ip.showtraceback()
140 return
143 141 finally:
144 142 # clear flags for next round
145 143 show._to_draw = []
146 144 show._draw_called = False
147 145
148 146
149 147 # Changes to matplotlib in version 1.2 requires a mpl backend to supply a default
150 148 # figurecanvas. This is set here to a Agg canvas
151 149 # See https://github.com/matplotlib/matplotlib/pull/1125
152 150 FigureCanvas = FigureCanvasAgg
153 151
General Comments 0
You need to be logged in to leave comments. Login now