##// END OF EJS Templates
Merge pull request #3205 from minrk/traitletsargs...
Merge pull request #3205 from minrk/traitletsargs add ignored *args to HasTraits constructor

File last commit:

r9372:37f32253
r10374:46e23e9f merge
Show More
pylabtools.py
370 lines | 12.6 KiB | text/x-python | PythonLexer
Fernando Perez
First semi-complete support for -pylab and %pylab....
r2363 # -*- coding: utf-8 -*-
"""Pylab (matplotlib) support utilities.
Authors
-------
Brian Granger
Updating terminal GUI support to use guisupport.py for qt4/wx.
r2918
* Fernando Perez.
* Brian Granger
Fernando Perez
First semi-complete support for -pylab and %pylab....
r2363 """
#-----------------------------------------------------------------------------
Matthias BUSSONNIER
update copyright to 2011/20xx-2011...
r5390 # Copyright (C) 2009-2011 The IPython Development Team
Fernando Perez
First semi-complete support for -pylab and %pylab....
r2363 #
# Distributed under the terms of the BSD License. The full license is in
# the file COPYING, distributed as part of this software.
#-----------------------------------------------------------------------------
Brian Granger
Work to address the review comments on Fernando's branch....
r2498
Fernando Perez
First semi-complete support for -pylab and %pylab....
r2363 #-----------------------------------------------------------------------------
# Imports
#-----------------------------------------------------------------------------
Brian Granger
Work to address the review comments on Fernando's branch....
r2498
MinRK
flush messages printed during startup...
r5361 import sys
Grahame Bowland
Make PNG images in the Qt console work in Python 3.
r4773 from io import BytesIO
Brian Granger
Lots of work on the display system, focused on pylab stuff....
r3280
Brian Granger
Work to address the review comments on Fernando's branch....
r2498 from IPython.utils.decorators import flag_calls
Fernando Perez
First semi-complete support for -pylab and %pylab....
r2363
Fernando Perez
Add support for simultaneous interactive and inline matplotlib plots....
r2987 # If user specifies a GUI, that dictates the backend, otherwise we read the
# user's mpl default from the mpl rc structure
backends = {'tk': 'TkAgg',
'gtk': 'GTKAgg',
'wx': 'WXAgg',
'qt': 'Qt4Agg', # qt3 not supported
'qt4': 'Qt4Agg',
MinRK
add 'osx' to known pylab backends, fix pylab mode with MacOSX backend...
r3462 'osx': 'MacOSX',
MinRK
mv IPython.zmq to IPython.kernel.zmq
r9372 'inline' : 'module://IPython.kernel.zmq.pylab.backend_inline'}
Fernando Perez
Add support for simultaneous interactive and inline matplotlib plots....
r2987
Fernando Perez
Fix support for raw GTK and WX matplotlib backends....
r3902 # We also need a reverse backends2guis mapping that will properly choose which
# GUI support to activate based on the desired matplotlib backend. For the
# most part it's just a reverse of the above dict, but we also need to add a
# few others that map to the same GUI manually:
backend2gui = dict(zip(backends.values(), backends.keys()))
# In the reverse mapping, there are a few extra valid matplotlib backends that
# map to the same GUI support
backend2gui['GTK'] = backend2gui['GTKCairo'] = 'gtk'
backend2gui['WX'] = 'wx'
backend2gui['CocoaAgg'] = 'osx'
Fernando Perez
First semi-complete support for -pylab and %pylab....
r2363 #-----------------------------------------------------------------------------
Brian Granger
Lots of work on the display system, focused on pylab stuff....
r3280 # Matplotlib utilities
#-----------------------------------------------------------------------------
Brian Granger
Final work on display system....
r3288
def getfigs(*fig_nums):
"""Get a list of matplotlib figures by figure numbers.
If no arguments are given, all available figures are returned. If the
argument list contains references to invalid figures, a warning is printed
but the function continues pasting further figures.
Parameters
----------
figs : tuple
A tuple of ints giving the figure numbers of the figures to return.
"""
from matplotlib._pylab_helpers import Gcf
if not fig_nums:
fig_managers = Gcf.get_all_fig_managers()
return [fm.canvas.figure for fm in fig_managers]
else:
figs = []
for num in fig_nums:
f = Gcf.figs.get(num)
if f is None:
print('Warning: figure %s not available.' % num)
Brian Granger
Renaming the special methods of the formatters....
r3878 else:
figs.append(f.canvas.figure)
Brian Granger
Final work on display system....
r3288 return figs
Brian Granger
Lots of work on the display system, focused on pylab stuff....
r3280 def figsize(sizex, sizey):
"""Set the default figure size to be [sizex, sizey].
This is just an easy to remember, convenience wrapper that sets::
matplotlib.rcParams['figure.figsize'] = [sizex, sizey]
"""
import matplotlib
matplotlib.rcParams['figure.figsize'] = [sizex, sizey]
MinRK
add InlineBackendConfig...
r3973 def print_figure(fig, fmt='png'):
"""Convert a figure to svg or png for inline display."""
Fernando Perez
Do not generate output for empty figures in Qt console....
r3731 # When there's an empty figure, we shouldn't return anything, otherwise we
# get big blank areas in the qt console.
Fernando Perez
Display figures with no axes but lines, which are also valid.
r5732 if not fig.axes and not fig.lines:
Fernando Perez
Do not generate output for empty figures in Qt console....
r3731 return
Brian Granger
Lots of work on the display system, focused on pylab stuff....
r3280 fc = fig.get_facecolor()
ec = fig.get_edgecolor()
Takafumi Arakaki
Make BG color of inline plot configurable...
r7798 bytes_io = BytesIO()
fig.canvas.print_figure(bytes_io, format=fmt, bbox_inches='tight',
facecolor=fc, edgecolor=ec)
data = bytes_io.getvalue()
MinRK
add InlineBackendConfig...
r3973 return data
Brian Granger
Lots of work on the display system, focused on pylab stuff....
r3280
# We need a little factory function here to create the closure where
# safe_execfile can live.
def mpl_runner(safe_execfile):
"""Factory to return a matplotlib-enabled runner for %run.
Parameters
----------
safe_execfile : function
This must be a function with the same interface as the
:meth:`safe_execfile` method of IPython.
Returns
-------
A function suitable for use as the ``runner`` argument of the %run magic
function.
"""
def mpl_execfile(fname,*where,**kw):
"""matplotlib-aware wrapper around safe_execfile.
Its interface is identical to that of the :func:`execfile` builtin.
This is ultimately a call to execfile(), but wrapped in safeties to
properly handle interactive rendering."""
import matplotlib
import matplotlib.pylab as pylab
#print '*** Matplotlib runner ***' # dbg
# turn off rendering until end of script
is_interactive = matplotlib.rcParams['interactive']
matplotlib.interactive(False)
safe_execfile(fname,*where,**kw)
matplotlib.interactive(is_interactive)
# make rendering call now, if the user tried to do it
if pylab.draw_if_interactive.called:
pylab.draw()
pylab.draw_if_interactive.called = False
return mpl_execfile
MinRK
add InlineBackendConfig...
r3973 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
MinRK
mv IPython.zmq to IPython.kernel.zmq
r9372 from IPython.kernel.zmq.pylab import backend_inline
MinRK
add InlineBackendConfig...
r3973
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
Brian Granger
Lots of work on the display system, focused on pylab stuff....
r3280 #-----------------------------------------------------------------------------
# Code for initializing matplotlib and importing pylab
Fernando Perez
First semi-complete support for -pylab and %pylab....
r2363 #-----------------------------------------------------------------------------
Ryan May
Implement bare %pylab switching back to appropriate GUI.
r7965 def find_gui_and_backend(gui=None, gui_select=None):
Brian Granger
Initial GUI support in kernel.
r2868 """Given a gui string return the gui and mpl backend.
Fernando Perez
First semi-complete support for -pylab and %pylab....
r2363
Parameters
----------
Brian Granger
Initial GUI support in kernel.
r2868 gui : str
Fernando Perez
Renamed 'payload-svg' matplotlib backend to 'inline'.
r2991 Can be one of ('tk','gtk','wx','qt','qt4','inline').
Ryan May
Implement bare %pylab switching back to appropriate GUI.
r7965 gui_select : str
Can be one of ('tk','gtk','wx','qt','qt4','inline').
This is any gui already selected by the shell.
Fernando Perez
First semi-complete support for -pylab and %pylab....
r2363
Returns
-------
Brian Granger
Initial GUI support in kernel.
r2868 A tuple of (gui, backend) where backend is one of ('TkAgg','GTKAgg',
MinRK
mv IPython.zmq to IPython.kernel.zmq
r9372 'WXAgg','Qt4Agg','module://IPython.kernel.zmq.pylab.backend_inline').
Fernando Perez
First semi-complete support for -pylab and %pylab....
r2363 """
import matplotlib
MinRK
quiet error messages instead of tracebacks in %pylab/%gui...
r5162 if gui and gui != 'auto':
Fernando Perez
First semi-complete support for -pylab and %pylab....
r2363 # select backend based on requested gui
Fernando Perez
Add support for simultaneous interactive and inline matplotlib plots....
r2987 backend = backends[gui]
Fernando Perez
First semi-complete support for -pylab and %pylab....
r2363 else:
backend = matplotlib.rcParams['backend']
# In this case, we need to find what the appropriate gui selection call
# should be for IPython, so we can activate inputhook accordingly
Fernando Perez
Fix support for raw GTK and WX matplotlib backends....
r3902 gui = backend2gui.get(backend, None)
Ryan May
Implement bare %pylab switching back to appropriate GUI.
r7965
# If we have already had a gui active, we need it and inline are the
# ones allowed.
if gui_select and gui != gui_select:
gui = gui_select
backend = backends[gui]
Brian Granger
Initial GUI support in kernel.
r2868 return gui, backend
Fernando Perez
First semi-complete support for -pylab and %pylab....
r2363
Brian Granger
Initial GUI support in kernel.
r2868
def activate_matplotlib(backend):
"""Activate the given backend and set interactive to True."""
import matplotlib
matplotlib.interactive(True)
Brian Granger
GUI support for wx, qt and tk.
r2872
Ryan May
Make use of matplotlib's switch_backend()...
r7939 # Matplotlib had a bug where even switch_backend could not force
# the rcParam to update. This needs to be set *before* the module
# magic of switch_backend().
matplotlib.rcParams['backend'] = backend
import matplotlib.pyplot
matplotlib.pyplot.switch_backend(backend)
Brian Granger
GUI support for wx, qt and tk.
r2872 # This must be imported last in the matplotlib series, after
# backend/interactivity choices have been made
Fernando Perez
First semi-complete support for -pylab and %pylab....
r2363 import matplotlib.pylab as pylab
Brian Granger
GUI support for wx, qt and tk.
r2872 pylab.show._needmain = False
# We need to detect at runtime whether show() is called by the user.
# For this, we wrap it into a decorator which adds a 'called' flag.
pylab.draw_if_interactive = flag_calls(pylab.draw_if_interactive)
Fernando Perez
First semi-complete support for -pylab and %pylab....
r2363
Fernando Perez
Refactor gui/pylab integration to eliminate code duplication....
r5469
def import_pylab(user_ns, import_all=True):
Brian Granger
Initial GUI support in kernel.
r2868 """Import the standard pylab symbols into user_ns."""
Fernando Perez
First semi-complete support for -pylab and %pylab....
r2363
# Import numpy as np/pyplot as plt are conventions we're trying to
# somewhat standardize on. Making them available to users by default
Fernando Perez
Fix name pollution of interactive namespace in pylab mode....
r3195 # will greatly help this.
s = ("import numpy\n"
Fernando Perez
First semi-complete support for -pylab and %pylab....
r2363 "import matplotlib\n"
"from matplotlib import pylab, mlab, pyplot\n"
"np = numpy\n"
"plt = pyplot\n"
Fernando Perez
Fix name pollution of interactive namespace in pylab mode....
r3195 )
exec s in user_ns
Fernando Perez
First semi-complete support for -pylab and %pylab....
r2363
if import_all:
Fernando Perez
Fix name pollution of interactive namespace in pylab mode....
r3195 s = ("from matplotlib.pylab import *\n"
"from numpy import *\n")
exec s in user_ns
Fernando Perez
Fix critical bug with pylab support inadvertently introduced in #648....
r5468
Fernando Perez
Refactor gui/pylab integration to eliminate code duplication....
r5469
Fernando Perez
Fix inline backend logic and avoid tests if mpl not available.
r5474 def configure_inline_support(shell, backend, user_ns=None):
Fernando Perez
Refactor gui/pylab integration to eliminate code duplication....
r5469 """Configure an IPython shell object for matplotlib use.
Parameters
----------
shell : InteractiveShell instance
Fernando Perez
Fix inline backend logic and avoid tests if mpl not available.
r5474 backend : matplotlib backend
Fernando Perez
Refactor gui/pylab integration to eliminate code duplication....
r5469 user_ns : dict
A namespace where all configured variables will be placed. If not given,
the `user_ns` attribute of the shell object is used.
"""
# 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.
Fernando Perez
Fix inline backend logic and avoid tests if mpl not available.
r5474 # Note: if we can't load the inline backend, then there's no point
# continuing (such as in terminal-only shells in environments without
# zeromq available).
try:
MinRK
mv IPython.zmq to IPython.kernel.zmq
r9372 from IPython.kernel.zmq.pylab.backend_inline import InlineBackend
Fernando Perez
Fix inline backend logic and avoid tests if mpl not available.
r5474 except ImportError:
return
Ryan May
Add code to de-init the inline backend....
r7940 from matplotlib import pyplot
Fernando Perez
Fix inline backend logic and avoid tests if mpl not available.
r5474
user_ns = shell.user_ns if user_ns is None else user_ns
Fernando Perez
Refactor gui/pylab integration to eliminate code duplication....
r5469 cfg = InlineBackend.instance(config=shell.config)
cfg.shell = shell
if cfg not in shell.configurables:
shell.configurables.append(cfg)
Fernando Perez
Fix inline backend logic and avoid tests if mpl not available.
r5474 if backend == backends['inline']:
MinRK
mv IPython.zmq to IPython.kernel.zmq
r9372 from IPython.kernel.zmq.pylab.backend_inline import flush_figures
Fernando Perez
Fix inline backend logic and avoid tests if mpl not available.
r5474 shell.register_post_execute(flush_figures)
Ryan May
Add code to de-init the inline backend....
r7940
# Save rcParams that will be overwrittern
shell._saved_rcParams = dict()
for k in cfg.rc:
shell._saved_rcParams[k] = pyplot.rcParams[k]
Fernando Perez
Fix inline backend logic and avoid tests if mpl not available.
r5474 # load inline_rc
pyplot.rcParams.update(cfg.rc)
# Add 'figsize' to pyplot and to the user's namespace
user_ns['figsize'] = pyplot.figsize = figsize
Ryan May
Add code to de-init the inline backend....
r7940 else:
MinRK
mv IPython.zmq to IPython.kernel.zmq
r9372 from IPython.kernel.zmq.pylab.backend_inline import flush_figures
Ryan May
Add code to de-init the inline backend....
r7940 if flush_figures in shell._post_execute:
shell._post_execute.pop(flush_figures)
if hasattr(shell, '_saved_rcParams'):
pyplot.rcParams.update(shell._saved_rcParams)
del shell._saved_rcParams
Fernando Perez
Refactor gui/pylab integration to eliminate code duplication....
r5469
# Setup the default figure format
fmt = cfg.figure_format
select_figure_format(shell, fmt)
# The old pastefig function has been replaced by display
from IPython.core.display import display
# Add display and getfigs to the user's namespace
user_ns['display'] = display
user_ns['getfigs'] = getfigs
Fernando Perez
First semi-complete support for -pylab and %pylab....
r2363
Brian Granger
Initial GUI support in kernel.
r2868
Aaron Meurer
Add welcome_message option to enable_pylab...
r8229 def pylab_activate(user_ns, gui=None, import_all=True, shell=None, welcome_message=False):
Brian Granger
Initial GUI support in kernel.
r2868 """Activate pylab mode in the user's namespace.
Loads and initializes numpy, matplotlib and friends for interactive use.
Parameters
----------
user_ns : dict
Namespace where the imports will occur.
gui : optional, string
A valid gui name following the conventions of the %gui magic.
import_all : optional, boolean
If true, an 'import *' is done from numpy and pylab.
Aaron Meurer
Add welcome_message option to enable_pylab...
r8229 welcome_message : optional, boolean
If true, print a welcome message about pylab, which includes the backend
being used.
Brian Granger
Initial GUI support in kernel.
r2868 Returns
-------
The actual gui used (if not given as input, it was obtained from matplotlib
itself, and will be needed next to configure IPython's gui integration.
"""
Ryan May
Implement bare %pylab switching back to appropriate GUI.
r7965 pylab_gui_select = shell.pylab_gui_select if shell is not None else None
# Try to find the appropriate gui and backend for the settings
gui, backend = find_gui_and_backend(gui, pylab_gui_select)
if shell is not None and gui != 'inline':
# If we have our first gui selection, store it
if pylab_gui_select is None:
shell.pylab_gui_select = gui
# Otherwise if they are different
elif gui != pylab_gui_select:
print ('Warning: Cannot change to a different GUI toolkit: %s.'
' Using %s instead.' % (gui, pylab_gui_select))
gui, backend = find_gui_and_backend(pylab_gui_select)
Brian Granger
Initial GUI support in kernel.
r2868 activate_matplotlib(backend)
Fernando Perez
Refactor gui/pylab integration to eliminate code duplication....
r5469 import_pylab(user_ns, import_all)
Fernando Perez
Avoid calling inline config if no shell - per @minrk feedback on #1052
r5475 if shell is not None:
configure_inline_support(shell, backend, user_ns)
Aaron Meurer
Add welcome_message option to enable_pylab...
r8229 if welcome_message:
print """
Fernando Perez
Small fix to info message when pylab starts.
r2364 Welcome to pylab, a matplotlib-based Python environment [backend: %s].
Fernando Perez
First semi-complete support for -pylab and %pylab....
r2363 For more information, type 'help(pylab)'.""" % backend
Aaron Meurer
Add welcome_message option to enable_pylab...
r8229 # flush stdout, just to be safe
sys.stdout.flush()
Fernando Perez
First semi-complete support for -pylab and %pylab....
r2363
Aaron Meurer
Add welcome_message option to enable_pylab...
r8229 return gui