def get_grid_line_collection(self, **kwargs): """ Get a LineCollection of the grid """ from matplotlib.collections import LineCollection xmin = self.xedge[0] xmax = self.xedge[-1] ymin = self.yedge[-1] ymax = self.yedge[0] linecol = [] # Vertical lines for j in xrange(self.dis.ncol + 1): x0 = self.xedge[j] x1 = x0 y0 = ymin y1 = ymax x0r, y0r = rotate(x0, y0, self.rotation, 0, self.yedge[0]) x0r += self.xul y0r += self.yul - self.yedge[0] x1r, y1r = rotate(x1, y1, self.rotation, 0, self.yedge[0]) x1r += self.xul y1r += self.yul - self.yedge[0] linecol.append(((x0r, y0r), (x1r, y1r))) #horizontal lines for i in xrange(self.dis.nrow + 1): x0 = xmin x1 = xmax y0 = self.yedge[i] y1 = y0 x0r, y0r = rotate(x0, y0, self.rotation, 0, self.yedge[0]) x0r += self.xul y0r += self.yul - self.yedge[0] x1r, y1r = rotate(x1, y1, self.rotation, 0, self.yedge[0]) x1r += self.xul y1r += self.yul - self.yedge[0] linecol.append(((x0r, y0r), (x1r, y1r))) lc = LineCollection(linecol, **kwargs) return lc
def get_extent(self): """ Get the extent of the rotated and offset grid Return (xmin, xmax, ymin, ymax) """ x0 = self.xedge[0] x1 = self.xedge[-1] y0 = self.yedge[0] y1 = self.yedge[-1] # upper left point x0r, y0r = rotate(x0, y0, self.rotation, 0, self.yedge[0]) x0r += self.xul y0r += self.yul - self.yedge[0] # upper right point x1r, y1r = rotate(x1, y0, self.rotation, 0, self.yedge[0]) x1r += self.xul y1r += self.yul - self.yedge[0] # lower right point x2r, y2r = rotate(x1, y1, self.rotation, 0, self.yedge[0]) x2r += self.xul y2r += self.yul - self.yedge[0] # lower left point x3r, y3r = rotate(x0, y1, self.rotation, 0, self.yedge[0]) x3r += self.xul y3r += self.yul - self.yedge[0] xmin = min(x0r, x1r, x2r, x3r) xmax = max(x0r, x1r, x2r, x3r) ymin = min(y0r, y1r, y2r, y3r) ymax = max(y0r, y1r, y2r, y3r) return (xmin, xmax, ymin, ymax)
def plot_discharge(self, frf, fff, flf=None, head=None, istep=1, jstep=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. istep : int row frequency to plot. (Default is 1.) jstep : int column frequency to plot. (Default is 1.) kwargs : dictionary Keyword arguments passed to plt.quiver() Returns ------- quiver : matplotlib.pyplot.quiver Vectors of specific discharge. """ # 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.ml is not None: lpf = self.ml.get_package('LPF') if lpf is not None: laytyp = lpf.laytyp.array hdry = lpf.hdry bas = self.ml.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) # Select correct slice and step x = self.xcentergrid[::istep, ::jstep] y = self.ycentergrid[::istep, ::jstep] u = qx[self.layer, :, :] v = qy[self.layer, :, :] u = u[::istep, ::jstep] v = v[::istep, ::jstep] # Rotate and plot urot, vrot = rotate(u, v, self.rotation) quiver = self.ax.quiver(x, y, urot, vrot, **kwargs) return quiver
def __init__(self, ax=None, model=None, dis=None, layer=0, xul=None, yul=None, rotation=0., extent=None): self.ml = model self.layer = layer 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 self.layer < 0 or self.layer > self.dis.nlay - 1: s = 'Not a valid layer: {}. Must be between 0 and {}.'.format( self.layer, self.dis.nlay - 1) 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 = np.add.reduce(self.dis.delc.array) 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() self.xgrid, self.ygrid = np.meshgrid(self.xedge, self.yedge) self.xgrid, self.ygrid = rotate(self.xgrid, self.ygrid, self.rotation, 0, self.yedge[0]) self.xgrid += self.xul self.ygrid += self.yul - self.yedge[0] # Create x and y center arrays and meshgrid of centers self.xcenter = self.get_xcenter_array() self.ycenter = self.get_ycenter_array() self.xcentergrid, self.ycentergrid = np.meshgrid(self.xcenter, self.ycenter) self.xcentergrid, self.ycentergrid = rotate(self.xcentergrid, self.ycentergrid, self.rotation, 0, self.yedge[0]) self.xcentergrid += self.xul self.ycentergrid += self.yul - self.yedge[0] # Create model 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
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
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
def __init__(self, ax=None, model=None, dis=None, layer=0, xul=None, yul=None, rotation=0., extent=None): self.ml = model self.layer = layer 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 self.layer < 0 or self.layer > self.dis.nlay - 1: s = 'Not a valid layer: {}. Must be between 0 and {}.'.format( self.layer, self.dis.nlay - 1) 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 = np.add.reduce(self.dis.delc.array) 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() self.xgrid, self.ygrid = np.meshgrid(self.xedge, self.yedge) self.xgrid, self.ygrid = rotate(self.xgrid, self.ygrid, self.rotation, 0, self.yedge[0]) self.xgrid += self.xul self.ygrid += self.yul - self.yedge[0] # Create x and y center arrays and meshgrid of centers self.xcenter = self.get_xcenter_array() self.ycenter = self.get_ycenter_array() self.xcentergrid, self.ycentergrid = np.meshgrid( self.xcenter, self.ycenter) self.xcentergrid, self.ycentergrid = rotate(self.xcentergrid, self.ycentergrid, self.rotation, 0, self.yedge[0]) self.xcentergrid += self.xul self.ycentergrid += self.yul - self.yedge[0] # Create model 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
def plot_discharge(self, frf, fff, flf=None, head=None, istep=1, jstep=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. istep : int row frequency to plot. (Default is 1.) jstep : int column frequency to plot. (Default is 1.) kwargs : dictionary Keyword arguments passed to plt.quiver() Returns ------- quiver : matplotlib.pyplot.quiver Vectors of specific discharge. """ # 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.ml is not None: lpf = self.ml.get_package('LPF') if lpf is not None: laytyp = lpf.laytyp.array hdry = lpf.hdry bas = self.ml.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) # Select correct slice and step x = self.xcentergrid[::istep, ::jstep] y = self.ycentergrid[::istep, ::jstep] u = qx[self.layer, :, :] v = qy[self.layer, :, :] u = u[::istep, ::jstep] v = v[::istep, ::jstep] # Rotate and plot urot, vrot = rotate(u, v, self.rotation) quiver = self.ax.quiver(x, y, urot, vrot, **kwargs) return quiver