Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

add InlineBackendConfig

The inline backend now has preliminary config support for rc and figure format.
  • Loading branch information...
commit 872ffeac28f3b1b87161d14b5c14d86202b2c0da 1 parent fe759a8
@minrk authored
Showing with 94 additions and 43 deletions.
  1. +47 −32 IPython/lib/pylabtools.py
  2. +47 −11 IPython/zmq/pylab/backend_inline.py
View
79 IPython/lib/pylabtools.py
@@ -33,6 +33,7 @@
'osx': 'MacOSX',
'inline' : 'module://IPython.zmq.pylab.backend_inline'}
+
#-----------------------------------------------------------------------------
# Matplotlib utilities
#-----------------------------------------------------------------------------
@@ -76,8 +77,8 @@ def figsize(sizex, sizey):
matplotlib.rcParams['figure.figsize'] = [sizex, sizey]
-def figure_to_svg(fig):
- """Convert a figure to svg for inline display."""
+def print_figure(fig, fmt='png'):
+ """Convert a figure to svg or png for inline display."""
# When there's an empty figure, we shouldn't return anything, otherwise we
# get big blank areas in the qt console.
if not fig.axes:
@@ -89,12 +90,15 @@ def figure_to_svg(fig):
fig.set_edgecolor('white')
try:
string_io = StringIO()
- fig.canvas.print_figure(string_io, format='svg')
- svg = string_io.getvalue()
+ # use 72 dpi to match QTConsole's dpi
+ fig.canvas.print_figure(string_io, format=fmt, dpi=72)
+ data = string_io.getvalue()
finally:
fig.set_facecolor(fc)
fig.set_edgecolor(ec)
- return svg
+ if fmt == 'png':
+ data = data.encode('base64')
+ return data
# We need a little factory function here to create the closure where
@@ -139,6 +143,29 @@ def mpl_execfile(fname,*where,**kw):
return mpl_execfile
+def select_figure_format(shell, fmt):
+ """Select figure format for inline backend, either 'png' or 'svg'.
+
+ Using this method ensures only one figure format is active at a time.
+ """
+ from matplotlib.figure import Figure
+ from IPython.zmq.pylab import backend_inline
+
+ svg_formatter = shell.display_formatter.formatters['image/svg+xml']
+ png_formatter = shell.display_formatter.formatters['image/png']
+
+ if fmt=='png':
+ svg_formatter.type_printers.pop(Figure, None)
+ png_formatter.for_type(Figure, lambda fig: print_figure(fig, 'png'))
+ elif fmt=='svg':
+ png_formatter.type_printers.pop(Figure, None)
+ svg_formatter.for_type(Figure, lambda fig: print_figure(fig, 'svg'))
+ else:
+ raise ValueError("supported formats are: 'png', 'svg', not %r"%fmt)
+
+ # set the format to be used in the backend()
+ backend_inline._figure_format = fmt
+
#-----------------------------------------------------------------------------
# Code for initializing matplotlib and importing pylab
#-----------------------------------------------------------------------------
@@ -199,7 +226,6 @@ def activate_matplotlib(backend):
# For this, we wrap it into a decorator which adds a 'called' flag.
pylab.draw_if_interactive = flag_calls(pylab.draw_if_interactive)
-
def import_pylab(user_ns, backend, import_all=True, shell=None):
"""Import the standard pylab symbols into user_ns."""
@@ -219,43 +245,32 @@ def import_pylab(user_ns, backend, import_all=True, shell=None):
# If using our svg payload backend, register the post-execution
# function that will pick up the results for display. This can only be
# done with access to the real shell object.
+ #
+ from IPython.zmq.pylab.backend_inline import InlineBackendConfig
+
+ cfg = InlineBackendConfig.instance(config=shell.config)
+ cfg.shell = shell
+
if backend == backends['inline']:
- from IPython.zmq.pylab.backend_inline import flush_svg
+ from IPython.zmq.pylab.backend_inline import flush_figures
from matplotlib import pyplot
- shell.register_post_execute(flush_svg)
- # The typical default figure size is too large for inline use,
- # so we shrink the figure size to 6x4, and tweak fonts to
- # make that fit. This is configurable via Global.pylab_inline_rc,
- # or rather it will be once the zmq kernel is hooked up to
- # the config system.
-
- default_rc = {
- 'figure.figsize': (6.0,4.0),
- # 12pt labels get cutoff on 6x4 logplots, so use 10pt.
- 'font.size': 10,
- # 10pt still needs a little more room on the xlabel:
- 'figure.subplot.bottom' : .125
- }
- rc = getattr(shell.config.Global, 'pylab_inline_rc', default_rc)
- pyplot.rcParams.update(rc)
- shell.config.Global.pylab_inline_rc = rc
+ shell.register_post_execute(flush_figures)
+ # load inline_rc
+ pyplot.rcParams.update(cfg.rc)
# Add 'figsize' to pyplot and to the user's namespace
user_ns['figsize'] = pyplot.figsize = figsize
shell.user_ns_hidden['figsize'] = figsize
+ # Setup the default figure format
+ fmt = cfg.figure_format
+ select_figure_format(shell, fmt)
+
# The old pastefig function has been replaced by display
- # Always add this svg formatter so display works.
- from IPython.core.display import display, display_svg
- svg_formatter = shell.display_formatter.formatters['image/svg+xml']
- svg_formatter.for_type_by_name(
- 'matplotlib.figure','Figure',figure_to_svg
- )
+ from IPython.core.display import display
# Add display and display_png to the user's namespace
user_ns['display'] = display
shell.user_ns_hidden['display'] = display
- user_ns['display_svg'] = display_svg
- shell.user_ns_hidden['display_svg'] = display_svg
user_ns['getfigs'] = getfigs
shell.user_ns_hidden['getfigs'] = getfigs
View
58 IPython/zmq/pylab/backend_inline.py
@@ -10,12 +10,46 @@
# Third-party imports
import matplotlib
-from matplotlib.backends.backend_svg import new_figure_manager
+from matplotlib.backends.backend_agg import new_figure_manager
from matplotlib._pylab_helpers import Gcf
# Local imports.
+from IPython.config.configurable import SingletonConfigurable
from IPython.core.displaypub import publish_display_data
-from IPython.lib.pylabtools import figure_to_svg
+from IPython.lib.pylabtools import print_figure, select_figure_format
+from IPython.utils.traitlets import Dict, Instance, CaselessStrEnum
+#-----------------------------------------------------------------------------
+# Configurable for inline backend options
+#-----------------------------------------------------------------------------
+
+class InlineBackendConfig(SingletonConfigurable):
+ """An object to store configuration of the inline backend."""
+
+ # The typical default figure size is too large for inline use,
+ # so we shrink the figure size to 6x4, and tweak fonts to
+ # make that fit. This is configurable via Global.pylab_inline_rc,
+ # or rather it will be once the zmq kernel is hooked up to
+ # the config system.
+ rc = Dict({'figure.figsize': (6.0,4.0),
+ # 12pt labels get cutoff on 6x4 logplots, so use 10pt.
+ 'font.size': 10,
+ # 10pt still needs a little more room on the xlabel:
+ 'figure.subplot.bottom' : .125
+ }, config=True,
+ help="""Subset of matplotlib rcParams that should be different for the
+ inline backend."""
+ )
+ figure_format = CaselessStrEnum(['svg', 'png'], default_value='png', config=True,
+ help="The image format for figures with the inline backend.")
+
+ def _format_changed(self, name, old, new):
+ if self.shell is None:
+ return
+ else:
+ select_figure_format(self.shell, new)
+
+ shell = Instance('IPython.core.interactiveshell.InteractiveShellABC')
+
#-----------------------------------------------------------------------------
# Functions
@@ -32,7 +66,7 @@ def show(close=True):
removed from the internal list of figures.
"""
for figure_manager in Gcf.get_all_fig_managers():
- send_svg_figure(figure_manager.canvas.figure)
+ send_figure(figure_manager.canvas.figure)
if close:
matplotlib.pyplot.close('all')
@@ -50,8 +84,8 @@ def draw_if_interactive():
show._draw_called = True
-def flush_svg():
- """Call show, close all open figures, sending all SVG images.
+def flush_figures():
+ """Call show, close all open figures, sending all figure images.
This is meant to be called automatically and will call show() if, during
prior code execution, there had been any calls to draw_if_interactive.
@@ -61,21 +95,23 @@ def flush_svg():
show._draw_called = False
-def send_svg_figure(fig):
- """Draw the current figure and send it as an SVG payload.
+def send_figure(fig):
+ """Draw the current figure and send it as a PNG payload.
"""
# For an empty figure, don't even bother calling figure_to_svg, to avoid
# big blank spaces in the qt console
if not fig.axes:
return
-
- svg = figure_to_svg(fig)
+ fmt = InlineBackendConfig.instance().figure_format
+ data = print_figure(fig, fmt)
+ mimetypes = { 'png' : 'image/png', 'svg' : 'image/svg+xml' }
+ mime = mimetypes[fmt]
# flush text streams before sending figures, helps a little with output
# synchronization in the console (though it's a bandaid, not a real sln)
sys.stdout.flush(); sys.stderr.flush()
publish_display_data(
- 'IPython.zmq.pylab.backend_inline.send_svg_figure',
+ 'IPython.zmq.pylab.backend_inline.send_figure',
'Matplotlib Plot',
- {'image/svg+xml' : svg}
+ {mime : data}
)
Please sign in to comment.
Something went wrong with that request. Please try again.