##// END OF EJS Templates
add InlineBackendConfig...
MinRK -
Show More
@@ -87,8 +87,8 b' def figsize(sizex, sizey):'
87 matplotlib.rcParams['figure.figsize'] = [sizex, sizey]
87 matplotlib.rcParams['figure.figsize'] = [sizex, sizey]
88
88
89
89
90 def figure_to_svg(fig):
90 def print_figure(fig, fmt='png'):
91 """Convert a figure to svg for inline display."""
91 """Convert a figure to svg or png for inline display."""
92 # When there's an empty figure, we shouldn't return anything, otherwise we
92 # When there's an empty figure, we shouldn't return anything, otherwise we
93 # get big blank areas in the qt console.
93 # get big blank areas in the qt console.
94 if not fig.axes:
94 if not fig.axes:
@@ -100,12 +100,15 b' def figure_to_svg(fig):'
100 fig.set_edgecolor('white')
100 fig.set_edgecolor('white')
101 try:
101 try:
102 string_io = StringIO()
102 string_io = StringIO()
103 fig.canvas.print_figure(string_io, format='svg')
103 # use 72 dpi to match QTConsole's dpi
104 svg = string_io.getvalue()
104 fig.canvas.print_figure(string_io, format=fmt, dpi=72)
105 data = string_io.getvalue()
105 finally:
106 finally:
106 fig.set_facecolor(fc)
107 fig.set_facecolor(fc)
107 fig.set_edgecolor(ec)
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 # We need a little factory function here to create the closure where
114 # We need a little factory function here to create the closure where
@@ -150,6 +153,29 b' def mpl_runner(safe_execfile):'
150 return mpl_execfile
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 # Code for initializing matplotlib and importing pylab
180 # Code for initializing matplotlib and importing pylab
155 #-----------------------------------------------------------------------------
181 #-----------------------------------------------------------------------------
@@ -208,7 +234,6 b' def activate_matplotlib(backend):'
208 # For this, we wrap it into a decorator which adds a 'called' flag.
234 # For this, we wrap it into a decorator which adds a 'called' flag.
209 pylab.draw_if_interactive = flag_calls(pylab.draw_if_interactive)
235 pylab.draw_if_interactive = flag_calls(pylab.draw_if_interactive)
210
236
211
212 def import_pylab(user_ns, backend, import_all=True, shell=None):
237 def import_pylab(user_ns, backend, import_all=True, shell=None):
213 """Import the standard pylab symbols into user_ns."""
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 # If using our svg payload backend, register the post-execution
253 # If using our svg payload backend, register the post-execution
229 # function that will pick up the results for display. This can only be
254 # function that will pick up the results for display. This can only be
230 # done with access to the real shell object.
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 if backend == backends['inline']:
262 if backend == backends['inline']:
232 from IPython.zmq.pylab.backend_inline import flush_svg
263 from IPython.zmq.pylab.backend_inline import flush_figures
233 from matplotlib import pyplot
264 from matplotlib import pyplot
234 shell.register_post_execute(flush_svg)
265 shell.register_post_execute(flush_figures)
235 # The typical default figure size is too large for inline use,
266 # load inline_rc
236 # so we shrink the figure size to 6x4, and tweak fonts to
267 pyplot.rcParams.update(cfg.rc)
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
251
268
252 # Add 'figsize' to pyplot and to the user's namespace
269 # Add 'figsize' to pyplot and to the user's namespace
253 user_ns['figsize'] = pyplot.figsize = figsize
270 user_ns['figsize'] = pyplot.figsize = figsize
254 shell.user_ns_hidden['figsize'] = figsize
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 # The old pastefig function has been replaced by display
277 # The old pastefig function has been replaced by display
257 # Always add this svg formatter so display works.
278 from IPython.core.display import display
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 )
263 # Add display and display_png to the user's namespace
279 # Add display and display_png to the user's namespace
264 user_ns['display'] = display
280 user_ns['display'] = display
265 shell.user_ns_hidden['display'] = display
281 shell.user_ns_hidden['display'] = display
266 user_ns['display_svg'] = display_svg
267 shell.user_ns_hidden['display_svg'] = display_svg
268 user_ns['getfigs'] = getfigs
282 user_ns['getfigs'] = getfigs
269 shell.user_ns_hidden['getfigs'] = getfigs
283 shell.user_ns_hidden['getfigs'] = getfigs
270
284
@@ -10,12 +10,46 b' import sys'
10
10
11 # Third-party imports
11 # Third-party imports
12 import matplotlib
12 import matplotlib
13 from matplotlib.backends.backend_svg import new_figure_manager
13 from matplotlib.backends.backend_agg import new_figure_manager
14 from matplotlib._pylab_helpers import Gcf
14 from matplotlib._pylab_helpers import Gcf
15
15
16 # Local imports.
16 # Local imports.
17 from IPython.config.configurable import SingletonConfigurable
17 from IPython.core.displaypub import publish_display_data
18 from IPython.core.displaypub import publish_display_data
18 from IPython.lib.pylabtools import figure_to_svg
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 # Functions
55 # Functions
@@ -32,7 +66,7 b' def show(close=True):'
32 removed from the internal list of figures.
66 removed from the internal list of figures.
33 """
67 """
34 for figure_manager in Gcf.get_all_fig_managers():
68 for figure_manager in Gcf.get_all_fig_managers():
35 send_svg_figure(figure_manager.canvas.figure)
69 send_figure(figure_manager.canvas.figure)
36 if close:
70 if close:
37 matplotlib.pyplot.close('all')
71 matplotlib.pyplot.close('all')
38
72
@@ -50,8 +84,8 b' def draw_if_interactive():'
50 show._draw_called = True
84 show._draw_called = True
51
85
52
86
53 def flush_svg():
87 def flush_figures():
54 """Call show, close all open figures, sending all SVG images.
88 """Call show, close all open figures, sending all figure images.
55
89
56 This is meant to be called automatically and will call show() if, during
90 This is meant to be called automatically and will call show() if, during
57 prior code execution, there had been any calls to draw_if_interactive.
91 prior code execution, there had been any calls to draw_if_interactive.
@@ -61,21 +95,23 b' def flush_svg():'
61 show._draw_called = False
95 show._draw_called = False
62
96
63
97
64 def send_svg_figure(fig):
98 def send_figure(fig):
65 """Draw the current figure and send it as an SVG payload.
99 """Draw the current figure and send it as a PNG payload.
66 """
100 """
67 # For an empty figure, don't even bother calling figure_to_svg, to avoid
101 # For an empty figure, don't even bother calling figure_to_svg, to avoid
68 # big blank spaces in the qt console
102 # big blank spaces in the qt console
69 if not fig.axes:
103 if not fig.axes:
70 return
104 return
71
105 fmt = InlineBackendConfig.instance().figure_format
72 svg = figure_to_svg(fig)
106 data = print_figure(fig, fmt)
107 mimetypes = { 'png' : 'image/png', 'svg' : 'image/svg+xml' }
108 mime = mimetypes[fmt]
73 # flush text streams before sending figures, helps a little with output
109 # flush text streams before sending figures, helps a little with output
74 # synchronization in the console (though it's a bandaid, not a real sln)
110 # synchronization in the console (though it's a bandaid, not a real sln)
75 sys.stdout.flush(); sys.stderr.flush()
111 sys.stdout.flush(); sys.stderr.flush()
76 publish_display_data(
112 publish_display_data(
77 'IPython.zmq.pylab.backend_inline.send_svg_figure',
113 'IPython.zmq.pylab.backend_inline.send_figure',
78 'Matplotlib Plot',
114 'Matplotlib Plot',
79 {'image/svg+xml' : svg}
115 {mime : data}
80 )
116 )
81
117
General Comments 0
You need to be logged in to leave comments. Login now