def to_sfr(self, roughness=0.037, streambed_thickness=1, streambedK=1, icalc=1, iupseg=0, iprior=0, nstrpts=0, flow=0, runoff=0, etsw=0, pptsw=0, roughch=0, roughbk=0, cdepth=0, fdepth=0, awdth=0, bwdth=0): # create a working dataframe self.df = self.fl[self.fl_cols].join(self.pfvaa[self.pfvaa_cols], how='inner') print '\nclipping flowlines to active area...' inside = [g.intersects(self.domain) for g in self.df.geometry] self.df = self.df.ix[inside].copy() self.df.sort('COMID', inplace=True) flowline_geoms = self.df.geometry.tolist() grid_geoms = self.grid.geometry.tolist() print "intersecting flowlines with grid cells..." grid_intersections = GISops.intersect_rtree(grid_geoms, flowline_geoms) print "setting up segments..." self.list_updown_comids() self.assign_segments() fl_segments = self.df.segment.tolist() fl_comids = self.df.COMID.tolist() m1 = make_mat1(flowline_geoms, fl_segments, fl_comids, grid_intersections, grid_geoms) print "computing widths..." m1['length'] = np.array([g.length for g in m1.geometry]) lengths = m1[['segment', 'length']].copy() groups = lengths.groupby('segment') reach_asums = np.concatenate([np.cumsum(grp.length.values[::-1])[::-1] for s, grp in groups]) segment_asums = np.array([self.df.ArbolateSu.values[s-1] for s in m1.segment.values]) reach_asums = -1 * self.to_km * reach_asums + segment_asums # arbolate sums are computed in km width = width_from_arbolate(reach_asums) # widths are returned in m if self.GISunits != 'm': width = width / 0.3048 m1['width'] = width * self.mf_units_mult m1['length'] = m1.length * self.mf_units_mult m1['roughness'] = roughness m1['sbthick'] = streambed_thickness m1['sbK'] = streambedK m1['sbtop'] = 0 if self.nrows is not None: m1['row'] = np.floor(m1.node / self.ncols) + 1 if self.ncols is not None: column = m1.node.values % self.ncols column[column == 0] = self.ncols # last column has remainder of 0 m1['column'] = column m1['layer'] = 1 self.m1 = m1 print "setting up Mat2..." self.m2 = self.df[['segment', 'outseg']] self.m2['icalc'] = icalc self.m2.index = self.m2.segment print 'Done'
def to_sfr( self, roughness=0.037, streambed_thickness=1, streambedK=1, icalc=1, iupseg=0, iprior=0, nstrpts=0, flow=0, runoff=0, etsw=0, pptsw=0, roughch=0, roughbk=0, cdepth=0, fdepth=0, awdth=0, bwdth=0, ): # create a working dataframe self.df = self.fl[self.fl_cols].join(self.pfvaa[self.pfvaa_cols], how="inner") print "\nclipping flowlines to active area..." inside = [g.intersects(self.domain) for g in self.df.geometry] self.df = self.df.ix[inside].copy() self.df.sort("COMID", inplace=True) flowline_geoms = self.df.geometry.tolist() grid_geoms = self.grid.geometry.tolist() print "intersecting flowlines with grid cells..." grid_intersections = GISops.intersect_rtree(grid_geoms, flowline_geoms) print "setting up segments..." self.list_updown_comids() self.assign_segments() fl_segments = self.df.segment.tolist() fl_comids = self.df.COMID.tolist() m1 = make_mat1(flowline_geoms, fl_segments, fl_comids, grid_intersections, grid_geoms) print "computing widths..." m1["length"] = np.array([g.length for g in m1.geometry]) lengths = m1[["segment", "length"]].copy() groups = lengths.groupby("segment") reach_asums = np.concatenate([np.cumsum(grp.length.values[::-1])[::-1] for s, grp in groups]) segment_asums = np.array([self.df.ArbolateSu.values[s - 1] for s in m1.segment.values]) reach_asums = -1 * self.to_km * reach_asums + segment_asums # arbolate sums are computed in km width = width_from_arbolate(reach_asums) # widths are returned in m if self.GISunits != "m": width = width / 0.3048 m1["width"] = width * self.mf_units_mult m1["length"] = m1.length * self.mf_units_mult m1["roughness"] = roughness m1["sbthick"] = streambed_thickness m1["sbK"] = streambedK m1["sbtop"] = 0 if self.nrows is not None: m1["row"] = np.floor(m1.node / self.ncols) + 1 if self.ncols is not None: column = m1.node.values % self.ncols column[column == 0] = self.ncols # last column has remainder of 0 m1["column"] = column m1["layer"] = 1 self.m1 = m1 print "setting up Mat2..." self.m2 = self.df[["segment", "outseg"]] self.m2["icalc"] = icalc self.m2.index = self.m2.segment print "Done"
print 'building UZF package IRUNBND array from {}'.format(MFgrid) MFgrid_joined = GISio.shp2df(os.path.join(os.getcwd(), 'MFgrid_catchments.shp'), geometry=True) MFgrid_joined.index = MFgrid_joined.node nrows, ncols = np.max(MFgrid_joined.row), np.max(MFgrid_joined.column) # make new column of SFR segment for each grid cell MFgrid_joined['segment'] = MFgrid_joined.FEATUREID.apply( segments_dict.get).fillna(0) print 'writing {}'.format(out_IRUNBND) # should add code to allow for a dataframe that only includes a subset of model cells # (could build a DF of zeros for each cellnum, and then merge with DF containing UZF cells, replacing the zeros for those cells IRUNBND = np.reshape(MFgrid_joined['segment'].sort_index().values, (nrows, ncols)) np.savetxt(out_IRUNBND, IRUNBND, fmt='%i', delimiter=' ') print 'writing {}'.format(out_IRUNBND_shp) #df, shpname, geo_column, prj GISio.df2shp(MFgrid_joined, os.path.join(os.getcwd(), 'MFgrid_segments.shp'), 'geometry', os.path.join(os.getcwd(), 'MFgrid_catchments.shp')[:-4] + '.prj') MFgrid_joined_dissolved = GISops.dissolve_df(MFgrid_joined, 'segment') GISio.df2shp(MFgrid_joined_dissolved, os.path.join(os.getcwd(), 'MFgrid_segments_dissolved.shp'), 'geometry', os.path.join(os.getcwd(), 'MFgrid_catchments.shp')[:-4] + '.prj')
segments_dict[cmt] = segment # can also use values_count() to get a frequency table for segments (reaches) in each catchment print 'building UZF package IRUNBND array from {}'.format(MFgrid) MFgrid_joined = GISio.shp2df(os.path.join(os.getcwd(), 'MFgrid_catchments.shp'), geometry=True) MFgrid_joined.index = MFgrid_joined.node nrows, ncols = np.max(MFgrid_joined.row), np.max(MFgrid_joined.column) # make new column of SFR segment for each grid cell MFgrid_joined['segment'] = MFgrid_joined.FEATUREID.apply(segments_dict.get).fillna(0) print 'writing {}'.format(out_IRUNBND) # should add code to allow for a dataframe that only includes a subset of model cells # (could build a DF of zeros for each cellnum, and then merge with DF containing UZF cells, replacing the zeros for those cells IRUNBND = np.reshape(MFgrid_joined['segment'].sort_index().values, (nrows, ncols)) np.savetxt(out_IRUNBND, IRUNBND, fmt='%i', delimiter=' ') print 'writing {}'.format(out_IRUNBND_shp) #df, shpname, geo_column, prj GISio.df2shp(MFgrid_joined, os.path.join(os.getcwd(), 'MFgrid_segments.shp'), 'geometry', os.path.join(os.getcwd(), 'MFgrid_catchments.shp')[:-4]+'.prj') MFgrid_joined_dissolved = GISops.dissolve_df(MFgrid_joined, 'segment') GISio.df2shp(MFgrid_joined_dissolved, os.path.join(os.getcwd(), 'MFgrid_segments_dissolved.shp'), 'geometry', os.path.join(os.getcwd(), 'MFgrid_catchments.shp')[:-4]+'.prj')
def join_SFR_out2streams(self, use_arcpy=True): # get model info try: DX, DY, NLAY, NROW, NCOL, i = disutil.read_meta_data(self.DISfile) except: raise IOError("Cannot read MODFLOW DIS file {0}".format(self.DISfile)) print "\naggregating flow information by cellnum..." indata = open(self.SFR_out).readlines() for line in indata[8:]: line = line.strip().split() # Kludge! terminates with blank line (only reads stress per. 1) # need to add support for transient. if len(line) == 0: break r, c = int(line[1]), int(line[2]) cellnum = (r-1)*NCOL + c seg_rch = "{0} {1}; ".format(line[3], line[4]) flow = 0.5 * (float(line[5]) + float(line[7])) loss = float(line[6]) overland = float(line[8]) stage = float(line[11]) depth = float(line[12]) try: existingflow = self.flow_by_cellnum[cellnum] seg_rch_info = self.seg_rch_by_cellnum[cellnum] except KeyError: existingflow = 0 seg_rch_info = 'segs rchs: ' # determine state if flow == 0: state = 'dry' elif loss > 0: state = 'losing' elif loss < 0: state = 'gaining' else: print 'Stream reach in cell {} has flow, but no interaction with aquifer.'.format(cellnum) self.flow_by_cellnum[cellnum] = existingflow + flow self.seg_rch_by_cellnum[cellnum] = seg_rch_info + seg_rch self.loss_by_cellnum[cellnum] = loss self.state_by_cellnum[cellnum] = state self.overland_by_cellnum[cellnum] = overland self.stage_by_cellnum[cellnum] = stage self.depth_by_cellnum[cellnum] = depth # write to temporary output file ofp = open(os.path.join(self.outpath, 'temp.csv'), 'w') ofp.write('{},row,column,seg_reach,flow,loss,overland,state,stage,depth\n'.format(self.node_num_attribute)) for cn in self.flow_by_cellnum.keys(): ofp.write('{0},{1},{2},"{3}",{4:.6e},{5},{6},{7},{8},{9}\n'.format(cn, 1, 1, self.seg_rch_by_cellnum[cn], self.flow_by_cellnum[cn], self.loss_by_cellnum[cn], self.overland_by_cellnum[cn], self.state_by_cellnum[cn], self.stage_by_cellnum[cn], self.depth_by_cellnum[cn])) ofp.close() outfile = os.path.join(self.outpath, "{0}.shp".format(self.SFR_out[:-4])) if use_arcpy: try: import arcpy import SFR_arcpy except: print 'module arcpy not found!' # make feature/table layers arcpy.env.workspace = self.outpath arcpy.env.overwriteOutput = True arcpy.CopyFeatures_management(self.streams_shp, self.streams_shp[:-4]+'_backup.shp') arcpy.MakeFeatureLayer_management(self.streams_shp[:-4]+'_backup.shp', "streams") arcpy.CopyRows_management(os.path.join(self.outpath, 'temp.csv'), os.path.join(self.outpath, 'temp.dbf')) # drop all fields except for cellnum from stream linework Fields = arcpy.ListFields("streams") Fields = [f.name for f in Fields if f.name not in ["FID", "Shape", self.node_num_attribute]] if len(Fields) > 0: arcpy.DeleteField_management("streams", Fields) SFR_arcpy.general_join(outfile, "streams", self.node_num_attribute, "temp.dbf", self.node_num_attribute, keep_common=True) else: import sys sys.path.append('../../GIS_utils') try: import GISops except: print 'GIS_utils.GISops not found!' GISops.join_csv2shp(self.streams_shp, self.node_num_attribute, os.path.join(self.outpath, 'temp.csv'), self.node_num_attribute, outfile, how='inner')
def join_SFR_out2streams(self, use_arcpy=True): # get model info try: DX, DY, NLAY, NROW, NCOL, i = disutil.read_meta_data(self.DISfile) except: raise IOError("Cannot read MODFLOW DIS file {0}".format( self.DISfile)) print "\naggregating flow information by cellnum..." indata = open(self.SFR_out).readlines() for line in indata[8:]: line = line.strip().split() # Kludge! terminates with blank line (only reads stress per. 1) # need to add support for transient. if len(line) == 0: break r, c = int(line[1]), int(line[2]) cellnum = (r - 1) * NCOL + c seg_rch = "{0} {1}; ".format(line[3], line[4]) flow = 0.5 * (float(line[5]) + float(line[7])) loss = float(line[6]) overland = float(line[8]) stage = float(line[11]) depth = float(line[12]) try: existingflow = self.flow_by_cellnum[cellnum] seg_rch_info = self.seg_rch_by_cellnum[cellnum] except KeyError: existingflow = 0 seg_rch_info = 'segs rchs: ' # determine state if flow == 0: state = 'dry' elif loss > 0: state = 'losing' elif loss < 0: state = 'gaining' else: print 'Stream reach in cell {} has flow, but no interaction with aquifer.'.format( cellnum) self.flow_by_cellnum[cellnum] = existingflow + flow self.seg_rch_by_cellnum[cellnum] = seg_rch_info + seg_rch self.loss_by_cellnum[cellnum] = loss self.state_by_cellnum[cellnum] = state self.overland_by_cellnum[cellnum] = overland self.stage_by_cellnum[cellnum] = stage self.depth_by_cellnum[cellnum] = depth # write to temporary output file ofp = open(os.path.join(self.outpath, 'temp.csv'), 'w') ofp.write( '{},row,column,seg_reach,flow,loss,overland,state,stage,depth\n'. format(self.node_num_attribute)) for cn in self.flow_by_cellnum.keys(): ofp.write('{0},{1},{2},"{3}",{4:.6e},{5},{6},{7},{8},{9}\n'.format( cn, 1, 1, self.seg_rch_by_cellnum[cn], self.flow_by_cellnum[cn], self.loss_by_cellnum[cn], self.overland_by_cellnum[cn], self.state_by_cellnum[cn], self.stage_by_cellnum[cn], self.depth_by_cellnum[cn])) ofp.close() outfile = os.path.join(self.outpath, "{0}.shp".format(self.SFR_out[:-4])) if use_arcpy: try: import arcpy import SFR_arcpy except: print 'module arcpy not found!' # make feature/table layers arcpy.env.workspace = self.outpath arcpy.env.overwriteOutput = True arcpy.CopyFeatures_management( self.streams_shp, self.streams_shp[:-4] + '_backup.shp') arcpy.MakeFeatureLayer_management( self.streams_shp[:-4] + '_backup.shp', "streams") arcpy.CopyRows_management(os.path.join(self.outpath, 'temp.csv'), os.path.join(self.outpath, 'temp.dbf')) # drop all fields except for cellnum from stream linework Fields = arcpy.ListFields("streams") Fields = [ f.name for f in Fields if f.name not in ["FID", "Shape", self.node_num_attribute] ] if len(Fields) > 0: arcpy.DeleteField_management("streams", Fields) SFR_arcpy.general_join(outfile, "streams", self.node_num_attribute, "temp.dbf", self.node_num_attribute, keep_common=True) else: import sys sys.path.append('../../GIS_utils') try: import GISops except: print 'GIS_utils.GISops not found!' GISops.join_csv2shp(self.streams_shp, self.node_num_attribute, os.path.join(self.outpath, 'temp.csv'), self.node_num_attribute, outfile, how='inner')
def to_sfr(self, roughness=0.037, streambed_thickness=1, streambedK=1, icalc=1, iupseg=0, iprior=0, nstrpts=0, flow=0, runoff=0, etsw=0, pptsw=0, roughch=0, roughbk=0, cdepth=0, fdepth=0, awdth=0, bwdth=0): # create a working dataframe self.df = self.fl[self.fl_cols].join(self.pfvaa[self.pfvaa_cols], how='inner') # bring in elevations from elevslope table self.df = self.df.join(self.elevs[['Max', 'Min']], how='inner') print('\nclipping flowlines to active area...') inside = np.array([g.intersects(self.domain) for g in self.df.geometry]) self.df = self.df.ix[inside].copy() self.df.sort_values(by='COMID', inplace=True) flowline_geoms = [g.intersection(self.domain) for g in self.df.geometry] grid_geoms = self.grid.geometry.tolist() print("intersecting flowlines with grid cells...") # this part crawls in debug mode grid_intersections = GISops.intersect_rtree(grid_geoms, flowline_geoms) print("setting up segments... (may take a few minutes for large networks)") ta = time.time() self.list_updown_comids() self.assign_segments() fl_segments = self.df.segment.tolist() fl_comids = self.df.COMID.tolist() print("finished in {:.2f}s\n".format(time.time() - ta)) print("setting up reaches and Mat1... (may take a few minutes for large grids)") ta = time.time() m1 = make_mat1(flowline_geoms, fl_segments, fl_comids, grid_intersections, grid_geoms) print("finished in {:.2f}s\n".format(time.time() - ta)) print("computing widths...") m1['length'] = np.array([g.length for g in m1.geometry]) lengths = m1[['segment', 'length']].copy() groups = lengths.groupby('segment') # compute arbolate sum at reach midpoints reach_asums = np.concatenate([np.cumsum(grp.length.values[::-1])[::-1] - 0.5*grp.length.values for s, grp in groups]) segment_asums = np.array([self.df.ArbolateSu.values[s-1] for s in m1.segment.values]) reach_asums = -1 * self.to_km * reach_asums + segment_asums # arbolate sums are computed in km width = width_from_arbolate(reach_asums) # widths are returned in m if self.GISunits != 'm': width = width / 0.3048 print("multiplying length units by {} to convert from GIS to MODFLOW...".format(self.mf_units_mult)) m1['width'] = width * self.mf_units_mult m1['length'] = m1.length * self.mf_units_mult m1['roughness'] = roughness m1['sbthick'] = streambed_thickness m1['sbK'] = streambedK m1['sbtop'] = 0 if self.nrows is not None: m1['row'] = np.floor(m1.node / self.ncols) + 1 if self.ncols is not None: column = m1.node.values % self.ncols column[column == 0] = self.ncols # last column has remainder of 0 m1['column'] = column m1['layer'] = 1 self.m1 = m1 print("\nsetting up Mat2...") ta = time.time() self.m2 = self.df[['segment', 'outseg', 'Max', 'Min']].copy() self.m2['icalc'] = icalc self.renumber_segments() # enforce best segment numbering self.m2.index = self.m2.segment print("finished in {:.2f}s\n".format(time.time() - ta)) # add outseg information to Mat1 self.m1['outseg'] = [self.m2.outseg[s] for s in self.m1.segment] self.m1.sort_values(by=['segment', 'reach'], inplace=True) print('\nDone creating SFR dataset.')