class Matplotlib2DContourViewer(AbstractMatplotlib2DViewer): """Displays a contour plot of a 2D `CellVariable` object. The `Matplotlib2DContourViewer` plots a 2D `CellVariable` using Matplotlib_. .. _Matplotlib: http://matplotlib.sourceforge.net/ """ __doc__ += AbstractMatplotlib2DViewer._test2D(viewer="Matplotlib2DContourViewer") def __init__(self, vars, title=None, limits={}, cmap=None, colorbar='vertical', axes=None, number=10, levels=None, figaspect='auto', **kwlimits): """Creates a `Matplotlib2DContourViewer`. Parameters ---------- vars : ~fipy.variables.cellVariable.CellVariable `Variable` to display title : str, optional displayed at the top of the `Viewer` window limits : dict, optional a (deprecated) alternative to limit keyword arguments float xmin, xmax, ymin, ymax, datamin, datamax : float, optional displayed range of data. Any limit set to a (default) value of `None` will autoscale. cmap : ~matplotlib.colors.Colormap, optional the Colormap. Defaults to `matplotlib.cm.jet` colorbar : bool, optional plot a color bar in specified orientation if not `None` axes : ~matplotlib.axes.Axes, optional if not `None`, `vars` will be plotted into this Matplotlib `Axes` object number : int, optional contour `number` automatically-chosen levels levels : :obj:`list` of :obj:`float`, optional A list of numbers indicating the level curves to draw; e.g. to draw just the zero contour pass ``levels=[0]`` figaspect : float desired aspect ratio of figure. If arg is a number, use that aspect ratio. If arg is `auto`, the aspect ratio will be determined from the Variable's mesh. """ kwlimits.update(limits) AbstractMatplotlib2DViewer.__init__(self, vars=vars, title=title, cmap=cmap, colorbar=colorbar, axes=axes, figaspect=figaspect, **kwlimits) self.number = number self.levels = levels self._plot() def _getSuitableVars(self, vars): from fipy.meshes.mesh2D import Mesh2D from fipy.variables.cellVariable import CellVariable vars = [var for var in AbstractMatplotlib2DViewer._getSuitableVars(self, vars) \ if ((isinstance(var.mesh, Mesh2D) and isinstance(var, CellVariable)) and var.rank == 0)] if len(vars) == 0: from fipy.viewers import MeshDimensionError raise MeshDimensionError("Matplotlib2DViewer can only display a rank-0, 2D CellVariable") # this viewer can only display one variable return [vars[0]] def _plot(self): ## plt.clf() ## ## Added garbage collection since matplotlib objects seem to hang ## ## around and accumulate. ## import gc ## gc.collect() mesh = self.vars[0].mesh x, y = mesh.cellCenters z = self.vars[0].value xmin, ymin = mesh.extents['min'] xmax, ymax = mesh.extents['max'] from matplotlib.mlab import griddata xi = numerix.linspace(xmin, xmax, 1000) yi = numerix.linspace(ymin, ymax, 1000) # grid the data. zi = griddata(x, y, z, xi, yi, interp='linear') if hasattr(self, "_contourSet"): for collection in self._contourSet.collections: try: ix = self.axes.collections.index(collection) except ValueError as e: ix = None if ix is not None: del self.axes.collections[ix] zmin, zmax = self._autoscale(vars=self.vars, datamin=self._getLimit(('datamin', 'zmin')), datamax=self._getLimit(('datamax', 'zmax'))) self.norm.vmin = zmin self.norm.vmax = zmax if self.levels is not None: levels = self.levels else: levels = numerix.arange(self.number + 1) * (zmax - zmin) / self.number + zmin self._contourSet = self.axes.contour(xi, yi, zi, levels=levels, cmap=self.cmap) self.axes.set_xlim(xmin=self._getLimit('xmin'), xmax=self._getLimit('xmax')) self.axes.set_ylim(ymin=self._getLimit('ymin'), ymax=self._getLimit('ymax')) if self.colorbar is not None: self.colorbar.plot()
class Matplotlib2DGridViewer(AbstractMatplotlib2DViewer): """ Displays an image plot of a 2D `CellVariable` object using Matplotlib_. .. _Matplotlib: http://matplotlib.sourceforge.net/ """ __doc__ += AbstractMatplotlib2DViewer._test2D( viewer="Matplotlib2DGridViewer") def __init__(self, vars, title=None, limits={}, cmap=None, colorbar='vertical', axes=None, figaspect='auto', **kwlimits): """ Creates a `Matplotlib2DGridViewer`. :Parameters: vars A `CellVariable` object. title displayed at the top of the `Viewer` window limits : dict a (deprecated) alternative to limit keyword arguments cmap The colormap. Defaults to `matplotlib.cm.jet` xmin, xmax, ymin, ymax, datamin, datamax displayed range of data. Any limit set to a (default) value of `None` will autoscale. colorbar plot a colorbar in specified orientation if not `None` axes if not `None`, `vars` will be plotted into this Matplotlib `Axes` object figaspect desired aspect ratio of figure. If arg is a number, use that aspect ratio. If arg is 'auto', the aspect ratio will be determined from the Variable's mesh. """ kwlimits.update(limits) AbstractMatplotlib2DViewer.__init__(self, vars=vars, title=title, cmap=cmap, colorbar=colorbar, axes=axes, figaspect=figaspect, **kwlimits) self.image = self.axes.imshow(self._data, extent=(self._getLimit('xmin'), self._getLimit('xmax'), self._getLimit('ymin'), self._getLimit('ymax')), vmin=0, vmax=1, cmap=self.cmap) if title is None: self.axes.set_title(self.vars[0].name) def _getLimit(self, key, default=None): limit = AbstractMatplotlib2DViewer._getLimit(self, key, default=default) if limit is None: X, Y = self.vars[0].mesh.faceCenters if 'xmin' in key: limit = float(min(X)) elif 'ymin' in key: limit = float(min(Y)) if 'xmax' in key: limit = float(max(X)) elif 'ymax' in key: limit = float(max(Y)) return limit def _getSuitableVars(self, vars): from fipy.meshes.uniformGrid2D import UniformGrid2D from fipy.variables.cellVariable import CellVariable vars = [var for var in AbstractMatplotlib2DViewer._getSuitableVars(self, vars) \ if (isinstance(var.mesh, UniformGrid2D) and isinstance(var, CellVariable) and var.rank == 0)] if len(vars) == 0: from fipy.viewers import MeshDimensionError raise MeshDimensionError, "Matplotlib2DGridViewer can only display a rank-0 CellVariable with a UniformGrid2D mesh" # this viewer can only display one variable return [vars[0]] @getsetDeprecated def _getData(self): return self._data @property def _data(self): from fipy.tools.numerix import array, reshape return reshape(array(self.vars[0]), self.vars[0].mesh.shape[::-1])[::-1] def _plot(self): self.norm.vmin = self._getLimit(('datamin', 'zmin')) self.norm.vmax = self._getLimit(('datamax', 'zmax')) self.image.set_data(self.norm(self._data)) if self.colorbar is not None: self.colorbar.plot()
class Matplotlib2DGridContourViewer(AbstractMatplotlib2DViewer): """Displays a contour plot of a 2D `CellVariable` object. The `Matplotlib2DGridContourViewer` plots a 2D `CellVariable` using Matplotlib_. .. _Matplotlib: http://matplotlib.sourceforge.net/ """ __doc__ += AbstractMatplotlib2DViewer._test2D( viewer="Matplotlib2DGridContourViewer") def __init__(self, vars, title=None, limits={}, cmap=None, colorbar='vertical', axes=None, figaspect='auto', **kwlimits): """Creates a `Matplotlib2DViewer`. :Parameters: vars a `CellVariable` object. title displayed at the top of the `Viewer` window limits : dict a (deprecated) alternative to limit keyword arguments xmin, xmax, ymin, ymax, datamin, datamax displayed range of data. Any limit set to a (default) value of `None` will autoscale. cmap the colormap. Defaults to `matplotlib.cm.jet` colorbar plot a colorbar in specified orientation if not `None` axes if not `None`, `vars` will be plotted into this Matplotlib `Axes` object figaspect desired aspect ratio of figure. If arg is a number, use that aspect ratio. If arg is 'auto', the aspect ratio will be determined from the Variable's mesh. """ kwlimits.update(limits) AbstractMatplotlib2DViewer.__init__(self, vars=vars, title=title, cmap=cmap, colorbar=colorbar, axes=axes, figaspect=figaspect, **kwlimits) self._plot() def _getSuitableVars(self, vars): from fipy.meshes.grid2D import Grid2D from fipy.meshes.uniformGrid2D import UniformGrid2D from fipy.variables.cellVariable import CellVariable vars = [var for var in AbstractMatplotlib2DViewer._getSuitableVars(self, vars) \ if ((isinstance(var.mesh, Grid2D) or isinstance(var.mesh, UniformGrid2D)) and isinstance(var, CellVariable))] if len(vars) == 0: from fipy.viewers import MeshDimensionError raise MeshDimensionError, "The mesh must be a Grid2D instance" # this viewer can only display one variable return [vars[0]] def _plot(self): ## pylab.clf() ## ## Added garbage collection since matplotlib objects seem to hang ## ## around and accumulate. ## import gc ## gc.collect() mesh = self.vars[0].mesh shape = mesh.shape X, Y = mesh.cellCenters Z = self.vars[0].value X, Y, Z = [v.reshape(shape, order="FORTRAN") for v in (X, Y, Z)] zmin, zmax = self._autoscale(vars=self.vars, datamin=self._getLimit( ('datamin', 'zmin')), datamax=self._getLimit( ('datamax', 'zmax'))) self.norm.vmin = zmin self.norm.vmax = zmax numberOfContours = 10 smallNumber = 1e-7 diff = zmax - zmin if diff < smallNumber: V = numerix.arange(numberOfContours + 1) * smallNumber / numberOfContours + zmin else: V = numerix.arange(numberOfContours + 1) * diff / numberOfContours + zmin self.axes.contourf(X, Y, Z, V, cmap=self.cmap) self.axes.set_xlim(xmin=self._getLimit('xmin'), xmax=self._getLimit('xmax')) self.axes.set_ylim(ymin=self._getLimit('ymin'), ymax=self._getLimit('ymax')) if self.colorbar is not None: self.colorbar.plot()