Show More
@@ -87,8 +87,8 b' def figsize(sizex, sizey):' | |||
|
87 | 87 | matplotlib.rcParams['figure.figsize'] = [sizex, sizey] |
|
88 | 88 | |
|
89 | 89 | |
|
90 | def figure_to_svg(fig): | |
|
91 | """Convert a figure to svg for inline display.""" | |
|
90 | def print_figure(fig, fmt='png'): | |
|
91 | """Convert a figure to svg or png for inline display.""" | |
|
92 | 92 | # When there's an empty figure, we shouldn't return anything, otherwise we |
|
93 | 93 | # get big blank areas in the qt console. |
|
94 | 94 | if not fig.axes: |
@@ -100,12 +100,15 b' def figure_to_svg(fig):' | |||
|
100 | 100 | fig.set_edgecolor('white') |
|
101 | 101 | try: |
|
102 | 102 | string_io = StringIO() |
|
103 | fig.canvas.print_figure(string_io, format='svg') | |
|
104 | svg = string_io.getvalue() | |
|
103 | # use 72 dpi to match QTConsole's dpi | |
|
104 | fig.canvas.print_figure(string_io, format=fmt, dpi=72) | |
|
105 | data = string_io.getvalue() | |
|
105 | 106 | finally: |
|
106 | 107 | fig.set_facecolor(fc) |
|
107 | 108 | fig.set_edgecolor(ec) |
|
108 | return svg | |
|
109 | if fmt == 'png': | |
|
110 | data = data.encode('base64') | |
|
111 | return data | |
|
109 | 112 | |
|
110 | 113 | |
|
111 | 114 | # We need a little factory function here to create the closure where |
@@ -150,6 +153,29 b' def mpl_runner(safe_execfile):' | |||
|
150 | 153 | return mpl_execfile |
|
151 | 154 | |
|
152 | 155 | |
|
156 | def select_figure_format(shell, fmt): | |
|
157 | """Select figure format for inline backend, either 'png' or 'svg'. | |
|
158 | ||
|
159 | Using this method ensures only one figure format is active at a time. | |
|
160 | """ | |
|
161 | from matplotlib.figure import Figure | |
|
162 | from IPython.zmq.pylab import backend_inline | |
|
163 | ||
|
164 | svg_formatter = shell.display_formatter.formatters['image/svg+xml'] | |
|
165 | png_formatter = shell.display_formatter.formatters['image/png'] | |
|
166 | ||
|
167 | if fmt=='png': | |
|
168 | svg_formatter.type_printers.pop(Figure, None) | |
|
169 | png_formatter.for_type(Figure, lambda fig: print_figure(fig, 'png')) | |
|
170 | elif fmt=='svg': | |
|
171 | png_formatter.type_printers.pop(Figure, None) | |
|
172 | svg_formatter.for_type(Figure, lambda fig: print_figure(fig, 'svg')) | |
|
173 | else: | |
|
174 | raise ValueError("supported formats are: 'png', 'svg', not %r"%fmt) | |
|
175 | ||
|
176 | # set the format to be used in the backend() | |
|
177 | backend_inline._figure_format = fmt | |
|
178 | ||
|
153 | 179 | #----------------------------------------------------------------------------- |
|
154 | 180 | # Code for initializing matplotlib and importing pylab |
|
155 | 181 | #----------------------------------------------------------------------------- |
@@ -208,7 +234,6 b' def activate_matplotlib(backend):' | |||
|
208 | 234 | # For this, we wrap it into a decorator which adds a 'called' flag. |
|
209 | 235 | pylab.draw_if_interactive = flag_calls(pylab.draw_if_interactive) |
|
210 | 236 | |
|
211 | ||
|
212 | 237 | def import_pylab(user_ns, backend, import_all=True, shell=None): |
|
213 | 238 | """Import the standard pylab symbols into user_ns.""" |
|
214 | 239 | |
@@ -228,43 +253,32 b' def import_pylab(user_ns, backend, import_all=True, shell=None):' | |||
|
228 | 253 | # If using our svg payload backend, register the post-execution |
|
229 | 254 | # function that will pick up the results for display. This can only be |
|
230 | 255 | # done with access to the real shell object. |
|
256 | # | |
|
257 | from IPython.zmq.pylab.backend_inline import InlineBackendConfig | |
|
258 | ||
|
259 | cfg = InlineBackendConfig.instance(config=shell.config) | |
|
260 | cfg.shell = shell | |
|
261 | ||
|
231 | 262 | if backend == backends['inline']: |
|
232 |
from IPython.zmq.pylab.backend_inline import flush_ |
|
|
263 | from IPython.zmq.pylab.backend_inline import flush_figures | |
|
233 | 264 | from matplotlib import pyplot |
|
234 |
shell.register_post_execute(flush_ |
|
|
235 | # The typical default figure size is too large for inline use, | |
|
236 | # so we shrink the figure size to 6x4, and tweak fonts to | |
|
237 | # make that fit. This is configurable via Global.pylab_inline_rc, | |
|
238 | # or rather it will be once the zmq kernel is hooked up to | |
|
239 | # the config system. | |
|
240 | ||
|
241 | default_rc = { | |
|
242 | 'figure.figsize': (6.0,4.0), | |
|
243 | # 12pt labels get cutoff on 6x4 logplots, so use 10pt. | |
|
244 | 'font.size': 10, | |
|
245 | # 10pt still needs a little more room on the xlabel: | |
|
246 | 'figure.subplot.bottom' : .125 | |
|
247 | } | |
|
248 | rc = getattr(shell.config.Global, 'pylab_inline_rc', default_rc) | |
|
249 | pyplot.rcParams.update(rc) | |
|
250 | shell.config.Global.pylab_inline_rc = rc | |
|
265 | shell.register_post_execute(flush_figures) | |
|
266 | # load inline_rc | |
|
267 | pyplot.rcParams.update(cfg.rc) | |
|
251 | 268 | |
|
252 | 269 | # Add 'figsize' to pyplot and to the user's namespace |
|
253 | 270 | user_ns['figsize'] = pyplot.figsize = figsize |
|
254 | 271 | shell.user_ns_hidden['figsize'] = figsize |
|
255 | 272 | |
|
273 | # Setup the default figure format | |
|
274 | fmt = cfg.figure_format | |
|
275 | select_figure_format(shell, fmt) | |
|
276 | ||
|
256 | 277 | # The old pastefig function has been replaced by display |
|
257 | # Always add this svg formatter so display works. | |
|
258 | from IPython.core.display import display, display_svg | |
|
259 | svg_formatter = shell.display_formatter.formatters['image/svg+xml'] | |
|
260 | svg_formatter.for_type_by_name( | |
|
261 | 'matplotlib.figure','Figure',figure_to_svg | |
|
262 | ) | |
|
278 | from IPython.core.display import display | |
|
263 | 279 | # Add display and display_png to the user's namespace |
|
264 | 280 | user_ns['display'] = display |
|
265 | 281 | shell.user_ns_hidden['display'] = display |
|
266 | user_ns['display_svg'] = display_svg | |
|
267 | shell.user_ns_hidden['display_svg'] = display_svg | |
|
268 | 282 | user_ns['getfigs'] = getfigs |
|
269 | 283 | shell.user_ns_hidden['getfigs'] = getfigs |
|
270 | 284 |
@@ -10,12 +10,46 b' import sys' | |||
|
10 | 10 | |
|
11 | 11 | # Third-party imports |
|
12 | 12 | import matplotlib |
|
13 |
from matplotlib.backends.backend_ |
|
|
13 | from matplotlib.backends.backend_agg import new_figure_manager | |
|
14 | 14 | from matplotlib._pylab_helpers import Gcf |
|
15 | 15 | |
|
16 | 16 | # Local imports. |
|
17 | from IPython.config.configurable import SingletonConfigurable | |
|
17 | 18 | from IPython.core.displaypub import publish_display_data |
|
18 |
from IPython.lib.pylabtools import figure |
|
|
19 | from IPython.lib.pylabtools import print_figure, select_figure_format | |
|
20 | from IPython.utils.traitlets import Dict, Instance, CaselessStrEnum | |
|
21 | #----------------------------------------------------------------------------- | |
|
22 | # Configurable for inline backend options | |
|
23 | #----------------------------------------------------------------------------- | |
|
24 | ||
|
25 | class InlineBackendConfig(SingletonConfigurable): | |
|
26 | """An object to store configuration of the inline backend.""" | |
|
27 | ||
|
28 | # The typical default figure size is too large for inline use, | |
|
29 | # so we shrink the figure size to 6x4, and tweak fonts to | |
|
30 | # make that fit. This is configurable via Global.pylab_inline_rc, | |
|
31 | # or rather it will be once the zmq kernel is hooked up to | |
|
32 | # the config system. | |
|
33 | rc = Dict({'figure.figsize': (6.0,4.0), | |
|
34 | # 12pt labels get cutoff on 6x4 logplots, so use 10pt. | |
|
35 | 'font.size': 10, | |
|
36 | # 10pt still needs a little more room on the xlabel: | |
|
37 | 'figure.subplot.bottom' : .125 | |
|
38 | }, config=True, | |
|
39 | help="""Subset of matplotlib rcParams that should be different for the | |
|
40 | inline backend.""" | |
|
41 | ) | |
|
42 | figure_format = CaselessStrEnum(['svg', 'png'], default_value='png', config=True, | |
|
43 | help="The image format for figures with the inline backend.") | |
|
44 | ||
|
45 | def _format_changed(self, name, old, new): | |
|
46 | if self.shell is None: | |
|
47 | return | |
|
48 | else: | |
|
49 | select_figure_format(self.shell, new) | |
|
50 | ||
|
51 | shell = Instance('IPython.core.interactiveshell.InteractiveShellABC') | |
|
52 | ||
|
19 | 53 | |
|
20 | 54 | #----------------------------------------------------------------------------- |
|
21 | 55 | # Functions |
@@ -32,7 +66,7 b' def show(close=True):' | |||
|
32 | 66 | removed from the internal list of figures. |
|
33 | 67 | """ |
|
34 | 68 | for figure_manager in Gcf.get_all_fig_managers(): |
|
35 |
send_ |
|
|
69 | send_figure(figure_manager.canvas.figure) | |
|
36 | 70 | if close: |
|
37 | 71 | matplotlib.pyplot.close('all') |
|
38 | 72 | |
@@ -50,8 +84,8 b' def draw_if_interactive():' | |||
|
50 | 84 | show._draw_called = True |
|
51 | 85 | |
|
52 | 86 | |
|
53 |
def flush_ |
|
|
54 |
"""Call show, close all open figures, sending all |
|
|
87 | def flush_figures(): | |
|
88 | """Call show, close all open figures, sending all figure images. | |
|
55 | 89 | |
|
56 | 90 | This is meant to be called automatically and will call show() if, during |
|
57 | 91 | prior code execution, there had been any calls to draw_if_interactive. |
@@ -61,21 +95,23 b' def flush_svg():' | |||
|
61 | 95 | show._draw_called = False |
|
62 | 96 | |
|
63 | 97 | |
|
64 |
def send_ |
|
|
65 |
"""Draw the current figure and send it as a |
|
|
98 | def send_figure(fig): | |
|
99 | """Draw the current figure and send it as a PNG payload. | |
|
66 | 100 | """ |
|
67 | 101 | # For an empty figure, don't even bother calling figure_to_svg, to avoid |
|
68 | 102 | # big blank spaces in the qt console |
|
69 | 103 | if not fig.axes: |
|
70 | 104 | return |
|
71 | ||
|
72 | svg = figure_to_svg(fig) | |
|
105 | fmt = InlineBackendConfig.instance().figure_format | |
|
106 | data = print_figure(fig, fmt) | |
|
107 | mimetypes = { 'png' : 'image/png', 'svg' : 'image/svg+xml' } | |
|
108 | mime = mimetypes[fmt] | |
|
73 | 109 | # flush text streams before sending figures, helps a little with output |
|
74 | 110 | # synchronization in the console (though it's a bandaid, not a real sln) |
|
75 | 111 | sys.stdout.flush(); sys.stderr.flush() |
|
76 | 112 | publish_display_data( |
|
77 |
'IPython.zmq.pylab.backend_inline.send_ |
|
|
113 | 'IPython.zmq.pylab.backend_inline.send_figure', | |
|
78 | 114 | 'Matplotlib Plot', |
|
79 |
{ |
|
|
115 | {mime : data} | |
|
80 | 116 | ) |
|
81 | 117 |
General Comments 0
You need to be logged in to leave comments.
Login now