Beispiel #1
0
    def plotEllipse(self,barotropic=False,k=0,con='M2',scale=1e4,subsample=4,\
            xlims=None,ylims=None,cbarpos=[0.15, 0.15, 0.03, 0.3],**kwargs):
        """
        Plots tidal ellipses on a map
        """
        from matplotlib.collections import EllipseCollection
        
        plt.ioff()
        fig = plt.gcf()
        ax = fig.gca()
        
        iicon = findCon(con,self.frqnames)
        
        if self.clim==None:
            self.clim=[]
            self.clim.append(np.min(self.Amp))
            self.clim.append(np.max(self.Amp))
        if xlims==None or ylims==None:
            xlims=self.xlims 
            ylims=self.ylims

        ell = self.getEllipse(barotropic=barotropic,k=k,con=con)
            
        # Create the ellipse collection
        indices = range(0,self.Nc,subsample)
        widths = [ell[0][ii]*scale for ii in indices]
        heights = [ell[1][ii]*scale for ii in indices]
        angles = [ell[2][ii]*180.0/np.pi for ii in indices]
        #angles = [ell[2][ii] for ii in indices]
        offsets = [(self.xv[ii],self.yv[ii]) for ii in indices]

        
        collection = EllipseCollection(widths,heights,angles,units='xy',\
            offsets=offsets, transOffset=ax.transData,**kwargs)
        
        z=ell[0][indices]
        collection.set_array(np.array(z))
        collection.set_clim(vmin=self.clim[0],vmax=self.clim[1])
        collection.set_edgecolors(collection.to_rgba(np.array(z))) 
        
        ax.set_aspect('equal')
        ax.set_xlim(xlims)
        ax.set_ylim(ylims)

        titlestr='%s - Semi-major Ellipse Amplitude'%(self.frqnames[iicon])
        plt.title(titlestr)
        
        ax.add_collection(collection)
        # Add a decent looking colorbar
        if not cbarpos==None:
            cbaxes = fig.add_axes(cbarpos) 
            cb = fig.colorbar(collection,cax = cbaxes,orientation='vertical')  
            cb.ax.set_title('[m s$^{-1}$]')
    
        plt.sca(ax)
        
        #axcb = fig.colorbar(collection)
        
        return collection
Beispiel #2
0
def display_matrices(ax, grid, texture, scale=None, col=None):
    """Display on a matplotlib axis an ellipse representing a symmetric matrix at each grid element. Each axis of the ellipse corresponds to an eigenvalue and is oriented along its eigenvector. An axis corresponding to a positive eigenvalue is drawn. A 'coffee bean' has a negative eigenvalue smaller in absolute value than its positive eigenvalue. A 'capsule' has a negative eigenvalue larger in absolute value than its positive eigenvalue. A circle is when the two eigenvalues are equal in absolute value."""
    XY = grid.mesh()
    mask = grid.mask()
    #convert the texture back to an array of matrices
    mat = tri2square(texture)
    #compute egenvalues and eigenvectors of texture for each cell of the grid
    evalues, evectors = np.linalg.eigh(mat)
    #width and height are the larger and smaller eigenvalues respectively
    ww = evalues[..., 1][mask]
    hh = evalues[..., 0][mask]
    #angle is given by the angle of the larger eigenvector
    aa = np.rad2deg(np.arctan2(evectors[..., 1, 1], evectors[..., 0, 1]))[mask]
    #sum of the eigenvalues (trace of the matrix)
    trace = ww + hh  #np.where(np.abs(ww)>np.abs(hh), ww, hh)#ww*hh
    #color
    #if col is None:
    #    if trace.ptp()>0:
    #        col = plt.cm.viridis((trace.ravel() - trace.min())/trace.ptp())
    #    else:
    #        col = plt.cm.viridis(np.ones_like(trace))

    if scale is None:
        #scale = 1
        ellipse_areas = np.pi * np.abs(np.prod(evalues, axis=-1))
        rarea = ellipse_areas / grid.areas()
        scale = np.nanpercentile(np.sqrt(rarea[mask]), 90)
        if scale == 0:
            scale = np.nanmax(np.sqrt(rarea[mask]))
            if scale == 0:
                raise ValueError("All matrices are null")
        scale = 1 / scale

    #show ellipses
    ec = EllipseCollection(
        ww * scale,
        hh * scale,
        aa,
        units='xy',
        offsets=XY,
        transOffset=ax.transData,
        edgecolors=col,
        facecolors='none',
    )
    #major and minor axes (only for positive eigenvalues)
    xyps = scale * np.transpose(
        evectors * np.maximum(0, evalues)[..., None, :],
        (0, 1, 3, 2))[mask].reshape(2 * len(ww), 2) * 0.5
    ma = LineCollection([[-xyp, xyp] for xyp in xyps],
                        offsets=np.repeat(XY, 2, axis=0),
                        color=(0.5, 0.5, 0.5))
    if col is None:
        if trace.ptp() > 0:
            ec.set_array(trace)
            ma.set_array(trace[mask.ravel()])
    else:
        ec.set_edgecolors(col)
        ma.set_edgecolors(col)
    ax.add_collection(ec)
    ax.add_collection(ma)
    return ec