|
3 | 3 | # Copyright (c) IPython Development Team. |
4 | 4 | # Distributed under the terms of the Modified BSD License. |
5 | 5 |
|
6 | | -import matplotlib |
7 | | -from matplotlib.backends.backend_agg import ( |
8 | | - new_figure_manager, |
9 | | - FigureCanvasAgg, |
10 | | - new_figure_manager_given_figure, |
11 | | -) # analysis: ignore |
12 | | -from matplotlib import colors |
13 | | -from matplotlib._pylab_helpers import Gcf |
| 6 | +import warnings |
14 | 7 |
|
15 | | -from IPython.core.getipython import get_ipython |
16 | | -from IPython.core.pylabtools import select_figure_formats |
17 | | -from IPython.display import display |
| 8 | +from matplotlib_inline.backend_inline import * # analysis: ignore |
18 | 9 |
|
19 | | -from .config import InlineBackend |
20 | 10 |
|
21 | | - |
22 | | -def show(close=None, block=None): |
23 | | - """Show all figures as SVG/PNG payloads sent to the IPython clients. |
24 | | -
|
25 | | - Parameters |
26 | | - ---------- |
27 | | - close : bool, optional |
28 | | - If true, a ``plt.close('all')`` call is automatically issued after |
29 | | - sending all the figures. If this is set, the figures will entirely |
30 | | - removed from the internal list of figures. |
31 | | - block : Not used. |
32 | | - The `block` parameter is a Matplotlib experimental parameter. |
33 | | - We accept it in the function signature for compatibility with other |
34 | | - backends. |
35 | | - """ |
36 | | - if close is None: |
37 | | - close = InlineBackend.instance().close_figures |
38 | | - try: |
39 | | - for figure_manager in Gcf.get_all_fig_managers(): |
40 | | - display( |
41 | | - figure_manager.canvas.figure, |
42 | | - metadata=_fetch_figure_metadata(figure_manager.canvas.figure) |
43 | | - ) |
44 | | - finally: |
45 | | - show._to_draw = [] |
46 | | - # only call close('all') if any to close |
47 | | - # close triggers gc.collect, which can be slow |
48 | | - if close and Gcf.get_all_fig_managers(): |
49 | | - matplotlib.pyplot.close('all') |
50 | | - |
51 | | - |
52 | | -# This flag will be reset by draw_if_interactive when called |
53 | | -show._draw_called = False |
54 | | -# list of figures to draw when flush_figures is called |
55 | | -show._to_draw = [] |
56 | | - |
57 | | - |
58 | | -def draw_if_interactive(): |
59 | | - """ |
60 | | - Is called after every pylab drawing command |
61 | | - """ |
62 | | - # signal that the current active figure should be sent at the end of |
63 | | - # execution. Also sets the _draw_called flag, signaling that there will be |
64 | | - # something to send. At the end of the code execution, a separate call to |
65 | | - # flush_figures() will act upon these values |
66 | | - manager = Gcf.get_active() |
67 | | - if manager is None: |
68 | | - return |
69 | | - fig = manager.canvas.figure |
70 | | - |
71 | | - # Hack: matplotlib FigureManager objects in interacive backends (at least |
72 | | - # in some of them) monkeypatch the figure object and add a .show() method |
73 | | - # to it. This applies the same monkeypatch in order to support user code |
74 | | - # that might expect `.show()` to be part of the official API of figure |
75 | | - # objects. |
76 | | - # For further reference: |
77 | | - # https://github.com/ipython/ipython/issues/1612 |
78 | | - # https://github.com/matplotlib/matplotlib/issues/835 |
79 | | - |
80 | | - if not hasattr(fig, 'show'): |
81 | | - # Queue up `fig` for display |
82 | | - fig.show = lambda *a: display(fig, metadata=_fetch_figure_metadata(fig)) |
83 | | - |
84 | | - # If matplotlib was manually set to non-interactive mode, this function |
85 | | - # should be a no-op (otherwise we'll generate duplicate plots, since a user |
86 | | - # who set ioff() manually expects to make separate draw/show calls). |
87 | | - if not matplotlib.is_interactive(): |
88 | | - return |
89 | | - |
90 | | - # ensure current figure will be drawn, and each subsequent call |
91 | | - # of draw_if_interactive() moves the active figure to ensure it is |
92 | | - # drawn last |
93 | | - try: |
94 | | - show._to_draw.remove(fig) |
95 | | - except ValueError: |
96 | | - # ensure it only appears in the draw list once |
97 | | - pass |
98 | | - # Queue up the figure for drawing in next show() call |
99 | | - show._to_draw.append(fig) |
100 | | - show._draw_called = True |
101 | | - |
102 | | - |
103 | | -def flush_figures(): |
104 | | - """Send all figures that changed |
105 | | -
|
106 | | - This is meant to be called automatically and will call show() if, during |
107 | | - prior code execution, there had been any calls to draw_if_interactive. |
108 | | -
|
109 | | - This function is meant to be used as a post_execute callback in IPython, |
110 | | - so user-caused errors are handled with showtraceback() instead of being |
111 | | - allowed to raise. If this function is not called from within IPython, |
112 | | - then these exceptions will raise. |
113 | | - """ |
114 | | - if not show._draw_called: |
115 | | - return |
116 | | - |
117 | | - if InlineBackend.instance().close_figures: |
118 | | - # ignore the tracking, just draw and close all figures |
119 | | - try: |
120 | | - return show(True) |
121 | | - except Exception as e: |
122 | | - # safely show traceback if in IPython, else raise |
123 | | - ip = get_ipython() |
124 | | - if ip is None: |
125 | | - raise e |
126 | | - else: |
127 | | - ip.showtraceback() |
128 | | - return |
129 | | - try: |
130 | | - # exclude any figures that were closed: |
131 | | - active = set([fm.canvas.figure for fm in Gcf.get_all_fig_managers()]) |
132 | | - for fig in [ fig for fig in show._to_draw if fig in active ]: |
133 | | - try: |
134 | | - display(fig, metadata=_fetch_figure_metadata(fig)) |
135 | | - except Exception as e: |
136 | | - # safely show traceback if in IPython, else raise |
137 | | - ip = get_ipython() |
138 | | - if ip is None: |
139 | | - raise e |
140 | | - else: |
141 | | - ip.showtraceback() |
142 | | - return |
143 | | - finally: |
144 | | - # clear flags for next round |
145 | | - show._to_draw = [] |
146 | | - show._draw_called = False |
147 | | - |
148 | | - |
149 | | -# Changes to matplotlib in version 1.2 requires a mpl backend to supply a default |
150 | | -# figurecanvas. This is set here to a Agg canvas |
151 | | -# See https://github.com/matplotlib/matplotlib/pull/1125 |
152 | | -FigureCanvas = FigureCanvasAgg |
153 | | - |
154 | | - |
155 | | -def configure_inline_support(shell, backend): |
156 | | - """Configure an IPython shell object for matplotlib use. |
157 | | -
|
158 | | - Parameters |
159 | | - ---------- |
160 | | - shell : InteractiveShell instance |
161 | | - backend : matplotlib backend |
162 | | - """ |
163 | | - # If using our svg payload backend, register the post-execution |
164 | | - # function that will pick up the results for display. This can only be |
165 | | - # done with access to the real shell object. |
166 | | - |
167 | | - cfg = InlineBackend.instance(parent=shell) |
168 | | - cfg.shell = shell |
169 | | - if cfg not in shell.configurables: |
170 | | - shell.configurables.append(cfg) |
171 | | - |
172 | | - if backend == 'module://ipykernel.pylab.backend_inline': |
173 | | - shell.events.register('post_execute', flush_figures) |
174 | | - |
175 | | - # Save rcParams that will be overwrittern |
176 | | - shell._saved_rcParams = {} |
177 | | - for k in cfg.rc: |
178 | | - shell._saved_rcParams[k] = matplotlib.rcParams[k] |
179 | | - # load inline_rc |
180 | | - matplotlib.rcParams.update(cfg.rc) |
181 | | - new_backend_name = "inline" |
182 | | - else: |
183 | | - try: |
184 | | - shell.events.unregister('post_execute', flush_figures) |
185 | | - except ValueError: |
186 | | - pass |
187 | | - if hasattr(shell, '_saved_rcParams'): |
188 | | - matplotlib.rcParams.update(shell._saved_rcParams) |
189 | | - del shell._saved_rcParams |
190 | | - new_backend_name = "other" |
191 | | - |
192 | | - # only enable the formats once -> don't change the enabled formats (which the user may |
193 | | - # has changed) when getting another "%matplotlib inline" call. |
194 | | - # See https://github.com/ipython/ipykernel/issues/29 |
195 | | - cur_backend = getattr(configure_inline_support, "current_backend", "unset") |
196 | | - if new_backend_name != cur_backend: |
197 | | - # Setup the default figure format |
198 | | - select_figure_formats(shell, cfg.figure_formats, **cfg.print_figure_kwargs) |
199 | | - configure_inline_support.current_backend = new_backend_name |
200 | | - |
201 | | - |
202 | | -def _enable_matplotlib_integration(): |
203 | | - """Enable extra IPython matplotlib integration when we are loaded as the matplotlib backend.""" |
204 | | - from matplotlib import get_backend |
205 | | - ip = get_ipython() |
206 | | - backend = get_backend() |
207 | | - if ip and backend == 'module://%s' % __name__: |
208 | | - from IPython.core.pylabtools import activate_matplotlib |
209 | | - try: |
210 | | - activate_matplotlib(backend) |
211 | | - configure_inline_support(ip, backend) |
212 | | - except (ImportError, AttributeError): |
213 | | - # bugs may cause a circular import on Python 2 |
214 | | - def configure_once(*args): |
215 | | - activate_matplotlib(backend) |
216 | | - configure_inline_support(ip, backend) |
217 | | - ip.events.unregister('post_run_cell', configure_once) |
218 | | - ip.events.register('post_run_cell', configure_once) |
219 | | - |
220 | | -_enable_matplotlib_integration() |
221 | | - |
222 | | -def _fetch_figure_metadata(fig): |
223 | | - """Get some metadata to help with displaying a figure.""" |
224 | | - # determine if a background is needed for legibility |
225 | | - if _is_transparent(fig.get_facecolor()): |
226 | | - # the background is transparent |
227 | | - ticksLight = _is_light([label.get_color() |
228 | | - for axes in fig.axes |
229 | | - for axis in (axes.xaxis, axes.yaxis) |
230 | | - for label in axis.get_ticklabels()]) |
231 | | - if ticksLight.size and (ticksLight == ticksLight[0]).all(): |
232 | | - # there are one or more tick labels, all with the same lightness |
233 | | - return {'needs_background': 'dark' if ticksLight[0] else 'light'} |
234 | | - |
235 | | - return None |
236 | | - |
237 | | -def _is_light(color): |
238 | | - """Determines if a color (or each of a sequence of colors) is light (as |
239 | | - opposed to dark). Based on ITU BT.601 luminance formula (see |
240 | | - https://stackoverflow.com/a/596241).""" |
241 | | - rgbaArr = colors.to_rgba_array(color) |
242 | | - return rgbaArr[:,:3].dot((.299, .587, .114)) > .5 |
243 | | - |
244 | | -def _is_transparent(color): |
245 | | - """Determine transparency from alpha.""" |
246 | | - rgba = colors.to_rgba(color) |
247 | | - return rgba[3] < .5 |
| 11 | +warnings.warn( |
| 12 | + "`ipykernel.pylab.backend_inline` is deprecated, directly " |
| 13 | + "use `matplotlib_inline.backend_inline`", |
| 14 | + DeprecationWarning |
| 15 | +) |
0 commit comments