Source code for scitools.easyviz.matplotlib_

"""
This backend uses the Python 2D plotting library Matplotlib (available from
http://matplotlib.sourceforge.net). To use this backend, one can run a
script somefile.py like

  python somefile.py --SCITOOLS_easyviz_backend matplotlib

or one can specify the backend in the SciTools configuration file
scitools.cfg under the [easyviz] section

  [easyviz]
  backend = matplotlib

and then

  from scitools.std import *

or if just easyviz is needed

  from scitools.easyviz import *

REQUIREMENTS:

Matplotlib

"""
from __future__ import division

from common import *
from scitools.numpyutils import floor, linspace, array
from scitools.globaldata import DEBUG, VERBOSE
from scitools.misc import test_if_module_exists
from misc import _update_from_config_file

test_if_module_exists('matplotlib', msg='You need to install the Matplotlib package.', abort=False)

import matplotlib
import matplotlib.colors
# Override values from the matplotlib configuration file with values
# from scitools.cfg before importing pylab
_update_from_config_file(matplotlib.rcParams, section='matplotlib')
matplotlib.interactive(True)
from matplotlib.font_manager import fontManager, FontProperties
#import pylab
import matplotlib.pyplot as pylab
import re


[docs]class MatplotlibBackend(BaseClass):
[docs] def __init__(self): BaseClass.__init__(self) self._init()
def _init(self, *args, **kwargs): """Perform initialization that is special for this backend.""" self.figure(self.getp('curfig')) # conversion tables for format strings: self._markers = { '': '', # no marker '.': '.', # dot 'o': 'o', # circle 'x': 'x', # cross '+': '+', # plus sign '*': '+', # asterisk --> plus 's': 's', # square, 'd': 'd', # diamond, 'v': 'v', # triangle (down), '^': '^', # triangle (up), '<': '<', # triangle (left), '>': '>', # triangle (right), 'p': 'p', # pentagram, 'h': 'h', # hexagram, } # convert table for colorbar location: self._colorbar_locations = { 'North': None, 'South': None, 'East': None, 'West': None, 'NorthOutside': None, 'SouthOutside': None, 'EastOutside': None, 'WestOutside': None, } if DEBUG: print "Setting backend standard variables" for disp in 'self._markers'.split(): print disp, eval(disp) def _set_scale(self, ax): """Set linear or logarithmic (base 10) axis scale.""" if DEBUG: print "Setting scales" scale = ax.getp('scale') if scale == 'loglog': # use logarithmic scale on both x- and y-axis self._g.gca().set_xscale('log') self._g.gca().set_yscale('log') elif scale == 'logx': # use logarithmic scale on x-axis and linear scale on y-axis self._g.gca().set_xscale('log') self._g.gca().set_yscale('linear') elif scale == 'logy': # use linear scale on x-axis and logarithmic scale on y-axis self._g.gca().set_xscale('linear') self._g.gca().set_yscale('log') elif scale == 'linear': # use linear scale on both x- and y-axis #self._g.gca().set_xscale('linear') #self._g.gca().set_yscale('linear') pass def _set_labels(self, ax): """Add text labels for x-, y-, and z-axis.""" if DEBUG: print "Setting labels" xlabel = ax.getp('xlabel') ylabel = ax.getp('ylabel') zlabel = ax.getp('zlabel') xlabel = self._fix_latex(xlabel) ylabel = self._fix_latex(ylabel) zlabel = self._fix_latex(zlabel) if xlabel: # add a text label on x-axis self._g.xlabel(xlabel) if ylabel: # add a text label on y-axis self._g.ylabel(ylabel, rotation='vertical') if zlabel: # add a text label on z-axis pass def _set_title(self, ax): """Add a title at the top of the axis.""" if DEBUG: print "Setting title" title = ax.getp('title') # The title can be a mix of math and text, leave this # to the user #title = self._fix_latex(title) if title: self._g.title(title) def _set_limits(self, ax): """Set axis limits in x, y, and z direction.""" if DEBUG: print "Setting axis limits" mode = ax.getp('mode') if mode == 'auto': # let plotting package set 'nice' axis limits in the x, y, # and z direction. If this is not automated in the plotting # package, one can use the following limits: #xmin, xmax, ymin, ymax, zmin, zmax = ax.get_limits() #self._g.axis('auto') pass elif mode == 'manual': # (some) axis limits are frozen xmin = ax.getp('xmin') xmax = ax.getp('xmax') if xmin is not None and xmax is not None: # set x-axis limits self._g.gca().set_xlim(xmin, xmax) else: # let plotting package set x-axis limits or use #xmin, xmax = ax.getp('xlim') pass ymin = ax.getp('ymin') ymax = ax.getp('ymax') if ymin is not None and ymax is not None: # set y-axis limits self._g.gca().set_ylim(ymin, ymax) else: # let plotting package set y-axis limits or use #ymin, ymax = ax.getp('ylim') pass zmin = ax.getp('zmin') zmax = ax.getp('zmax') if zmin is not None and zmax is not None: # set z-axis limits pass else: # let plotting package set z-axis limits or use #zmin, zmax = ax.getp('zlim') pass elif mode == 'tight': # set the limits on the axis to the range of the data. If # this is not automated in the plotting package, one can # use the following limits: #xmin, xmax, ymin, ymax, zmin, zmax = ax.get_limits() self._g.axis('tight') elif mode == 'fill': # not sure about this pass def _set_position(self, ax): """Set axes position.""" rect = ax.getp('viewport') if rect: # axes position is defined. In Matlab rect is defined as # [left,bottom,width,height], where the four parameters are # location values between 0 and 1 ((0,0) is the lower-left # corner and (1,1) is the upper-right corner). # NOTE: This can be different in the plotting package. pass def _set_daspect(self, ax): """Set data aspect ratio.""" if ax.getp('daspectmode') == 'manual': dar = ax.getp('daspect') # dar is a list (len(dar) is 3). xmin = ax.getp('xmin') xmax = ax.getp('xmax') ymin = ax.getp('ymin') ymax = ax.getp('ymax') r = float(xmax-xmin)/(ymax-ymin) self._g.gca().set_aspect(r*dar[0]) elif ax.getp('daspectmode') == 'equal': self._g.gca().set_aspect('equal') else: # daspectmode is 'auto'. Plotting package handles data # aspect ratio automatically. self._g.gca().set_aspect('auto') def _set_axis_method(self, ax): method = ax.getp('method') if method == 'equal': # tick mark increments on the x-, y-, and z-axis should # be equal in size. self._g.axis('equal') elif method == 'image': # same effect as axis('equal') and axis('tight') self._g.axis('image') elif method == 'square': # make the axis box square in size pass elif method == 'normal': # full size axis box pass elif method == 'vis3d': # freeze data aspect ratio when rotating 3D objects pass def _set_coordinate_system(self, ax): """ Use either the default Cartesian coordinate system or a matrix coordinate system. """ direction = ax.getp('direction') if direction == 'ij': # Use matrix coordinates. The origin of the coordinate # system is the upper-left corner. The i-axis should be # vertical and numbered from top to bottom, while the j-axis # should be horizontal and numbered from left to right. pass elif direction == 'xy': # use the default Cartesian axes form. The origin is at the # lower-left corner. The x-axis is vertical and numbered # from left to right, while the y-axis is vertical and # numbered from bottom to top. pass def _set_box(self, ax): """Turn box around axes boundary on or off.""" if DEBUG: print "Setting box" if ax.getp('box'): # display box self._g.box(on=True) else: # do not display box self._g.box(on=False) def _set_grid(self, ax): """Turn grid lines on or off.""" if DEBUG: print "Setting grid" if self._mpl3D: # Do not call self._g.grid for 3D surf plots return if ax.getp('grid'): # turn grid lines on self._g.grid(b=True) else: # turn grid lines off self._g.grid(b=False) def _set_hidden_line_removal(self, ax): """Turn on/off hidden line removal for meshes.""" if DEBUG: print "Setting hidden line removal" if ax.getp('hidden'): # turn hidden line removal on pass else: # turn hidden line removal off pass def _set_colorbar(self, ax): """Add a colorbar to the axis.""" if DEBUG: print "Setting colorbar" if self._mpl3D: # Do not call self._g.grid for 3D surf plots return cbar = ax.getp('colorbar') if cbar.getp('visible'): # turn on colorbar cbar_title = cbar.getp('cbtitle') cbar_location = self._colorbar_locations[cbar.getp('cblocation')] cbar2 = self._g.colorbar(orientation='vertical') if cbar_title: cbar2.set_label(cbar_title) #pos = [0.78, 0.1, 0.12, 0.8] #cbar2.ax.set_position(pos) #print cbar2.ax.get_position() else: # turn off colorbar pass def _set_caxis(self, ax): """Set the color axis scale.""" if DEBUG: print "Setting caxis" if ax.getp('caxismode') == 'manual': cmin, cmax = ax.getp('caxis') # NOTE: cmin and cmax might be None: if cmin is None or cmax is None: cmin, cmax = [0,1] # set color axis scaling according to cmin and cmax if self._mplsurf is not None: pass # cannot handle 3D surf else: self._g.clim(cmin,cmax) else: # use autoranging for color axis scale pass def _set_colormap(self, ax): """Set the colormap.""" if DEBUG: print "Setting colormap" cmap = ax.getp('colormap') # cmap is plotting package dependent # the colormap is set in def _set_view(self, ax): """Set viewpoint specification.""" if DEBUG: print "Setting view" cam = ax.getp('camera') view = cam.getp('view') if view == 2: # setup a default 2D view pass elif view == 3: az = cam.getp('azimuth') el = cam.getp('elevation') if az is None or el is None: # azimuth or elevation is not given. Set up a default # 3D view (az=-37.5 and el=30 is the default 3D view in # Matlab). pass else: # set a 3D view according to az and el pass if cam.getp('cammode') == 'manual': # for advanced camera handling: roll = cam.getp('camroll') zoom = cam.getp('camzoom') dolly = cam.getp('camdolly') target = cam.getp('camtarget') position = cam.getp('campos') up_vector = cam.getp('camup') view_angle = cam.getp('camva') projection = cam.getp('camproj') def _set_axis_props(self, ax): if DEBUG: print "Setting axis properties" self._set_title(ax) self._set_scale(ax) self._set_axis_method(ax) self._set_limits(ax) self._set_position(ax) self._set_daspect(ax) self._set_coordinate_system(ax) self._set_hidden_line_removal(ax) self._set_colorbar(ax) self._set_caxis(ax) self._set_colormap(ax) self._set_view(ax) if ax.getp('visible'): self._set_labels(ax) self._set_box(ax) self._set_grid(ax) else: # turn off all axis labeling, tickmarks, and background self._g.axis('off') def _get_linespecs(self, item): """ Return the line marker, line color, line style, and line width of the item. """ marker = self._markers[item.getp('linemarker')] color = item.getp('linecolor') style = item.getp('linetype') width = item.getp('linewidth') if width: width = float(width) return marker, color, style, width def _fix_latex(self, legend): """Enclose legend in $$ if latex syntax is detected.""" # We always support latex syntax either through direct # use of latex (text.usetex=true) or through the native mathtext. #if not matplotlib.rcParams['text.usetex']: # return legend legend = legend.strip() if len(legend) >= 2 and legend[0] != '$' and legend[-1] != '$': # else: assume correct latex syntax, otherwise fix #print '....fix', legend, if '**' in legend: legend = legend.replace('**', '^') if '*' in legend: #legend = legend.replace('*', '\\cdot') legend = legend.replace('*', ' ') chars = '\\', '^', '_' latex = False for c in chars: if c in legend: latex = True break if latex: # make this math: legend = '$' + legend + '$' # enclose words in \hbox{}'es: # (not successful enough) #word = r'(\s?[^\\][A-Za-z][a-z]*[ :;,$)] ?)' #word = r'(\s?[A-Za-z][a-z]*[ :;,$)])' #word = r'(\w[ :;,$)])' #word = r'(\b[A-Za-z][a-z]*[ :;,$)]\b)' #if re.search(word, legend): # legend = re.sub(word, r'\hbox{\g<1>}', legend) # remove internal $ chars: legend = legend.replace('$', '') legend = '$' + legend + '$' # fix sin, cos, exp, ln, log, etc: def _fix_func(func, newfunc, legend): if re.search(r'[^\\]'+func, legend): legend = legend.replace(func, '\\'+newfunc) return legend funcs = 'sin', 'cos', 'tan', 'exp', 'ln', 'log', \ 'sinh', 'cosh', 'tanh' for func in funcs: legend = _fix_func(func, func, legend) funcs = [('atan', 'arctan'), ('asin', 'arcsin'), ('acos', 'arccos'),] for func, newfunc in funcs: legend = _fix_func(func, newfunc, legend) #print 'after fix:', legend return legend def _add_line(self, item): """Add a 2D or 3D curve to the scene.""" if DEBUG: print "Adding a line" # get data: x = squeeze(item.getp('xdata')) y = squeeze(item.getp('ydata')) z = item.getp('zdata') if z is not None: z = squeeze(z) # get line specifiactions: marker, color, style, width = self._get_linespecs(item) fmt = marker+color+style if not width: width = 1.0 if z is not None: # zdata is given, add a 3D curve: print "No support for plot3 in Matplotlib." else: # no zdata, add a 2D curve: #l, = self._g.plot(x,y,fmt,linewidth=width) l = self._g.plot(x,y,fmt,linewidth=width) legend = item.getp('legend') legend = self._fix_latex(legend) if legend: l[0].set_label(legend) def _add_filled_line(self, item): """Add a 2D or 3D filled curve.""" if DEBUG: print "Adding a line" # get data: x = squeeze(item.getp('xdata')) y = squeeze(item.getp('ydata')) z = item.getp('zdata') # get line specifiactions: marker, color, style, width = self._get_linespecs(item) if not width: width = 1.0 facecolor = item.getp('facecolor') if not facecolor: if not color: color = 'b' facecolor = color edgecolor = item.getp('edgecolor') if not edgecolor: edgecolor = 'k' # use black for now # FIXME: edgecolor should be ax.getp('fgcolor') by default opacity = item.getp('material').getp('opacity') if opacity is None: opacity = 1.0 if z is not None: # zdata is given, add a filled 3D curve: print "No support for fill3 in Matplotlib." else: # no zdata, add a filled 2D curve: l = self._g.fill(x, y, fc=facecolor, ec=edgecolor, linewidth=width, alpha=opacity) legend = item.getp('legend') legend = self._fix_latex(legend) if legend: l[0].set_label(legend) def _add_bar_graph(self, item, shading='faceted'): if DEBUG: print "Adding a bar graph" # get data: x = squeeze(item.getp('xdata')) y = squeeze(item.getp('ydata')) # get line specifiactions: marker, color, style, width = self._get_linespecs(item) edgecolor = item.getp('edgecolor') if not edgecolor: edgecolor = 'k' # use black for now # FIXME: edgecolor should be same as ax.getp('fgcolor') by default facecolor = item.getp('facecolor') if not facecolor: facecolor = color opacity = item.getp('material').getp('opacity') if opacity is None: opacity = 1.0 if rank(y) == 1: y = reshape(y,(len(y),1)) nx, ny = shape(y) step = item.getp('barstepsize')/10 center = floor(ny/2) start = -step*center stop = step*center if not ny%2: start += step/2 stop -= step/2 a = linspace(start,stop,ny) barwidth = item.getp('barwidth')/10 hold_state = self._g.ishold() self._g.hold(True) colors = PlotProperties._colors + matplotlib.colors.cnames.values() for j in range(ny): y_ = y[:,j] x_ = array(range(nx)) + a[j] - barwidth/2 if not facecolor: c = colors[j] else: c = facecolor self._g.bar(x_, y_, width=barwidth, color=c, ec=edgecolor, alpha=opacity) self._g.hold(hold_state) barticks = item.getp('barticks') if barticks is None: barticks = x if item.getp('rotated_barticks'): self._g.xticks(range(len(x)), barticks, rotation=90) else: self._g.xticks(range(len(x)), barticks) def _add_surface(self, item, shading='faceted', colormap=None, showcolorbar=False, zmin=None, zmax=None): if DEBUG: print "Adding a surface" x = squeeze(item.getp('xdata')) # grid component in x-direction y = squeeze(item.getp('ydata')) # grid component in y-direction z = item.getp('zdata') # scalar field c = item.getp('cdata') # pseudocolor data (can be None) legend = item.getp('legend') legend = self._fix_latex(legend) if colormap is None or colormap == 'default': colormap = self._g.cm.get_cmap('jet') if shape(x) != shape(z) or shape(y) != shape(z): x, y = meshgrid(x, y, sparse=False, indexing=item.getp('indexing')) opacity = item.getp('material').getp('opacity') if opacity is None: opacity = 1.0 contours = item.getp('contours') if contours: # the current item is produced by meshc or surfc and we # should therefore add contours at the bottom: #self._add_contours(contours, placement='bottom') print "No support for meshc/surfc in Matplotlib." if item.getp('wireframe'): # wireframe mesh (as produced by mesh or meshc) fig = self._g.gcf() ax = fig.gca(projection='3d') h = ax.plot_wireframe(x, y, z) if legend: h.set_label(legend) else: # colored surface (as produced by surf, surfc, or pcolor) # use keyword argument shading to set the color shading mode function = item.getp('function') if function == 'pcolor': h = self._g.pcolor(x, y, z, shading=shading, cmap=colormap, alpha=opacity) else: # This is really a hack to use 3D surfaces in matplotlib... from mpl_toolkits.mplot3d import Axes3D fig = self._g.gcf() ax = fig.gca(projection='3d') if self._mplsurf is not None: ax.collections.remove(self._mplsurf) self._mplsurf = ax.plot_surface(x, y, z, rstride=1, cstride=1, linewidth=0, cmap=colormap, antialiased=False) if showcolorbar and not self._mpl3D: # Show colorbar only for the first plot in an animation fig.colorbar(self._mplsurf, shrink=1.0, aspect=15, orientation='vertical',) if zmin is not None and zmax is not None: ax.set_zlim3d(zmin, zmax) self._mpl3D = True # Problem: cannot fix color scale (or?) if legend: h.set_label(legend) def _add_contours(self, item, placement=None, colormap=None): # The placement keyword can be either None or 'bottom'. The # latter specifies that the contours should be placed at the # bottom (as in meshc or surfc). if DEBUG: print "Adding contours" x = squeeze(item.getp('xdata')) # grid component in x-direction y = squeeze(item.getp('ydata')) # grid component in y-direction z = item.getp('zdata') # scalar field legend = item.getp('legend') legend = self._fix_latex(legend) if colormap is None or colormap == 'default': colormap = self._g.cm.get_cmap('jet') if shape(x) != shape(z) or shape(y) != shape(z): x, y = meshgrid(x, y, sparse=False, indexing=item.getp('indexing')) opacity = item.getp('material').getp('opacity') if opacity is None: opacity = 1.0 filled = item.getp('filled') # draw filled contour plot if True cvector = item.getp('cvector') clevels = item.getp('clevels') # number of contour levels if cvector is None: # the contour levels are chosen automatically #cvector = pass else: clevels = cvector contour_cmd = self._g.contour location = item.getp('clocation') if location == 'surface': # place the contours at the corresponding z level (contour3) print "No support for contour3 in Matplotlib." elif location == 'base': if placement == 'bottom': # place the contours at the bottom (as in meshc or surfc) pass else: # standard contour plot pass if filled: contour_cmd = self._g.contourf kwargs = {'cmap': colormap, 'alpha': opacity} # get line specifiactions: marker, color, style, width = self._get_linespecs(item) if color: kwargs['colors'] = color kwargs['cmap'] = None if width: kwargs['linewidths'] = width if legend: kwargs['label'] = legend cs = contour_cmd(x,y,z,clevels,**kwargs) if item.getp('clabels'): # add labels on the contour curves self._g.clabel(cs) def _add_vectors(self, item): if DEBUG: print "Adding vectors" # uncomment the following command if there is no support for # automatic scaling of vectors in the current plotting package: #item.scale_vectors() # grid components: x = squeeze(item.getp('xdata')) y = squeeze(item.getp('ydata')) z = item.getp('zdata') # vector components: u, v, w = item.getp('udata'), item.getp('vdata'), item.getp('wdata') # get line specifiactions (marker='.' means no marker): marker, color, style, width = self._get_linespecs(item) indexing = item.getp('indexing') legend = item.getp('legend') legend = self._fix_latex(legend) # scale the vectors according to this variable (scale=0 should # turn off automatic scaling): scale = item.getp('arrowscale') if scale == 0: scale = None filled = item.getp('filledarrows') # draw filled arrows if True if z is not None and w is not None: # draw velocity vectors as arrows with components (u,v,w) at # points (x,y,z): print "No support for quiver3 in Matplotlib." else: # draw velocity vectors as arrows with components (u,v) at # points (x,y): if shape(x) != shape(u) and shape(y) != shape(u): x, y = meshgrid(x, y, sparse=False, indexing=indexing) if not color: c = u**2+v**2 # color arrows by magnitude h = self._g.quiver(x,y,u,v,c,scale=scale) else: h = self._g.quiver(x,y,u,v,scale=scale,color=color) if legend: h.set_label(legend) def _add_streams(self, item): if DEBUG: print "Adding streams" # grid components: x, y, z = item.getp('xdata'), item.getp('ydata'), item.getp('zdata') # vector components: u, v, w = item.getp('udata'), item.getp('vdata'), item.getp('wdata') # starting positions for streams: sx, sy, sz = item.getp('startx'), item.getp('starty'), item.getp('startz') if item.getp('tubes'): # draw stream tubes from vector data (u,v,w) at points (x,y,z) n = item.getp('n') # no points along the circumference of the tube scale = item.getp('tubescale') pass elif item.getp('ribbons'): # draw stream ribbons from vector data (u,v,w) at points (x,y,z) width = item.getp('ribbonwidth') pass else: if z is not None and w is not None: # draw stream lines from vector data (u,v,w) at points (x,y,z) pass else: # draw stream lines from vector data (u,v) at points (x,y) pass pass def _add_isosurface(self, item): if DEBUG: print "Adding a isosurface" # grid components: x, y, z = item.getp('xdata'), item.getp('ydata'), item.getp('zdata') v = item.getp('vdata') # volume c = item.getp('cdata') # pseudocolor data isovalue = item.getp('isovalue') def _add_slices(self, item): if DEBUG: print "Adding slices in a volume" # grid components: x, y, z = item.getp('xdata'), item.getp('ydata'), item.getp('zdata') v = item.getp('vdata') # volume sx, sy, sz = item.getp('slices') if rank(sz) == 2: # sx, sy, and sz defines a surface pass else: # sx, sy, and sz is either numbers or vectors with numbers pass pass def _add_contourslices(self, item): if DEBUG: print "Adding contours in slice planes" # grid components: x, y, z = item.getp('xdata'), item.getp('ydata'), item.getp('zdata') v = item.getp('vdata') # volume sx, sy, sz = item.getp('slices') if rank(sz) == 2: # sx, sy, and sz defines a surface pass else: # sx, sy, and sz is either numbers or vectors with numbers pass cvector = item.getp('cvector') clevels = item.getp('clevels') # number of contour levels per plane if cvector is None: # the contour levels are chosen automatically #cvector = pass pass def _set_figure_size(self, fig): if DEBUG: print "Setting figure size" width, height = fig.getp('size') if width and height: # set figure width and height fig = self._g.gcf() fig.set_size_inches(width,height) else: # use the default width and height in plotting package pass
[docs] def figure(self, *args, **kwargs): # Extension of BaseClass.figure: # add a plotting package figure instance as fig._g and create a # link to it as self._g fignum = BaseClass.figure(self, *args, **kwargs) fig = self.gcf() try: fig._g except: # create plotting package figure and save figure instance # as fig._g if DEBUG: name = 'Fig ' + str(fignum) print "creating figure %s in backend" % name fig._g = pylab self._g = fig._g # link for faster access self._mpl3D = False self._mplsurf = None self._texts = {} # store calls to text (for replot) return fignum
def _replot(self): """Replot all axes and all plotitems in the backend.""" # NOTE: only the current figure (gcf) is redrawn. if DEBUG: print "Doing replot in backend" # turn off interactive in pyplot temporarily: old_pylab_interactive_state = self._g.isinteractive() self._g.ioff() fig = self.gcf() try: fig._g except: self.figure(self.getp('curfig')) self._g.figure(self.getp('curfig')) # reset the plotting package instance in fig._g now if needed if not self._mpl3D: self._g.clf() self._set_figure_size(fig) nrows, ncolumns = fig.getp('axshape') for axnr, ax in fig.getp('axes').items(): if ax.getp('numberofitems') == 0: continue if nrows != 1 or ncolumns != 1: # create axes in tiled position # this is subplot(nrows, ncolumns, axnr) self._g.subplot(nrows, ncolumns, axnr) else: rect = ax.getp('viewport') if isinstance(rect, (list,tuple)) and len(rect) == 4 and \ ax.getp('pth') is None: self._g.axes(rect) legends = False plotitems = ax.getp('plotitems') plotitems.sort(self._cmpPlotProperties) for item in plotitems: func = item.getp('function') # function that produced this item if isinstance(item, Line): if func == 'fill': self._add_filled_line(item) else: self._add_line(item) elif isinstance(item, Bars): self._add_bar_graph(item, shading=ax.getp('shading')) elif isinstance(item, Surface): self._add_surface(item, shading=ax.getp('shading'), colormap=ax.getp('colormap'), showcolorbar=ax.getp('colorbar').getp('visible'), zmin=ax.getp('zmin'), zmax=ax.getp('zmax')) elif isinstance(item, Contours): self._add_contours(item, colormap=ax.getp('colormap')) elif isinstance(item, VelocityVectors): self._add_vectors(item) elif isinstance(item, Streams): self._add_streams(item) elif isinstance(item, Volume): if func == 'isosurface': self._add_isosurface(item) elif func == 'slice_': self._add_slices(item) elif func == 'contourslice': self._add_contourslices(item) legend = item.getp('legend') legend = self._fix_latex(legend) if legend: # add legend to plot legends = True if ax.getp('numberofitems') > 1 and not self._g.ishold(): self._g.hold(True) if legends: try: loc = ax.getp('legend_loc') except KeyError: loc = 'best' try: fancybox = ax.getp('legend_fancybox') except KeyError: fancybox = True self._g.legend(loc=loc, fancybox=fancybox) self._set_axis_props(ax) # Display texts for args in self._texts: self.text(args[0], args[1], args[2], fontname=args[3], fontsize=args[4]) # set back the interactive state in pylab: if old_pylab_interactive_state: self._g.ion() self._g.draw() if self.getp('show'): # display plot on the screen if DEBUG: print "\nDumping plot data to screen\n" debug(self) self._g.figure(self.getp('curfig')) # raise figure # Or is there a better way to draw the current figure without # calling pylab.show()? #self._g.show()
[docs] def text(self, x, y, text, fontname=Axis._local_prop['fontname'], fontsize=Axis._local_prop['fontsize']): """Write text at position (x,y) in a curveplot.""" self._g.text(x, y, text, family=fontname, size=fontsize) self._texts[(x, y, text, fontname, fontsize)] = None
[docs] def hardcopy(self, filename, **kwargs): """ Supported extensions: .eps, .jpg, .pdf, .png, .ps, and .svg This is dependent on the Matplotlib backend. Optional arguments: dpi -- image resolution. Default is 150. orientation -- 'portrait' (default) or 'landscape'. Only available for PostScript output. """ self.setp(**kwargs) color = self.getp('color') replot = kwargs.get('replot', True) if replot: self._replot() if DEBUG: print "Hardcopy to %s" % filename dpi = kwargs.get('dpi', 150) orientation = kwargs.get('orientation', 'portrait') self._g.savefig(filename, facecolor='w', edgecolor='w', orientation=orientation)
[docs] def clf(self): self._g.clf() BaseClass.clf(self)
[docs] def closefig(self, arg=None): if arg is None: num = self.getp('curfig') # close current figure elif arg in self._figs.keys(): num = arg elif arg in self._figs.values(): for fignr, fig in self._figs.items(): if fig == arg: num = fignr break else: raise ValueError("closefig: cannot close figure '%s'" % arg) self._g.close(num) #del self._figs[num]._g #del self._figs[num]
[docs] def closefigs(self): for key in self._figs.keys(): self.closefig(key) del self._g BaseClass.closefigs(self) # Colormap methods:
[docs] def hsv(self, m=None): return pylab.cm.get_cmap('hsv', m)
[docs] def hot(self, m=None): return pylab.cm.get_cmap('hot', m)
[docs] def gray(self, m=None): return pylab.cm.get_cmap('gray', m)
[docs] def bone(self, m=None): return pylab.cm.get_cmap('bone', m)
[docs] def copper(self, m=None): return pylab.cm.get_cmap('copper', m)
[docs] def pink(self, m=None): return pylab.cm.get_cmap('pink', m)
[docs] def white(self, m=None): raise NotImplementedError('white not implemented in class %s' % \ self.__class__.__name__)
[docs] def flag(self, m=None): return pylab.cm.get_cmap('flag', m)
[docs] def lines(self, m=None): raise NotImplementedError('lines not implemented in class %s' % \ self.__class__.__name__)
[docs] def colorcube(self, m=None): raise NotImplementedError('colorcube not implemented in class %s' % \ self.__class__.__name__)
[docs] def vga(self, m=None): raise NotImplementedError('vga not implemented in class %s' % \ self.__class__.__name__)
[docs] def jet(self, m=None): return pylab.cm.get_cmap('jet', m)
[docs] def prism(self, m=None): return pylab.cm.get_cmap('prism', m)
[docs] def cool(self, m=None): return pylab.cm.get_cmap('cool', m)
[docs] def autumn(self, m=None): return pylab.cm.get_cmap('autumn', m)
[docs] def spring(self, m=None): return pylab.cm.get_cmap('spring', m)
[docs] def winter(self, m=None): return pylab.cm.get_cmap('winter', m)
[docs] def summer(self, m=None): return pylab.cm.get_cmap('summer', m) # Now we add the doc string from the methods in BaseClass to the # methods that are reimplemented in this backend:
for cmd in BaseClass._matlab_like_cmds: if not '__' in cmd and hasattr(BaseClass, cmd): m1 = eval('BaseClass.%s' % cmd) try: m2 = eval('%s' % cmd) except NameError: pass else: if m1.__doc__ != m2.__doc__: if m2.__doc__ is None: m2.__doc__ = "" m2.__doc__ = m1.__doc__ + m2.__doc__
plt = MatplotlibBackend() # create backend instance use(plt, globals()) # export public namespace of plt to globals() # We should close all figure windows on program exit: import atexit atexit.register(close, 'all') backend = os.path.splitext(os.path.basename(__file__))[0][:-1]