Example #1
0
    def set_zpts(self, vs):
        """
        Get an array of z elevations based on minimum of cell elevation
        (self.elev) or passed vs numpy.ndarray

        Parameters
        ----------
        vs : numpy.ndarray
            Three-dimensional array to plot.

        Returns
        -------
        zpts : numpy.ndarray

        """
        zpts = []
        for k in xrange(self.layer0, self.layer1):
            e = self.elev[k, :, :]
            if k < self.dis.nlay:
                v = vs[k, :, :]
                idx = v < e
                e[idx] = v[idx]
            zpts.append(
                plotutil.cell_value_points(self.xpts, self.xedge, self.yedge,
                                           e))
        return np.array(zpts)
Example #2
0
    def set_zpts(self, vs):
        """
        Get an array of z elevations based on minimum of cell elevation
        (self.elev) or passed vs numpy.ndarray

        Parameters
        ----------
        vs : numpy.ndarray
            Three-dimensional array to plot.

        Returns
        -------
        zpts : numpy.ndarray

        """
        zpts = []
        for k in xrange(self.layer0, self.layer1):
            e = self.elev[k, :, :]
            if k < self.dis.nlay:
                v = vs[k, :, :]
                idx =  v < e
                e[idx] = v[idx] 
            zpts.append(plotutil.cell_value_points(self.xpts, self.xedge,
                                                   self.yedge, e))
        return np.array(zpts)
Example #3
0
    def set_zcentergrid(self, vs):
        """
        Get an array of z elevations at the center of a cell that is based 
        on minimum of cell top elevation (self.elev) or passed vs numpy.ndarray

        Parameters
        ----------
        vs : numpy.ndarray
            Three-dimensional array to plot.

        Returns
        -------
        zcentergrid : numpy.ndarray

        """
        vpts = []
        for k in xrange(self.layer0, self.layer1):
            if k < self.dis.nlay:
                e = vs[k, :, :]
            else:
                e = self.elev[k, :, :]
            vpts.append(
                plotutil.cell_value_points(self.xpts, self.xedge, self.yedge,
                                           e))
        vpts = np.array(vpts)

        zcentergrid = []
        nz = 0
        if self.dis.nlay == 1:
            for k in xrange(0, self.zpts.shape[0]):
                nz += 1
                nx = 0
                for i in xrange(0, self.xpts.shape[0], 2):
                    nx += 1
                    vp = vpts[k, i]
                    zp = self.zpts[k, i]
                    if k == 0:
                        if vp < zp:
                            zp = vp
                    zcentergrid.append(zp)
        else:
            for k in xrange(0, self.zpts.shape[0], 2):
                nz += 1
                nx = 0
                for i in xrange(0, self.xpts.shape[0], 2):
                    nx += 1
                    vp = vpts[k, i]
                    ep = self.zpts[k, i]
                    if vp < ep:
                        ep = vp
                    zp = 0.5 * (ep + self.zpts[k + 1, i + 1])
                    zcentergrid.append(zp)
        return np.array(zcentergrid).reshape((nz, nx))
Example #4
0
    def set_zcentergrid(self, vs):
        """
        Get an array of z elevations at the center of a cell that is based 
        on minimum of cell top elevation (self.elev) or passed vs numpy.ndarray

        Parameters
        ----------
        vs : numpy.ndarray
            Three-dimensional array to plot.

        Returns
        -------
        zcentergrid : numpy.ndarray

        """
        vpts = []
        for k in xrange(self.layer0, self.layer1):
            if k < self.dis.nlay:
                e = vs[k, :, :]
            else:
                e = self.elev[k, :, :]
            vpts.append(plotutil.cell_value_points(self.xpts, self.xedge,
                                                   self.yedge, e))
        vpts = np.array(vpts)

        zcentergrid = []
        nz = 0
        if self.dis.nlay == 1:
            for k in xrange(0, self.zpts.shape[0]):
                nz += 1
                nx = 0
                for i in xrange(0, self.xpts.shape[0], 2):
                    nx += 1
                    vp = vpts[k, i]
                    zp = self.zpts[k, i]
                    if k == 0:
                        if vp < zp:
                            zp = vp
                    zcentergrid.append(zp)
        else:
            for k in xrange(0, self.zpts.shape[0], 2):
                nz += 1
                nx = 0
                for i in xrange(0, self.xpts.shape[0], 2):
                    nx += 1
                    vp = vpts[k, i]
                    ep = self.zpts[k, i]
                    if vp < ep:
                        ep = vp
                    zp = 0.5 * (ep + self.zpts[k+1, i+1])
                    zcentergrid.append(zp)
        return np.array(zcentergrid).reshape((nz, nx)) 
Example #5
0
    def plot_array(self, a, masked_values=None, head=None, **kwargs):
        """
        Plot a three-dimensional array as a patch collection.
        
        Parameters
        ----------
        a : numpy.ndarray
            Three-dimensional array to plot.
        masked_values : iterable of floats, ints
            Values to mask.
        head : numpy.ndarray
            Three-dimensional array to set top of patches to the minimum
            of the top of a layer or the head value. Used to create
            patches that conform to water-level elevations.
        **kwargs : dictionary
            keyword arguments passed to matplotlib.collections.PatchCollection

        Returns
        -------
        patches : matplotlib.collections.PatchCollection

        """
        if 'ax' in kwargs:
            ax = kwargs.pop('ax')
        else:
            ax = self.ax

        plotarray = a
        if masked_values is not None:
            for mval in masked_values:
                plotarray = np.ma.masked_equal(plotarray, mval)

        vpts = []
        for k in xrange(self.dis.nlay):
            vpts.append(plotutil.cell_value_points(self.xpts, self.xedge,
                                                   self.yedge,
                                                   plotarray[k, :, :]))
        vpts = np.array(vpts)
            
        if isinstance(head, np.ndarray):
            zpts = self.set_zpts(head)
        else:
            zpts = self.zpts

        if masked_values is not None:
            for mval in masked_values:
                vpts = np.ma.masked_equal(vpts, mval)
        
        pc = self.get_grid_patch_collection(zpts, vpts, **kwargs)
        if pc != None:
            ax.add_collection(pc)
        return pc
Example #6
0
    def plot_array(self, a, masked_values=None, head=None, **kwargs):
        """
        Plot a three-dimensional array as a patch collection.
        
        Parameters
        ----------
        a : numpy.ndarray
            Three-dimensional array to plot.
        masked_values : iterable of floats, ints
            Values to mask.
        head : numpy.ndarray
            Three-dimensional array to set top of patches to the minimum
            of the top of a layer or the head value. Used to create
            patches that conform to water-level elevations.
        **kwargs : dictionary
            keyword arguments passed to matplotlib.collections.PatchCollection

        Returns
        -------
        patches : matplotlib.collections.PatchCollection

        """
        if 'ax' in kwargs:
            ax = kwargs.pop('ax')
        else:
            ax = self.ax

        plotarray = a
        if masked_values is not None:
            for mval in masked_values:
                plotarray = np.ma.masked_equal(plotarray, mval)

        vpts = []
        for k in xrange(self.dis.nlay):
            vpts.append(
                plotutil.cell_value_points(self.xpts, self.xedge, self.yedge,
                                           plotarray[k, :, :]))
        vpts = np.array(vpts)

        if isinstance(head, np.ndarray):
            zpts = self.set_zpts(head)
        else:
            zpts = self.zpts

        if masked_values is not None:
            for mval in masked_values:
                vpts = np.ma.masked_equal(vpts, mval)

        pc = self.get_grid_patch_collection(zpts, vpts, **kwargs)
        if pc != None:
            ax.add_collection(pc)
        return pc
Example #7
0
    def contour_array(self, a, masked_values=None, head=None, **kwargs):
        """
        Contour a three-dimensional array.

        Parameters
        ----------
        a : numpy.ndarray
            Three-dimensional array to plot.
        masked_values : iterable of floats, ints
            Values to mask.
        head : numpy.ndarray
            Three-dimensional array to set top of patches to the minimum
            of the top of a layer or the head value. Used to create
            patches that conform to water-level elevations.
        **kwargs : dictionary
            keyword arguments passed to matplotlib.pyplot.contour

        Returns
        -------
        contour_set : matplotlib.pyplot.contour

        """
        plotarray = a

        vpts = []
        for k in xrange(self.dis.nlay):
            vpts.append(plotutil.cell_value_points(self.xpts, self.xedge,
                                                   self.yedge,
                                                   plotarray[k, :, :]))
        vpts = np.array(vpts)
        vpts = vpts[:, ::2]
        if self.dis.nlay == 1:
            vpts = np.vstack((vpts, vpts))

        if masked_values is not None:
            for mval in masked_values:
                vpts = np.ma.masked_equal(vpts, mval)
            
        if isinstance(head, np.ndarray):
            zcentergrid = self.set_zcentergrid(head)
        else:
            zcentergrid = self.zcentergrid

        contour_set = self.ax.contour(self.xcentergrid, zcentergrid,
                                      vpts, **kwargs)
        return contour_set
Example #8
0
    def contour_array(self, a, masked_values=None, head=None, **kwargs):
        """
        Contour a three-dimensional array.

        Parameters
        ----------
        a : numpy.ndarray
            Three-dimensional array to plot.
        masked_values : iterable of floats, ints
            Values to mask.
        head : numpy.ndarray
            Three-dimensional array to set top of patches to the minimum
            of the top of a layer or the head value. Used to create
            patches that conform to water-level elevations.
        **kwargs : dictionary
            keyword arguments passed to matplotlib.pyplot.contour

        Returns
        -------
        contour_set : matplotlib.pyplot.contour

        """
        plotarray = a

        vpts = []
        for k in xrange(self.dis.nlay):
            vpts.append(
                plotutil.cell_value_points(self.xpts, self.xedge, self.yedge,
                                           plotarray[k, :, :]))
        vpts = np.array(vpts)
        vpts = vpts[:, ::2]
        if self.dis.nlay == 1:
            vpts = np.vstack((vpts, vpts))

        if masked_values is not None:
            for mval in masked_values:
                vpts = np.ma.masked_equal(vpts, mval)

        if isinstance(head, np.ndarray):
            zcentergrid = self.set_zcentergrid(head)
        else:
            zcentergrid = self.zcentergrid

        contour_set = self.ax.contour(self.xcentergrid, zcentergrid, vpts,
                                      **kwargs)
        return contour_set
Example #9
0
    def plot_surface(self, a, masked_values=None, **kwargs):
        """
        Plot a three-dimensional array as lines.

        Parameters
        ----------
        a : numpy.ndarray
            Three-dimensional array to plot.
        masked_values : iterable of floats, ints
            Values to mask.
        **kwargs : dictionary
            keyword arguments passed to matplotlib.pyplot.plot

        Returns
        -------
        plot : list containing matplotlib.plot objects

        """
        if 'ax' in kwargs:
            ax = kwargs.pop('ax')
        else:
            ax = self.ax

        plotarray = a

        vpts = []
        for k in xrange(self.dis.nlay):
            vpts.append(plotutil.cell_value_points(self.xpts, self.xedge,
                                                   self.yedge,
                                                   plotarray[k, :, :]))
        vpts = np.array(vpts)
        
        if masked_values is not None:
            for mval in masked_values:
                vpts = np.ma.masked_equal(vpts, mval)

        plot = []
        for k in xrange(vpts.shape[0]):
            plot.append(ax.plot(self.d, vpts[k, :], **kwargs))
        return plot
Example #10
0
    def plot_surface(self, a, masked_values=None, **kwargs):
        """
        Plot a three-dimensional array as lines.

        Parameters
        ----------
        a : numpy.ndarray
            Three-dimensional array to plot.
        masked_values : iterable of floats, ints
            Values to mask.
        **kwargs : dictionary
            keyword arguments passed to matplotlib.pyplot.plot

        Returns
        -------
        plot : list containing matplotlib.plot objects

        """
        if 'ax' in kwargs:
            ax = kwargs.pop('ax')
        else:
            ax = self.ax

        plotarray = a

        vpts = []
        for k in xrange(self.dis.nlay):
            vpts.append(
                plotutil.cell_value_points(self.xpts, self.xedge, self.yedge,
                                           plotarray[k, :, :]))
        vpts = np.array(vpts)

        if masked_values is not None:
            for mval in masked_values:
                vpts = np.ma.masked_equal(vpts, mval)

        plot = []
        for k in xrange(vpts.shape[0]):
            plot.append(ax.plot(self.d, vpts[k, :], **kwargs))
        return plot
Example #11
0
    def plot_discharge(self, frf, fff, flf=None, head=None,
                         kstep=1, hstep=1,
                         **kwargs):
        """
        Use quiver to plot vectors.

        Parameters
        ----------
        frf : numpy.ndarray
            MODFLOW's 'flow right face'
        fff : numpy.ndarray
            MODFLOW's 'flow front face'
        flf : numpy.ndarray
            MODFLOW's 'flow lower face' (Default is None.)
        head : numpy.ndarray
            MODFLOW's head array.  If not provided, then will assume confined
            conditions in order to calculated saturated thickness.
        kstep : int
            layer frequency to plot. (Default is 1.)
        hstep : int
            horizontal frequency to plot. (Default is 1.)
        kwargs : dictionary
            Keyword arguments passed to plt.quiver()

        Returns
        -------
        quiver : matplotlib.pyplot.quiver
            Vectors

        """

        # Calculate specific discharge
        delr = self.dis.delr.array
        delc = self.dis.delc.array
        top = self.dis.top.array
        botm = self.dis.botm.array
        nlay, nrow, ncol = botm.shape
        laytyp = None
        hnoflo = 999.
        hdry = 999.
        if self.model is not None:
            lpf = self.model.get_package('LPF')
            if lpf is not None:
                laytyp = lpf.laytyp.array
                hdry = lpf.hdry
            bas = self.model.get_package('BAS6')
            if bas is not None:
                hnoflo = bas.hnoflo

        # If no access to head or laytyp, then calculate confined saturated
        # thickness by setting laytyp to zeros
        if head is None or laytyp is None:
            head = np.zeros(botm.shape, np.float32)
            laytyp = np.zeros((nlay), dtype=np.int)
        sat_thk = plotutil.saturated_thickness(head, top, botm, laytyp,
                                               [hnoflo, hdry])

        # Calculate specific discharge
        qx, qy, qz = plotutil.centered_specific_discharge(frf, fff, flf, delr,
                                                          delc, sat_thk)
        
        if qz == None:
            qz = np.zeros((qx.shape), dtype=np.float)
        
        # Select correct specific discharge direction
        if self.direction == 'x':
            u = -qx[:, :, :]
            u2 = -qy[:, :, :]
            v = qz[:, :, :]
        elif self.direction == 'y':
            u = -qy[:, :, :]
            u2 = -qx[:, :, :]
            v = qz[:, :, :]
        elif self.direction == 'xy':
            print 'csplot_discharge does not support arbitrary cross-sections'
            return None
            
        if isinstance(head, np.ndarray):
            zcentergrid = self.set_zcentergrid(head)
        else:
            zcentergrid = self.zcentergrid
        
        if nlay == 1:
            x = []
            z = []
            for k in xrange(1):
                for i in xrange(self.xcentergrid.shape[1]):
                    x.append(self.xcentergrid[k, i])
                    z.append(0.5 * (zcentergrid[k, i] + zcentergrid[k+1, i]))
            x = np.array(x).reshape((1,self.xcentergrid.shape[1]))
            z = np.array(z).reshape((1,self.xcentergrid.shape[1]))
        else:
            x = self.xcentergrid
            z = zcentergrid
            
        upts = []
        u2pts = []
        vpts = []
        for k in xrange(self.dis.nlay):
            upts.append(plotutil.cell_value_points(self.xpts, self.xedge,
                                                   self.yedge, u[k, :, :]))
            u2pts.append(plotutil.cell_value_points(self.xpts, self.xedge,
                                                    self.yedge, u2[k, :, :]))
            vpts.append(plotutil.cell_value_points(self.xpts, self.xedge,
                                                   self.yedge, v[k, :, :]))
        upts = np.array(upts)
        u2pts = np.array(u2pts)
        vpts = np.array(vpts)
        
        x = x[::kstep, ::hstep]
        z = z[::kstep, ::hstep]
        upts = upts[::kstep, ::hstep]
        u2pts = u2pts[::kstep, ::hstep]
        vpts = vpts[::kstep, ::hstep]
            
        N = np.sqrt(upts**2. + u2pts**2. + vpts**2.)
        idx = N > 0.
        upts[idx] /= N[idx]
        u2pts[idx] /= N[idx]
        vpts[idx] /= N[idx]
        
        # plot the vectors
        quiver = self.ax.quiver(x, z, upts, vpts, **kwargs)

        return quiver
Example #12
0
    def __init__(self, ax=None, model=None, dis=None, line=None,
                 xul=None, yul=None, rotation=0., extent=None):
        self.model = model
        if dis is None:
            if model is None:
                raise Exception('Cannot find discretization package')
            else:
                self.dis = model.get_package('DIS')
        else:
            self.dis = dis
            
        if line == None:
            s = 'line must be specified.'
            raise Exception(s)
        
        linekeys = [linekeys.lower() for linekeys in line.keys()]
        
        if len(linekeys) < 1:
            s = 'only row, column, or line can be specified in line dictionary.\n'
            s += 'keys specified: '
            for k in linekeys:
                s += '{} '.format(k)
            raise Exception(s)
        
        if 'row' in linekeys and 'column' in linekeys: 
            s = 'row and column cannot both be specified in line dictionary.'
            raise Exception(s)
        
        if 'row' in linekeys and 'line' in linekeys: 
            s = 'row and line cannot both be specified in line dictionary.'
            raise Exception(s)
        
        if 'column' in linekeys and 'line' in linekeys: 
            s = 'column and line cannot both be specified in line dictionary.'
            raise Exception(s)

        if ax is None:
            self.ax = plt.gca()
        else:
            self.ax = ax

        # Set origin and rotation
        if xul is None:
            self.xul = 0.
        else:
            self.xul = xul
        if yul is None:
            self.yul = 0
        else:
            self.yul = yul
        self.rotation = -rotation * np.pi / 180.

        # Create edge arrays and meshgrid for pcolormesh
        self.xedge = self.get_xedge_array()
        self.yedge = self.get_yedge_array()

        # Create x and y center arrays and meshgrid of centers
        self.xcenter = self.get_xcenter_array()
        self.ycenter = self.get_ycenter_array()
                                                         
        onkey = line.keys()[0]                      
        if 'row' in linekeys:
            self.direction = 'x'
            pts = [(self.xedge[0]+0.1, self.ycenter[int(line[onkey])]-0.1), 
                   (self.xedge[-1]-0.1, self.ycenter[int(line[onkey])]+0.1)]
        elif 'column' in linekeys:
            self.direction = 'y'
            pts = [(self.xcenter[int(line[onkey])]+0.1, self.yedge[0]-0.1), 
                   (self.xcenter[int(line[onkey])]-0.1, self.yedge[-1]+0.1)]
        else:
            self.direction = 'xy'
            verts = line[onkey]
            xp = []
            yp = []
            for [v1, v2] in verts:
                xp.append(v1)
                yp.append(v2)
            xp, yp = np.array(xp), np.array(yp)
            # remove offset and rotation from line
            xp -= self.xul
            yp -= self.yul
            xp, yp = rotate(xp, yp, -self.rotation, 0, self.yedge[0])
            pts = []
            for xt, yt in zip(xp, yp):
                pts.append((xt, yt))
        # convert pts list to numpy array
        self.pts = np.array(pts)
            
        # get points along the line
        self.xpts = plotutil.line_intersect_grid(self.pts, self.xedge,
                                                 self.yedge)
        if len(self.xpts) < 2:
            s = 'cross-section cannot be created\n.'
            s += '   less than 2 points intersect the model grid\n'
            s += '   {} points intersect the grid.'.format(len(self.xpts))
            raise Exception(s)           
        
        # set horizontal distance
        d = []
        for v in self.xpts:
            d.append(v[2])
        self.d = np.array(d)

        top = self.dis.top.array
        botm = self.dis.botm.array
        elev = [top.copy()]
        for k in xrange(self.dis.nlay):
            elev.append(botm[k, :, :])
        
        self.elev = np.array(elev)
        self.layer0 = 0
        self.layer1 = self.dis.nlay + 1
        
        zpts = []
        for k in xrange(self.layer0, self.layer1):
            zpts.append(plotutil.cell_value_points(self.xpts, self.xedge,
                                                   self.yedge,
                                                   self.elev[k, :, :]))
        self.zpts = np.array(zpts)
        
        xcentergrid = []
        zcentergrid = []
        nz = 0
        if self.dis.nlay == 1:
            for k in xrange(0, self.zpts.shape[0]):
                nz += 1
                nx = 0
                for i in xrange(0, self.xpts.shape[0], 2):
                    try:
                        xp = 0.5 * (self.xpts[i][2] + self.xpts[i+1][2])
                        zp = self.zpts[k, i]
                        xcentergrid.append(xp)
                        zcentergrid.append(zp)
                        nx += 1
                    except:
                        break
        else:
            for k in xrange(0, self.zpts.shape[0]-1):
                nz += 1
                nx = 0
                for i in xrange(0, self.xpts.shape[0], 2):
                    try:
                        xp = 0.5 * (self.xpts[i][2] + self.xpts[i+1][2])
                        zp = 0.5 * (self.zpts[k, i] + self.zpts[k+1, i+1])
                        xcentergrid.append(xp)
                        zcentergrid.append(zp)
                        nx += 1
                    except:
                        break
        self.xcentergrid = np.array(xcentergrid).reshape((nz, nx))
        self.zcentergrid = np.array(zcentergrid).reshape((nz, nx))
        
        # Create cross-section extent
        if extent is None:
            self.extent = self.get_extent()
        else:
            self.extent = extent

        # Set axis limits
        self.ax.set_xlim(self.extent[0], self.extent[1])
        self.ax.set_ylim(self.extent[2], self.extent[3])

        return
Example #13
0
    def plot_fill_between(self, a, colors=['blue', 'red'],
                            masked_values=None, **kwargs):
        """
        Plot a three-dimensional array as lines.

        Parameters
        ----------
        a : numpy.ndarray
            Three-dimensional array to plot.
        masked_values : iterable of floats, ints
            Values to mask.
        **kwargs : dictionary
            keyword arguments passed to matplotlib.pyplot.plot

        Returns
        -------
        plot : list containing matplotlib.fillbetween objects

        """
        if 'ax' in kwargs:
            ax = kwargs.pop('ax')
        else:
            ax = self.ax

        plotarray = a

        vpts = []
        for k in xrange(self.dis.nlay):
            vpts.append(plotutil.cell_value_points(self.xpts, self.xedge,
                                                   self.yedge,
                                                   plotarray[k, :, :]))
        vpts = np.ma.array(vpts, mask=False)
        
        if masked_values is not None:
            for mval in masked_values:
                vpts = np.ma.masked_equal(vpts, mval)
        idxm = np.ma.getmask(vpts)

        plot = []
        for k in xrange(self.dis.nlay):
            idxmk = idxm[k, :]
            v = vpts[k, :]
            y1 = self.zpts[k, :]
            y2 = self.zpts[k+1, :]
            #--make sure y1 is not below y2
            idx = y1 < y2
            y1[idx] = y2[idx]
            #--make sure v is not below y2
            idx = v < y2
            v[idx] = y2[idx]
            #--make sure v is not above y1
            idx = v > y1
            v[idx] = y1[idx]
            #--set y2 to v
            y2 = v
            #--mask cells
            y1[idxmk] = np.nan
            y2[idxmk] = np.nan
            plot.append(ax.fill_between(self.d, y1=y1, y2=y2, color=colors[0],
                                        **kwargs))
            y1 = y2
            y2 = self.zpts[k+1, :]
            y2[idxmk] = np.nan
            plot.append(ax.fill_between(self.d, y1=y1, y2=y2, color=colors[1],
                                        **kwargs))
        return plot
Example #14
0
    def plot_discharge(self,
                       frf,
                       fff,
                       flf=None,
                       head=None,
                       kstep=1,
                       hstep=1,
                       **kwargs):
        """
        Use quiver to plot vectors.

        Parameters
        ----------
        frf : numpy.ndarray
            MODFLOW's 'flow right face'
        fff : numpy.ndarray
            MODFLOW's 'flow front face'
        flf : numpy.ndarray
            MODFLOW's 'flow lower face' (Default is None.)
        head : numpy.ndarray
            MODFLOW's head array.  If not provided, then will assume confined
            conditions in order to calculated saturated thickness.
        kstep : int
            layer frequency to plot. (Default is 1.)
        hstep : int
            horizontal frequency to plot. (Default is 1.)
        kwargs : dictionary
            Keyword arguments passed to plt.quiver()

        Returns
        -------
        quiver : matplotlib.pyplot.quiver
            Vectors

        """

        # Calculate specific discharge
        delr = self.dis.delr.array
        delc = self.dis.delc.array
        top = self.dis.top.array
        botm = self.dis.botm.array
        nlay, nrow, ncol = botm.shape
        laytyp = None
        hnoflo = 999.
        hdry = 999.
        if self.model is not None:
            lpf = self.model.get_package('LPF')
            if lpf is not None:
                laytyp = lpf.laytyp.array
                hdry = lpf.hdry
            bas = self.model.get_package('BAS6')
            if bas is not None:
                hnoflo = bas.hnoflo

        # If no access to head or laytyp, then calculate confined saturated
        # thickness by setting laytyp to zeros
        if head is None or laytyp is None:
            head = np.zeros(botm.shape, np.float32)
            laytyp = np.zeros((nlay), dtype=np.int)
        sat_thk = plotutil.saturated_thickness(head, top, botm, laytyp,
                                               [hnoflo, hdry])

        # Calculate specific discharge
        qx, qy, qz = plotutil.centered_specific_discharge(
            frf, fff, flf, delr, delc, sat_thk)

        if qz == None:
            qz = np.zeros((qx.shape), dtype=np.float)

        # Select correct specific discharge direction
        if self.direction == 'x':
            u = -qx[:, :, :]
            u2 = -qy[:, :, :]
            v = qz[:, :, :]
        elif self.direction == 'y':
            u = -qy[:, :, :]
            u2 = -qx[:, :, :]
            v = qz[:, :, :]
        elif self.direction == 'xy':
            print 'csplot_discharge does not support arbitrary cross-sections'
            return None

        if isinstance(head, np.ndarray):
            zcentergrid = self.set_zcentergrid(head)
        else:
            zcentergrid = self.zcentergrid

        if nlay == 1:
            x = []
            z = []
            for k in xrange(1):
                for i in xrange(self.xcentergrid.shape[1]):
                    x.append(self.xcentergrid[k, i])
                    z.append(0.5 * (zcentergrid[k, i] + zcentergrid[k + 1, i]))
            x = np.array(x).reshape((1, self.xcentergrid.shape[1]))
            z = np.array(z).reshape((1, self.xcentergrid.shape[1]))
        else:
            x = self.xcentergrid
            z = zcentergrid

        upts = []
        u2pts = []
        vpts = []
        for k in xrange(self.dis.nlay):
            upts.append(
                plotutil.cell_value_points(self.xpts, self.xedge, self.yedge,
                                           u[k, :, :]))
            u2pts.append(
                plotutil.cell_value_points(self.xpts, self.xedge, self.yedge,
                                           u2[k, :, :]))
            vpts.append(
                plotutil.cell_value_points(self.xpts, self.xedge, self.yedge,
                                           v[k, :, :]))
        upts = np.array(upts)
        u2pts = np.array(u2pts)
        vpts = np.array(vpts)

        x = x[::kstep, ::hstep]
        z = z[::kstep, ::hstep]
        upts = upts[::kstep, ::hstep]
        u2pts = u2pts[::kstep, ::hstep]
        vpts = vpts[::kstep, ::hstep]

        N = np.sqrt(upts**2. + u2pts**2. + vpts**2.)
        idx = N > 0.
        upts[idx] /= N[idx]
        u2pts[idx] /= N[idx]
        vpts[idx] /= N[idx]

        # plot the vectors
        quiver = self.ax.quiver(x, z, upts, vpts, **kwargs)

        return quiver
Example #15
0
    def __init__(self,
                 ax=None,
                 model=None,
                 dis=None,
                 line=None,
                 xul=None,
                 yul=None,
                 rotation=0.,
                 extent=None):
        self.model = model
        if dis is None:
            if model is None:
                raise Exception('Cannot find discretization package')
            else:
                self.dis = model.get_package('DIS')
        else:
            self.dis = dis

        if line == None:
            s = 'line must be specified.'
            raise Exception(s)

        linekeys = [linekeys.lower() for linekeys in line.keys()]

        if len(linekeys) < 1:
            s = 'only row, column, or line can be specified in line dictionary.\n'
            s += 'keys specified: '
            for k in linekeys:
                s += '{} '.format(k)
            raise Exception(s)

        if 'row' in linekeys and 'column' in linekeys:
            s = 'row and column cannot both be specified in line dictionary.'
            raise Exception(s)

        if 'row' in linekeys and 'line' in linekeys:
            s = 'row and line cannot both be specified in line dictionary.'
            raise Exception(s)

        if 'column' in linekeys and 'line' in linekeys:
            s = 'column and line cannot both be specified in line dictionary.'
            raise Exception(s)

        if ax is None:
            self.ax = plt.gca()
        else:
            self.ax = ax

        # Set origin and rotation
        if xul is None:
            self.xul = 0.
        else:
            self.xul = xul
        if yul is None:
            self.yul = 0
        else:
            self.yul = yul
        self.rotation = -rotation * np.pi / 180.

        # Create edge arrays and meshgrid for pcolormesh
        self.xedge = self.get_xedge_array()
        self.yedge = self.get_yedge_array()

        # Create x and y center arrays and meshgrid of centers
        self.xcenter = self.get_xcenter_array()
        self.ycenter = self.get_ycenter_array()

        onkey = line.keys()[0]
        if 'row' in linekeys:
            self.direction = 'x'
            pts = [(self.xedge[0] + 0.1, self.ycenter[int(line[onkey])] - 0.1),
                   (self.xedge[-1] - 0.1, self.ycenter[int(line[onkey])] + 0.1)
                   ]
        elif 'column' in linekeys:
            self.direction = 'y'
            pts = [(self.xcenter[int(line[onkey])] + 0.1, self.yedge[0] - 0.1),
                   (self.xcenter[int(line[onkey])] - 0.1, self.yedge[-1] + 0.1)
                   ]
        else:
            self.direction = 'xy'
            verts = line[onkey]
            xp = []
            yp = []
            for [v1, v2] in verts:
                xp.append(v1)
                yp.append(v2)
            xp, yp = np.array(xp), np.array(yp)
            # remove offset and rotation from line
            xp -= self.xul
            yp -= self.yul
            xp, yp = rotate(xp, yp, -self.rotation, 0, self.yedge[0])
            pts = []
            for xt, yt in zip(xp, yp):
                pts.append((xt, yt))
        # convert pts list to numpy array
        self.pts = np.array(pts)

        # get points along the line
        self.xpts = plotutil.line_intersect_grid(self.pts, self.xedge,
                                                 self.yedge)
        if len(self.xpts) < 2:
            s = 'cross-section cannot be created\n.'
            s += '   less than 2 points intersect the model grid\n'
            s += '   {} points intersect the grid.'.format(len(self.xpts))
            raise Exception(s)

        # set horizontal distance
        d = []
        for v in self.xpts:
            d.append(v[2])
        self.d = np.array(d)

        top = self.dis.top.array
        botm = self.dis.botm.array
        elev = [top.copy()]
        for k in xrange(self.dis.nlay):
            elev.append(botm[k, :, :])

        self.elev = np.array(elev)
        self.layer0 = 0
        self.layer1 = self.dis.nlay + 1

        zpts = []
        for k in xrange(self.layer0, self.layer1):
            zpts.append(
                plotutil.cell_value_points(self.xpts, self.xedge, self.yedge,
                                           self.elev[k, :, :]))
        self.zpts = np.array(zpts)

        xcentergrid = []
        zcentergrid = []
        nz = 0
        if self.dis.nlay == 1:
            for k in xrange(0, self.zpts.shape[0]):
                nz += 1
                nx = 0
                for i in xrange(0, self.xpts.shape[0], 2):
                    try:
                        xp = 0.5 * (self.xpts[i][2] + self.xpts[i + 1][2])
                        zp = self.zpts[k, i]
                        xcentergrid.append(xp)
                        zcentergrid.append(zp)
                        nx += 1
                    except:
                        break
        else:
            for k in xrange(0, self.zpts.shape[0] - 1):
                nz += 1
                nx = 0
                for i in xrange(0, self.xpts.shape[0], 2):
                    try:
                        xp = 0.5 * (self.xpts[i][2] + self.xpts[i + 1][2])
                        zp = 0.5 * (self.zpts[k, i] + self.zpts[k + 1, i + 1])
                        xcentergrid.append(xp)
                        zcentergrid.append(zp)
                        nx += 1
                    except:
                        break
        self.xcentergrid = np.array(xcentergrid).reshape((nz, nx))
        self.zcentergrid = np.array(zcentergrid).reshape((nz, nx))

        # Create cross-section extent
        if extent is None:
            self.extent = self.get_extent()
        else:
            self.extent = extent

        # Set axis limits
        self.ax.set_xlim(self.extent[0], self.extent[1])
        self.ax.set_ylim(self.extent[2], self.extent[3])

        return
Example #16
0
    def plot_fill_between(self,
                          a,
                          colors=['blue', 'red'],
                          masked_values=None,
                          **kwargs):
        """
        Plot a three-dimensional array as lines.

        Parameters
        ----------
        a : numpy.ndarray
            Three-dimensional array to plot.
        masked_values : iterable of floats, ints
            Values to mask.
        **kwargs : dictionary
            keyword arguments passed to matplotlib.pyplot.plot

        Returns
        -------
        plot : list containing matplotlib.fillbetween objects

        """
        if 'ax' in kwargs:
            ax = kwargs.pop('ax')
        else:
            ax = self.ax

        plotarray = a

        vpts = []
        for k in xrange(self.dis.nlay):
            vpts.append(
                plotutil.cell_value_points(self.xpts, self.xedge, self.yedge,
                                           plotarray[k, :, :]))
        vpts = np.ma.array(vpts, mask=False)

        if masked_values is not None:
            for mval in masked_values:
                vpts = np.ma.masked_equal(vpts, mval)
        idxm = np.ma.getmask(vpts)

        plot = []
        for k in xrange(self.dis.nlay):
            idxmk = idxm[k, :]
            v = vpts[k, :]
            y1 = self.zpts[k, :]
            y2 = self.zpts[k + 1, :]
            #--make sure y1 is not below y2
            idx = y1 < y2
            y1[idx] = y2[idx]
            #--make sure v is not below y2
            idx = v < y2
            v[idx] = y2[idx]
            #--make sure v is not above y1
            idx = v > y1
            v[idx] = y1[idx]
            #--set y2 to v
            y2 = v
            #--mask cells
            y1[idxmk] = np.nan
            y2[idxmk] = np.nan
            plot.append(
                ax.fill_between(self.d,
                                y1=y1,
                                y2=y2,
                                color=colors[0],
                                **kwargs))
            y1 = y2
            y2 = self.zpts[k + 1, :]
            y2[idxmk] = np.nan
            plot.append(
                ax.fill_between(self.d,
                                y1=y1,
                                y2=y2,
                                color=colors[1],
                                **kwargs))
        return plot