Пример #1
0
class VarPlot(object):

    def __init__(self, var, cmap, axes):
        self.axes = axes
        self.var = var
        self.cmap = cmap
        self.mesh = self.var.mesh
        self.plot_mesh()

    def plot_mesh(self):
        vertexIDs = self.mesh._orderedCellVertexIDs
        vertexCoords = self.mesh.vertexCoords
        xCoords = numerix.take(vertexCoords[0], vertexIDs)
        yCoords = numerix.take(vertexCoords[1], vertexIDs)
        polys = []
        for x, y in zip(xCoords.swapaxes(0, 1), yCoords.swapaxes(0, 1)):
            polys.append(zip(x, y))
        self.collection = PolyCollection(polys)
        self.collection.set_linewidth(0.5)
        self.axes.add_collection(self.collection)
        self.update(self.var)

    def update(self, var):
        rgba = self.cmap(var.value)
        self.collection.set_facecolors(rgba)
        self.collection.set_edgecolors(rgba)
Пример #2
0
def plot_trimesh2D(verts, faces, val=None, cmap=plt.cm.get_cmap(), 
        vmin=None, vmax=None, mirror=False, **kw):
    """Plot a mesh of triangles, from directly above, without all this
    3D stuff.
    
    Input   verts   N x 3 array of vertex locations
    
            faces   M x 3 array of vertex indices for each face
            
            val     M list of values for each vertex, used for coloring
            
            cmap    colormap, defaulting to current colormap
            
            vmin    lower limit for coloring, defaulting to min(val)
            
            vmax    upper limit for coloring, defaulting to max(val)
            
            mirror  flag for mirror around x=0
            
            Other keyword pairs are passed to PolyCollection
    """
    
    v = array([[verts[ind,:2] for ind in face] for face in faces])
    if mirror:
        v = r_[v, v * [-1,1]]
    if val is not None:
        val = array(val)
    
    poly = PolyCollection(v, cmap=cmap, norm=Normalize(clip=True), **kw)
    poly.set_array(val)
    poly.set_clim(vmin, vmax)
    poly.set_facecolors(poly.norm(val)) 
    
    ax = plt.gca()
    ax.add_collection(poly)
    ax.axis('image')
    if val is not None:
        # This magic dohickey is used by colorbar() and clim(), for example
        plt.gci._current = poly
    plt.draw() # Seems like should be draw_if_interactive(), but that doesn't
               # work, for some unexplained reason.
    
    return poly
Пример #3
0
class Matplotlib2DViewer(_MatplotlibViewer):
    """
    Displays a contour plot of a 2D `CellVariable` object.    

    The `Matplotlib2DViewer` plots a 2D `CellVariable` using Matplotlib_.

    .. _Matplotlib: http://matplotlib.sourceforge.net/
    """ 
    
    __doc__ += _MatplotlibViewer._test2Dirregular(viewer="Matplotlib2DViewer")

    def __init__(self, vars, title=None, limits={}, cmap=None, colorbar=True, axes=None, **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
          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
        """
        kwlimits.update(limits)
        _MatplotlibViewer.__init__(self, vars=vars, title=title, figaspect=1. / 1.3, 
                                   cmap=cmap, colorbar=colorbar, axes=axes, 
                                   **kwlimits)

        self.mesh = self.vars[0].getMesh()
        
        vertexIDs = self.mesh._getOrderedCellVertexIDs()

        vertexCoords = self.mesh.getVertexCoords()

        xCoords = numerix.take(vertexCoords[0], vertexIDs)
        yCoords = numerix.take(vertexCoords[1], vertexIDs)
        
        polys = []

        for x, y in zip(xCoords.swapaxes(0,1), yCoords.swapaxes(0,1)):
            if hasattr(x, 'mask'):
                x = x.compressed()
            if hasattr(y, 'mask'):
                y = y.compressed()
            polys.append(zip(x,y))

        import matplotlib

        from matplotlib.collections import PolyCollection
        self.collection = PolyCollection(polys)
        self.collection.set_linewidth(0.5)
        try:
            self.axes.add_patch(self.collection)
        except:
            # PolyCollection not child of PatchCollection in matplotlib 0.98
            self.axes.add_collection(self.collection)

        xmin = self._getLimit('xmin', default=xCoords.min())
        xmax = self._getLimit('xmax', default=xCoords.max())
        ymin = self._getLimit('ymin', default=yCoords.min())
        ymax = self._getLimit('ymax', default=yCoords.max())

        self.axes.set_xlim(xmin=xmin, xmax=xmax)
        self.axes.set_ylim(ymin=ymin, ymax=ymax)

        self._plot()
        
    def _getSuitableVars(self, vars):
        from fipy.meshes.numMesh.mesh2D import Mesh2D
        from fipy.variables.cellVariable import CellVariable
        vars = [var for var in _MatplotlibViewer._getSuitableVars(self, vars) \
          if ((isinstance(var.getMesh(), Mesh2D) and isinstance(var, CellVariable))
              and var.getRank() == 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):
##         pylab.clf()
        
##         ## Added garbage collection since matplotlib objects seem to hang
##         ## around and accumulate.
##         import gc
##         gc.collect()

        Z = self.vars[0].getValue() 
        
        zmin, zmax = self._autoscale(vars=self.vars,
                                     datamin=self._getLimit(('datamin', 'zmin')),
                                     datamax=self._getLimit(('datamax', 'zmax')))

        diff = zmax - zmin
        
        import matplotlib

        if diff == 0:
            rgba = self.cmap(0.5)
        else:
            rgba = self.cmap((Z - zmin) / diff)
        
        self.collection.set_facecolors(rgba)
        self.collection.set_edgecolors(rgba)

        if self.colorbar is not None:
            self.colorbar.plot(vmin=zmin, vmax=zmax)
Пример #4
0
class Matplotlib2DViewer(_MatplotlibViewer):
    """
    Displays a contour plot of a 2D `CellVariable` object.    

    The `Matplotlib2DViewer` plots a 2D `CellVariable` using Matplotlib_.

    .. _Matplotlib: http://matplotlib.sourceforge.net/
    """ 
    
    __doc__ += _MatplotlibViewer._test2Dirregular(viewer="Matplotlib2DViewer")

    def __init__(self, vars, title=None, limits={}, cmap=None, **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
          cmap
            the colormap. Defaults to `pylab.cm.jet`
          xmin, xmax, ymin, ymax, datamin, datamax
            displayed range of data. Any limit set to 
            a (default) value of `None` will autoscale.

        """
        kwlimits.update(limits)
        _MatplotlibViewer.__init__(self, vars=vars, title=title, figaspect=1. / 1.3, **kwlimits)

        self.colorbar = None
        
        self.mesh = self.vars[0].getMesh()
        
        vertexIDs = self.mesh._getOrderedCellVertexIDs()

        vertexCoords = self.mesh.getVertexCoords()

        xCoords = numerix.take(vertexCoords[0], vertexIDs)
        yCoords = numerix.take(vertexCoords[1], vertexIDs)
        
        polys = []

        for x, y in zip(xCoords.swapaxes(0,1), yCoords.swapaxes(0,1)):
            if hasattr(x, 'mask'):
                x = x.compressed()
            if hasattr(y, 'mask'):
                y = y.compressed()
            polys.append(zip(x,y))

        import pylab
        import matplotlib

        fig = pylab.figure(self.id)

        ax = fig.get_axes()[0]

        from matplotlib.collections import PolyCollection
        self.collection = PolyCollection(polys)
        self.collection.set_linewidth(0.5)
        try:
            ax.add_patch(self.collection)
        except:
            # PolyCollection not child of PatchCollection in matplotlib 0.98
            ax.add_collection(self.collection)

        if self._getLimit('xmin') is None:
            xmin = xCoords.min()
        else:
            xmin = self._getLimit('xmin')

        if self._getLimit('xmax') is None:
            xmax = xCoords.max()
        else:
            xmax = self._getLimit('xmax')

        if self._getLimit('ymin') is None:
            ymin = yCoords.min()
        else:
            ymin = self._getLimit('ymin')

        if self._getLimit('ymax') is None:
            ymax = yCoords.max()
        else:
            ymax = self._getLimit('ymax')

        pylab.axis((xmin, xmax, ymin, ymax))

        cbax, kw = matplotlib.colorbar.make_axes(ax, orientation='vertical')
        
        # Set the colormap and norm to correspond to the data for which
        # the colorbar will be used.
        if cmap is None:
            self.cmap = matplotlib.cm.jet
        else:
            self.cmap = cmap
            
        norm = matplotlib.colors.normalize(vmin=-1, vmax=1)
        
        # ColorbarBase derives from ScalarMappable and puts a colorbar
        # in a specified axes, so it has everything needed for a
        # standalone colorbar.  There are many more kwargs, but the
        # following gives a basic continuous colorbar with ticks
        # and labels.
        self.cb = matplotlib.colorbar.ColorbarBase(cbax, cmap=self.cmap,
                                                   norm=norm,
                                                   orientation='vertical')
        self.cb.set_label(self.vars[0].name)
        
        self._plot()
        
    def _getSuitableVars(self, vars):
        from fipy.meshes.numMesh.mesh2D import Mesh2D
        from fipy.variables.cellVariable import CellVariable
        vars = [var for var in _MatplotlibViewer._getSuitableVars(self, vars) \
          if ((isinstance(var.getMesh(), Mesh2D) and isinstance(var, CellVariable))
              and var.getRank() == 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):
##         pylab.clf()
        
##         ## Added garbage collection since matplotlib objects seem to hang
##         ## around and accumulate.
##         import gc
##         gc.collect()

        Z = self.vars[0].getValue() 
        
        zmin, zmax = self._autoscale(vars=self.vars,
                                     datamin=self._getLimit(('datamin', 'zmin')),
                                     datamax=self._getLimit(('datamax', 'zmax')))

        diff = zmax - zmin
        
        import matplotlib

        if diff == 0:
            rgba = self.cmap(0.5)
        else:
            rgba = self.cmap((Z - zmin) / diff)
        
        self.collection.set_facecolors(rgba)
        self.collection.set_edgecolors(rgba)

        self.cb.norm = matplotlib.colors.normalize(vmin=zmin, vmax=zmax)
        self.cb.cmap = self.cmap
        self.cb.draw_all()
Пример #5
0

lLCollection=PolyCollection(vivll[whichVertsToPlot][w],zorder=10)
col1=(c-cMin)/(cMax-cMin)
col1=num.clip(col1,0.,1.)
if showBinaryColours:
    ww=num.where(c>0.3)
    www=num.where(c<=0.3)
    col1[ww]=1.
    col1[www]=0.1
#wc=num.where(c>0.1)
#col1[:]=1.
collectionColours=cmap(col1)
collectionColours[:,3]=alpha
#collectionColours[w][:,3]=0.0
lLCollection.set_facecolors(collectionColours[whichVertsToPlot][w])
lLCollection.set_linewidths(0.0)

slLCollection=PolyCollection(vivll[whichVertsToPlot][w])
scollectionColours=cmap(s/num.max(s))
scollectionColours[:,3]=alpha
#collectionColours[w][:,3]=0.0
slLCollection.set_facecolors(scollectionColours[whichVertsToPlot][w])
slLCollection.set_linewidths(0.0)





meanWDs=num.array(meanWDs)
stdWDs=num.array(stdWDs)#/meanWDs
class Animator(object):
    def __init__(self, template_w, template_h):
        
        #set up figure
        plt.ion()
        fig = plt.figure(figsize = (10,10))
        ax = fig.gca()

        ax.axis([-template_w/2.0, template_w/2.0,-template_h/2.0,template_h/2.0]) 
        ax.get_xaxis().set_visible(True)
        ax.get_yaxis().set_visible(True)

        #draw template
        self.plot_template(template_w,template_h)

        #draw to screen
        plt.draw()
        plt.pause(0.1)

        #save axes to object
        self.ax = ax

    #plot template
    def plot_template(self,l = 20.0, w = 20.0):
        x_pos = [-l/2, l/2, l/2, -l/2, -l/2 ]
        y_pos = [-w/2, -w/2, w/2, w/2, -w/2]
        plt.plot(x_pos,y_pos,'k-',linewidth = 3.0)
        plt.xlabel('x')
        plt.ylabel('y')

    def generate_color_array(self,collision):
        #define colors (red = collision, blue = no collision)
        colors = [None] * len(collision)
        for i in range(len(collision)):
            if collision[i] == True:
                colors[i] = (1.0,0.0,0.0)
            else:
                colors[i] = (0.0,0.0,1.0)
        return colors


    #add circular objects
    def add_circular_objects(self,diameters,positions,collision):
        
        circ_colors = self.generate_color_array(collision)
        self.circles = EllipseCollection(widths=diameters,
                                         heights=diameters,
                                         angles=np.zeros_like(diameters),
                                         units='xy',
                                         offsets=positions,
                                         transOffset=self.ax.transData,
                                         edgecolor='k', facecolor=circ_colors)


        self.ax.add_collection(self.circles)

        #add text label
        text_labels = [None] * len(collision)
        for i in range(len(collision)):
            text_labels[i]= plt.text(positions[i,0],positions[i,1],str(i),color = 'w')
        self.circle_labels = text_labels

        #draw to screen
        plt.draw()
        plt.pause(0.1)

        #remove text labels
        #for i in range(len(collision)):
        #    text_labels[i].remove()

    #add polygon objects
    def add_polygon_objects(self,verts,collision):

        poly_colors = self.generate_color_array(collision)
        self.polygons = PolyCollection(verts, facecolors=poly_colors)

        self.ax.add_collection(self.polygons)

        #add text label
        num_circles = self.circles.get_offsets().shape[1]
        text_labels = [None] * len(collision)
        for i in range(len(collision)):
            temp = np.array(verts[i])
            x = np.mean(temp[:,0])
            y = np.mean(temp[:,1])
            text_labels[i]= plt.text(x,y,str(i+num_circles),color = 'w')

        self.polygon_labels = text_labels


        plt.draw()
        plt.pause(0.1)

        #remove text labels
        #for i in range(len(collision)):
        #    text_labels[i].remove()


    #remove circular objects:
    def remove_circles(self):
        self.circles.remove()
        for label in self.circle_labels:
            label.remove()

    #remove polygon objects:
    def remove_polygons(self):
        self.polygons.remove()
        for label in self.polygon_labels:
            label.remove()

    #update circular objects
    def update_circular_objects(self,positions,collision):
        
        #set circle colors
        circ_colors = self.generate_color_array(collision)
        self.circles.set_facecolors(circ_colors)

        #set circle positions
        self.circles.set_offsets(positions)

        #remove labels
        for label in self.circle_labels:
            label.remove()

        #add labels
        text_labels = [None] * len(collision)
        for i in range(len(collision)):
            text_labels[i]= plt.text(positions[i,0],positions[i,1],str(i),color = 'w')
        self.circle_labels = text_labels


        plt.draw()
        plt.pause(0.1)


    #update polygon objects
    def update_polygon_objects(self,positions,collision):

        #set polygon colors
        poly_colors = self.generate_color_array(collision)
        self.polygons.set_facecolors(poly_colors)

        #set polygon positions
        #print 'new verts positions=' , positions
        self.polygons.set_verts(positions)

        #remove labels
        for label in self.polygon_labels:
            label.remove()

        #add new labels
        num_circles = self.circles.get_offsets().shape[1]
        #print self.polygons.get_offsets()

        #assert(0)
        text_labels = [None] * len(collision)
        for i in range(len(collision)):
            temp = np.array(positions[i])
            x = np.mean(temp[:,0])
            y = np.mean(temp[:,1])
            text_labels[i]= plt.text(x,y,str(i+num_circles),color = 'w')

        self.polygon_labels = text_labels

        plt.draw()
        plt.pause(0.1)
Пример #7
0
class Matplotlib2DViewer(AbstractMatplotlib2DViewer):
    """
    Displays a contour plot of a 2D `CellVariable` object.

    The `Matplotlib2DViewer` plots a 2D `CellVariable` using Matplotlib_.

    .. _Matplotlib: http://matplotlib.sourceforge.net/
    """

    __doc__ += AbstractMatplotlib2DViewer._test2Dirregular(viewer="Matplotlib2DViewer")

    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
          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, figaspect=figaspect,
                                            cmap=cmap, colorbar=colorbar, axes=axes,
                                            **kwlimits)

        self.mesh = self.vars[0].mesh

        vertexIDs = self.mesh._orderedCellVertexIDs

        vertexCoords = self.mesh.vertexCoords

        xCoords = numerix.take(vertexCoords[0], vertexIDs)
        yCoords = numerix.take(vertexCoords[1], vertexIDs)

        polys = []

        for x, y in zip(xCoords.swapaxes(0, 1), yCoords.swapaxes(0, 1)):
            if hasattr(x, 'mask'):
                x = x.compressed()
            if hasattr(y, 'mask'):
                y = y.compressed()
            polys.append(list(zip(x, y)))

        from matplotlib.collections import PolyCollection
        self.collection = PolyCollection(polys)
        self.collection.set_linewidth(0.5)
        try:
            self.axes.add_patch(self.collection)
        except:
            # PolyCollection not child of PatchCollection in matplotlib 0.98
            self.axes.add_collection(self.collection)

        xmin = self._getLimit('xmin', default=xCoords.min())
        xmax = self._getLimit('xmax', default=xCoords.max())
        ymin = self._getLimit('ymin', default=yCoords.min())
        ymax = self._getLimit('ymax', default=yCoords.max())

        self.axes.set_xlim(xmin=xmin, xmax=xmax)
        self.axes.set_ylim(ymin=ymin, ymax=ymax)

        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 ((var.mesh.dim == 2 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()

        Z = self.vars[0].value

        self.norm.vmin = self._getLimit(('datamin', 'zmin'))
        self.norm.vmax = self._getLimit(('datamax', 'zmax'))

        rgba = self.cmap(self.norm(Z))

        self.collection.set_facecolors(rgba)
        self.collection.set_edgecolors(rgba)

        if self.colorbar is not None:
            self.colorbar.plot() #vmin=zmin, vmax=zmax)
Пример #8
0
def show_mesh_2d(axes, mesh,  
        nodecolor='k', edgecolor='k',
        cellcolor='grey', aspect='equal',
        linewidths=1, markersize=20,
        showaxis=False, showcolorbar=False, cmap='rainbow'):
    
    axes.set_aspect(aspect)
    if showaxis == False:
        axes.set_axis_off()
    else:
        axes.set_axis_on()

    if (type(nodecolor) is np.ndarray) & np.isreal(nodecolor[0]):
        cmax = nodecolor.max()
        cmin = nodecolor.min()
        norm = colors.Normalize(vmin=cmin, vmax=cmax)
        mapper = cm.ScalarMappable(norm=norm, cmap=cmap)
        nodecolor = mapper.to_rgba(nodecolor)

    if (type(cellcolor) is np.ndarray) & np.isreal(cellcolor[0]):
        cmax = cellcolor.max()
        cmin = cellcolor.min()
        norm = colors.Normalize(vmin=cmin, vmax=cmax)
        mapper = cm.ScalarMappable(norm=norm, cmap=cmap)
        mapper.set_array(cellcolor)
        cellcolor = mapper.to_rgba(cellcolor)
        if showcolorbar:
            f = axes.get_figure()
            cbar = f.colorbar(mapper, shrink=0.5, ax=axes)
    node = mesh.node
    cell = mesh.ds.cell


    if mesh.meshtype is not 'polygon':
        if mesh.geo_dimension() == 2:
            poly = PolyCollection(node[cell, :])
        else:
            poly = a3.art3d.Poly3DCollection(node[cell,:])
    else:
        cellLocation = mesh.ds.cellLocation
        NC = mesh.number_of_cells()
        patches = [Polygon(node[cell[cellLocation[i]:cellLocation[i+1]], :], True) for i in range(NC)]
        poly = PatchCollection(patches)


    poly.set_edgecolor(edgecolor)
    poly.set_linewidth(linewidths)
    poly.set_facecolors(cellcolor)

    if mesh.geo_dimension() == 2:
        box = np.zeros(4, dtype=np.float)
    else:
        box = np.zeros(6, dtype=np.float)

    box[0::2] = np.min(node, axis=0)
    box[1::2] = np.max(node, axis=0)

    axes.set_xlim(box[0:2])
    axes.set_ylim(box[2:4])

    if mesh.geo_dimension() == 3:
        axes.set_zlim(box[4:6])

    return axes.add_collection(poly)
Пример #9
0
def plot_densities(vor,
                   thr=None,
                   plot_axis='on',
                   show_points=True,
                   cmap='jet',
                   norm='linear',
                   hold=False):
    """
    This function plots:
    1) the zero-rank densities of the bounded voronoi regions within ROI, contained in
    vor.densities_zero
    2) if threshold is given, it also plots voronoi pologons with densities larger than threshold.

    Input:
    -----------------------------
    threshold (float): optional minimum density (in nm-2) to generate a thresholded voronoi

    """

    from matplotlib.collections import PolyCollection
    from matplotlib import cm, colors

    if not hasattr(vor, 'densities_zero'):
        raise ValueError(
            "Requires vor.densities_zero attribute! Please, run vprocessing.compute_densities(vor)."
        )

    polygons, polygons_thresholded = [], []
    p = 0
    for p1, density in enumerate(vor.densities_zero):
        if density > 0:
            vertices_label = vor.regions[vor.point_region[p1]]
            polygons.append([(x, y) for x, y in vor.vertices[vertices_label]])
            p += 1
            if density >= thr:
                polygons_thresholded.append(p - 1)
    fig, ax = plt.subplots()

    if cmap is 'jet': cmap = plt.cm.jet
    if cmap is 'gray': cmap = plt.cm.gray

    if norm is 'linear':
        values = vor.densities_zero  # vor.densities_zero[vor.densities_zero > 0]
    if norm is 'log':
        values = np.log10(vor.densities_zero[vor.densities_zero > 0])
    cnorm = colors.Normalize(vmin=np.min(values), vmax=np.max(values))
    scalarmap = cm.ScalarMappable(norm=cnorm, cmap=cmap)
    scalarmap.set_array(values)
    colour = [scalarmap.to_rgba(ii) for ii in values]
    coll = PolyCollection(polygons, edgecolors='none')
    ax.add_collection(coll), ax.autoscale_view()
    coll.set_facecolors(colour)
    # cbar = fig.colorbar(coll, ax=ax)   # Add a colorbar for the PolyCollection
    # cbar.ax.set_ylabel('zero-rank density [nm$^{-2}$]', rotation=270); cbar.ax.set_xlabel('$log_{10}$')
    plt.hold(True)
    if show_points is True:
        ax.plot(vor.points[:, 0], vor.points[:, 1], 'k.', markersize=0.2)

    if plot_axis is 'off':
        plt.axis(plot_axis)
        ax.axes.get_xaxis().set_ticks([])
        ax.axes.get_yaxis().set_ticks([])

    ax.set_xlim(vor.points[:, 0].min(), vor.points[:, 0].max())
    ax.set_ylim(vor.points[:, 1].min(), vor.points[:, 1].max())
    ax.set_aspect('equal', adjustable='box')
    fig.hold(hold)

    if thr is not None:
        fig_th, ax_th = plt.subplots()
        polygons_th = [polygons[i] for i in polygons_thresholded]
        coll_th = PolyCollection(polygons_th, color='grey', edgecolors='none')
        ax_th.add_collection(coll_th)  # , ax_th.autoscale_view()
        ax_th.set_xlim(vor.points[:, 0].min(), vor.points[:, 0].max())
        ax_th.set_ylim(vor.points[:, 1].min(), vor.points[:, 1].max())
        ax_th.set_aspect('equal', adjustable='box')

    return fig, ax  # .figure