def generate_openwater(catchments, landuse, meteo_areas, zonalstats_alltouched=None): """ Combine all data to form a complete OPENWATE definotion. ALso the coordinates for the network topology are included. Zonal statistics are applied to land use, to get the open water area. The classificition described in the notebook is assumed. """ all_touched=False if zonalstats_alltouched is None else zonalstats_alltouched lu_rast, lu_affine = read_raster(landuse, static=True) lu_counts = zonal_stats(catchments, lu_rast, affine=lu_affine, categorical=True, all_touched=all_touched) # get raster cellsize px_area = lu_affine[0] * -lu_affine[4] ow_drr = ExtendedDataFrame(required_columns=['code']) ow_drr.set_data( pd.DataFrame(np.zeros((len(catchments),6)), columns=['code','area','meteostat','px', 'py', 'boundary'], dtype="str"), index_col='code') ow_drr.index = catchments.code for num, cat in enumerate(catchments.itertuples()): # find corresponding meteo-station tm = [m for m in meteo_areas.itertuples() if m.geometry.contains(cat.geometry.centroid)] ms = meteo_areas.iloc[0,:][0] if tm==[] else tm[0].code ow_drr.at[cat.code, 'code'] = str(cat.code) ow_drr.at[cat.code, 'area'] = str(lu_counts[num][13]*px_area) if 13 in lu_counts[num] else '0' ow_drr.at[cat.code, 'meteostat'] = ms ow_drr.at[cat.code, 'px'] = f'{cat.geometry.centroid.coords[0][0]-20:.0f}' ow_drr.at[cat.code, 'py'] = f'{cat.geometry.centroid.coords[0][1]:.0f}' ow_drr.at[cat.code, 'boundary'] = cat.lateraleknoopcode return ow_drr
def generate_boundary(boundary_nodes, catchments, overflows=None): """ Method to create boundary nodes for RR. """ if overflows is not None: numlats = len(catchments)+len(overflows) else: numlats = len(catchments) bnd_drr = ExtendedDataFrame(required_columns=['code']) bnd_drr.set_data( pd.DataFrame(np.zeros((numlats,3)), columns=['code', 'px', 'py'], dtype="str"), index_col='code') if overflows is not None: bnd_drr.index = catchments.code.append(overflows.code) else: bnd_drr.index = catchments.code for num, cat in enumerate(catchments.itertuples()): # print(num, cat.code) if boundary_nodes[boundary_nodes['code']==cat.lateraleknoopcode].empty: #raise IndexError(f'{cat.code} not connected to a boundary node. Skipping.') print(f'{cat.code} not connected to a boundary node. Skipping.') continue bnd_drr.at[cat.code, 'code'] = cat.lateraleknoopcode bnd_drr.at[cat.code, 'px'] = str(boundary_nodes[boundary_nodes['code']==cat.lateraleknoopcode]['geometry'].x.iloc[0]).strip() bnd_drr.at[cat.code, 'py'] = str(boundary_nodes[boundary_nodes['code']==cat.lateraleknoopcode]['geometry'].y.iloc[0]).strip() if overflows is not None: for num, ovf in enumerate(overflows.itertuples()): bnd_drr.at[ovf.code, 'code'] = ovf.code bnd_drr.at[ovf.code, 'px'] = str(ovf.geometry.coords[0][0]) bnd_drr.at[ovf.code, 'py'] = str(ovf.geometry.coords[0][1]) return bnd_drr
def generate_boundary(boundary_nodes, catchments, overflows=None): """ Method to create boundary nodes for RR. """ if overflows is not None: numlats = len(catchments) + len(overflows) else: numlats = len(catchments) bnd_drr = ExtendedDataFrame(required_columns=['code']) bnd_drr.set_data(pd.DataFrame(np.zeros((numlats, 3)), columns=['code', 'px', 'py'], dtype="str"), index_col='code') if overflows is not None: bnd_drr.index = catchments.code.append(overflows.code) else: bnd_drr.index = catchments.code for num, cat in enumerate(catchments.itertuples()): bnd_drr.at[cat.code, 'code'] = cat.lateraleknoopcode bnd_drr.at[cat.code, 'px'] = boundary_nodes[ boundary_nodes['code'] == cat.lateraleknoopcode]['X'].to_string( index=False).strip() bnd_drr.at[cat.code, 'py'] = boundary_nodes[ boundary_nodes['code'] == cat.lateraleknoopcode]['Y'].to_string( index=False).strip() if overflows is not None: for num, ovf in enumerate(overflows.itertuples()): bnd_drr.at[ovf.code, 'code'] = ovf.code bnd_drr.at[ovf.code, 'px'] = str(ovf.geometry.coords[0][0]) bnd_drr.at[ovf.code, 'py'] = str(ovf.geometry.coords[0][1]) return bnd_drr
def generate_ernst(catchments, depths, resistance, infiltration_resistance, runoff_resistance): """ The lists with depths and resistances as well as the standard infiltration and runoff resistances, are converted, to a dataframe. """ ernst_drr = ExtendedDataFrame(required_columns=['code']) ernst_drr.set_data( pd.DataFrame(np.zeros((len(catchments),5)), columns=['code','reslist','lvs','cvi','cvs'], dtype="str"), index_col='code') ernst_drr.index = catchments.code for num, cat in enumerate(catchments.itertuples()): ernst_drr.at[cat.code, 'code'] = str(cat.code) ernst_drr.at[cat.code, 'reslist'] = ' '.join([str(res) for res in resistance]) ernst_drr.at[cat.code, 'lvs'] = ' '.join([str(depth) for depth in depths]) ernst_drr.at[cat.code, 'cvi'] = str(infiltration_resistance) ernst_drr.at[cat.code, 'cvs'] = str(runoff_resistance) return ernst_drr
def generate_greenhouse(catchments, landuse, surface_level, roof_storage, meteo_areas, zonalstats_alltouched=None): """ Combine all data to form a complete GREENHSE defintion. ALso the coordinates for the network topology are included. Zonal statistics are applied to land use, to get the paved area. The classificition described in the notebook is assumed. From the elevation grid, the median value per catchment is assumed. Other parameters can be prescribed as as float (spatially uniform) or as a raster name, in which case the mean value per catchment is used. """ all_touched=False if zonalstats_alltouched is None else zonalstats_alltouched lu_rast, lu_affine = read_raster(landuse, static=True) lu_counts = zonal_stats(catchments, lu_rast, affine=lu_affine, categorical=all_touched) rast, affine = read_raster(surface_level, static=True) mean_elev = zonal_stats(catchments, rast, affine=affine, stats="median", all_touched=all_touched) # optional rasters if isinstance(roof_storage, str): rast, affine = read_raster(roof_storage, static=True) roofstors = zonal_stats(catchments, rast, affine=affine, stats="mean", all_touched=True) elif isinstance(roof_storage, int): roof_storage = float(roof_storage) # get raster cellsize px_area = lu_affine[0] * -lu_affine[4] gh_drr = ExtendedDataFrame(required_columns=['code']) gh_drr.set_data( pd.DataFrame(np.zeros((len(catchments),8)), columns=['code','area','mvlevel', 'roofstor', 'meteostat','px', 'py', 'boundary'], dtype="str"), index_col='code') gh_drr.index = catchments.code for num, cat in enumerate(catchments.itertuples()): # if no rasterdata could be obtained for this catchment, skip it. if mean_elev[num]['median'] is None: logger.warning('No rasterdata available for catchment %s' % cat.code) continue # find corresponding meteo-station tm = [m for m in meteo_areas.itertuples() if m.geometry.contains(cat.geometry.centroid)] ms = meteo_areas.iloc[0,:][0] if tm==[] else tm[0].code elev = mean_elev[num]['median'] gh_drr.at[cat.code, 'code'] = str(cat.code) gh_drr.at[cat.code, 'area'] = str(lu_counts[num][15]*px_area) if 15 in lu_counts[num] else '0' gh_drr.at[cat.code, 'mvlevel'] = f'{elev:.2f}' if isinstance(roof_storage, float): gh_drr.at[cat.code, 'roofstor'] = f'{roof_storage:.2f}' else: gh_drr.at[cat.code, 'roofstor'] = f'{roofstors[num]["mean"]:.2f}' gh_drr.at[cat.code, 'meteostat'] = ms gh_drr.at[cat.code, 'px'] = f'{cat.geometry.centroid.coords[0][0]+20:.0f}' gh_drr.at[cat.code, 'py'] = f'{cat.geometry.centroid.coords[0][1]:.0f}' gh_drr.at[cat.code, 'boundary'] = cat.lateraleknoopcode return gh_drr
def generate_compounds(idlist, structurelist): # probably the coordinates should all be set to those of the first structure compounds_dfm = ExtendedDataFrame( required_columns=['code', 'structurelist']) compounds_dfm.set_data(pd.DataFrame( np.zeros((len(idlist), 3)), columns=['code', 'numstructures', 'structurelist'], dtype='str'), index_col='code') compounds_dfm.index = idlist for ii, compound in enumerate(compounds_dfm.itertuples()): compounds_dfm.at[compound.Index, 'code'] = idlist[ii] compounds_dfm.at[compound.Index, 'numstructures'] = len(structurelist[ii]) compounds_dfm.at[compound.Index, 'structurelist'] = ';'.join( [f'{s}' for s in structurelist[ii]]) return compounds_dfm
def generate_unpaved(catchments, landuse, surface_level, soiltype, surface_storage, infiltration_capacity, initial_gwd, meteo_areas, zonalstats_alltouched=None): """ Combine all data to form a complete UNPAVED definition. ALso the coordinates for the networ topology are included. Zonal statistics are applied to land use, to get the areas per type. The classificition described in the notebook is assumed. From the elevation grid, the median value per catchment is assumed, and for soil type the dominant soil type in the catchment is used. Other parameters can be prescribed as as float (spatially uniform) or as a raster name, in which case the mean value per catchment is used. """ all_touched=False if zonalstats_alltouched is None else zonalstats_alltouched # required rasters warnings.filterwarnings('ignore') lu_rast, lu_affine = read_raster(landuse, static=True) lu_counts = zonal_stats(catchments, lu_rast, affine=lu_affine, categorical=True, all_touched=all_touched) rast, affine = read_raster(soiltype, static=True) soiltypes = zonal_stats(catchments, soiltype, affine = affine, stats='majority',all_touched=all_touched) rast, affine = read_raster(surface_level, static=True) mean_elev = zonal_stats(catchments, rast, affine=affine, stats="median",all_touched=all_touched) # optional rasters if not isinstance(surface_storage, float): rast,affine = read_raster(surface_storage, static=True) sstores = zonal_stats(catchments, rast, affine=affine, stats="mean",all_touched=True) if not isinstance(infiltration_capacity, float): rast,affine = read_raster(infiltration_capacity, static=True) infcaps = zonal_stats(catchments, rast, affine=affine, stats="mean",all_touched=True) if not isinstance(initial_gwd, float): rast,affine = read_raster(initial_gwd, static=True) ini_gwds = zonal_stats(catchments, rast, affine=affine, stats="mean", all_touched=True) # get raster cellsize px_area = lu_affine[0] * -lu_affine[4] unpaved_drr = ExtendedDataFrame(required_columns=['code']) unpaved_drr.set_data( pd.DataFrame(np.zeros((len(catchments),12)), columns=['code','total_area','lu_areas','mvlevel', 'soiltype','surstor','infcap','initial_gwd','meteostat','px','py','boundary' ], dtype="str"), index_col='code') unpaved_drr.index = catchments.code # HyDAMO Crop code; hydamo name, sobek index, sobek name: # 1 aardappelen 3 potatoes # 2 graan 5 grain # 3 suikerbiet 4 sugarbeet # 4 mais 2 corn # 5 overige gew. 15 vegetables # 6 bloembollen 10 bulbous plants # 7 boomgaard 9 orchard # 8 gras 1 grass # 9 loofbos 11 dediduous # 10 naaldbos 12 conferous # 11 natuuur 13 nature # 12 braak 14 fallow sobek_indices = [3,5,4,2,15,10,9,1,11,12,13,14] for num, cat in enumerate(catchments.itertuples()): # if no rasterdata could be obtained for this catchment, skip it. if mean_elev[num]['median'] is None: continue tm = [m for m in meteo_areas.itertuples() if m.geometry.contains(cat.geometry.centroid)] ms = meteo_areas.iloc[0,:][0] if tm==[] else tm[0].code # find corresponding meteo-station #ms = [ms for ms in meteo_areas.itertuples() if ms.geometry.contains(cat.geometry.centroid)] #ms = ms[0] if ms != [] else meteo_areas.iloc[0,:][0] mapping = np.zeros(16, dtype=int) for i in range(1,12): if i in lu_counts[num]: mapping[sobek_indices[i-1]-1] = lu_counts[num][i]*px_area lu_map = ' '.join(map(str,mapping)) elev = mean_elev[num]['median'] unpaved_drr.at[cat.code, 'code'] = str(cat.code) unpaved_drr.at[cat.code, 'total_area'] = f'{cat.geometry.area:.0f}' unpaved_drr.at[cat.code, 'lu_areas'] = lu_map unpaved_drr.at[cat.code, 'mvlevel'] = f'{elev:.2f}' unpaved_drr.at[cat.code, 'soiltype'] =f'{soiltypes[num]["majority"]+100.:.0f}' if isinstance(surface_storage, float): unpaved_drr.at[cat.code, 'surstor'] = f'{surface_storage:.3f}' else: unpaved_drr.at[cat.code, 'surstor'] = f'{sstores[num]["mean"]:.3f}' if isinstance(infiltration_capacity, float): unpaved_drr.at[cat.code, 'infcap'] = f'{infiltration_capacity:.3f}' else: unpaved_drr.at[cat.code, 'infcap'] = f'{infcaps[num]["mean"]:.3f}' if isinstance(initial_gwd, float): unpaved_drr.at[cat.code, 'initial_gwd'] = f'{initial_gwd:.2f}' else: unpaved_drr.at[cat.code, 'initial_gwd'] = f'{ini_gwds[num]["mean"]:.2f}' unpaved_drr.at[cat.code, 'meteostat'] = ms unpaved_drr.at[cat.code, 'px'] = f'{cat.geometry.centroid.coords[0][0]-10:.0f}' unpaved_drr.at[cat.code, 'py'] = f'{cat.geometry.centroid.coords[0][1]:.0f}' unpaved_drr.at[cat.code, 'boundary'] = cat.lateraleknoopcode return unpaved_drr
def generate_paved( catchments=None, overflows=None, sewer_areas=None, landuse=None, surface_level=None, street_storage=None, sewer_storage=None, pump_capacity=None, meteo_areas=None, zonalstats_alltouched=None): """ Combine all data to form a complete PAVED definition. ALso the coordinates for the networ topology are included. Zonal statistics are applied to land use, to get the paved area. The classificition described in the notebook is assumed. From the elevation grid, the median value per catchment is assumed. Other parameters can be prescribed as as float (spatially uniform) or as a raster name, in which case the mean value per catchment is used. """ all_touched=False if zonalstats_alltouched is None else zonalstats_alltouched lu_rast, lu_affine = read_raster(landuse, static=True) lu_counts = zonal_stats(catchments, lu_rast, affine=lu_affine, categorical=True, all_touched=all_touched) sl_rast, sl_affine = read_raster(surface_level, static=True) mean_elev = zonal_stats(catchments, sl_rast, affine=sl_affine, stats="median",all_touched=all_touched) if not isinstance( street_storage, float): strs_rast, strs_affine = read_raster(street_storage, static=True) str_stors = zonal_stats(catchments, strs_rast, affine=strs_affine, stats="mean", all_touched=True) if not isinstance( sewer_storage, float): sews_rast, sews_affine = read_raster(sewer_storage, static=True) sew_stors = zonal_stats(catchments, sews_rast, affine=sews_affine, stats="mean", all_touched=True) if not isinstance(pump_capacity, float): pump_rast, pump_affine = read_raster(pump_capacity, static=True) pump_caps = zonal_stats(catchments, pump_rast, affine=pump_affine, stats="mean", all_touched=True) # get raster cellsize px_area = lu_affine[0] * -lu_affine[4] paved_drr = ExtendedDataFrame(required_columns=['code']) if sewer_areas is not None: # if the parameters area rasters, do the zonal statistics per sewage area as well. if not isinstance( street_storage, float): str_stors_sa = zonal_stats(sewer_areas, strs_rast,affine=strs_affine,stats="mean", all_touched=True) if not isinstance( sewer_storage, float): sew_stors_sa = zonal_stats(sewer_areas, sews_rast,affine=sews_affine,stats="mean", all_touched=True) if not isinstance(pump_capacity, float): pump_caps_sa = zonal_stats(sewer_areas, pump_rast,affine=pump_affine,stats="mean", all_touched=True) mean_sa_elev = zonal_stats(sewer_areas, sl_rast, affine=sl_affine, stats="median",all_touched=True) # initialize the array of paved nodes, which should contain a node for all catchments and all overflows paved_drr.set_data( pd.DataFrame(np.zeros((len(catchments)+len(overflows),10)), columns=['code','area','mvlevel', 'streetstor', 'sewstor', 'pumpcap','meteostat','px', 'py', 'boundary'], dtype="str"), index_col='code') paved_drr.index = catchments.code.append(overflows.code) # find the paved area in the sewer areas for isew, sew in enumerate(sewer_areas.itertuples()): pav_area = 0 for cat_ind, cat in enumerate(catchments.itertuples()): # if no rasterdata could be obtained for this catchment, skip it. if mean_elev[cat_ind]['median'] is None: continue if(cat.geometry.intersects(sew.geometry)): # find the paved area within the intersection and add it to the sewer area sum intersecting_pixels = zonal_stats(cat.geometry.intersection(sew.geometry), lu_rast, affine=lu_affine, categorical=True, all_touched=all_touched) if intersecting_pixels[0]=={}: continue if 14.0 not in intersecting_pixels[0]: print(f'{sew.code} / {cat.code}: no paved area in sewer area!') continue pav_pixels = intersecting_pixels[0][14.0] pav_area += pav_pixels*px_area # subtract it fromthe total paved area in this catchment, make sure at least 0 remains lu_counts[cat_ind][14.0] -= pav_pixels if lu_counts[cat_ind][14.0] < 0: lu_counts[cat_ind][14.0] = 0 elev = mean_sa_elev[isew]['median'] # find overflows related to this sewer area ovf = overflows[overflows.codegerelateerdobject==sew.code] for ov in ovf.itertuples(): # find corresponding meteo-station tm = [m for m in meteo_areas.itertuples() if m.geometry.contains(sew.geometry.centroid)] ms = meteo_areas.iloc[0,:][0] if tm==[] else tm[0].code #ms = ms[0] if ms != [] else meteo_areas.iloc[0,:][0] # add prefix to the overflow id to create the paved-node id paved_drr.at[ov.code, 'code'] = str(ov.code) paved_drr.at[ov.code, 'area'] = str(pav_area * ov.fractie) paved_drr.at[ov.code, 'mvlevel'] = f'{elev:.2f}' # if a float is given, a standard value is passed. If a string is given, a rastername is assumed to zonal statistics are applied. if isinstance(street_storage, float): paved_drr.at[ov.code, 'streetstor'] = f'{street_storage:.2f}' else: paved_drr.at[ov.code, 'streetstor'] = f'{str_stors_sa[isew]["mean"]:.2f}' if isinstance(sewer_storage, float): paved_drr.at[ov.code, 'sewstor'] = f'{sewer_storage:.2f}' else: paved_drr.at[ov.code, 'sewstor'] = f'{sew_stors_sa[isew]["mean"]:.2f}' if isinstance(pump_capacity, float): paved_drr.at[ov.code, 'pumpcap'] = f'{pump_capacity}' else: paved_drr.at[ov.code, 'pumpcap'] = f'{pump_caps_sa[isew]["mean"]:.2f}' paved_drr.at[ov.code,'meteostat'] = ms paved_drr.at[ov.code, 'px'] = f'{ov.geometry.coords[0][0]+10:.0f}' paved_drr.at[ov.code, 'py'] = f'{ov.geometry.coords[0][1]:.0f}' paved_drr.at[ov.code, 'boundary'] = ov.code else: # in this case only the catchments are taken into account. A node is created for every catchment nonetheless, but only nodes with a remaining area >0 are written. paved_drr.set_data( pd.DataFrame(np.zeros((len(catchments),10)), columns=['code','area','mvlevel', 'streetstor', 'sewstor', 'pumpcap','meteostat', 'px', 'py', 'boundary'], dtype="str"), index_col='code') paved_drr.index = catchments.code for num, cat in enumerate(catchments.itertuples()): # if no rasterdata could be obtained for this catchment, skip it. if mean_elev[num]['median'] is None: continue # find corresponding meteo-station tm = [m for m in meteo_areas.itertuples() if m.geometry.contains(cat.geometry.centroid)] ms = meteo_areas.iloc[0,:][0] if tm==[] else tm[0].code elev = mean_elev[num]['median'] paved_drr.at[cat.code, 'code'] = str(cat.code) paved_drr.at[cat.code, 'area'] = str(lu_counts[num][14]*px_area) if 14 in lu_counts[num] else '0' paved_drr.at[cat.code, 'mvlevel'] = f'{elev:.2f}' # if a float is given, a standard value is passed. If a string is given, a rastername is assumed to zonal statistics are applied. if isinstance(street_storage, float): paved_drr.at[cat.code, 'streetstor'] = f'{street_storage:.2f}' else: paved_drr.at[cat.code, 'streetstor'] = f'{str_stors[num]["mean"]:.2f}' if isinstance(sewer_storage, float): paved_drr.at[cat.code, 'sewstor'] = f'{sewer_storage:.2f}' else: paved_drr.at[cat.code, 'sewstor'] = f'{sew_stors[num]["mean"]:.2f}' if isinstance(pump_capacity, float): paved_drr.at[cat.code, 'pumpcap'] = f'{pump_capacity}' else: paved_drr.at[cat.code, 'pumpcap'] = f'{pump_caps[num]["mean"]:.2f}' paved_drr.at[cat.code,'meteostat'] = ms paved_drr.at[cat.code, 'px'] = f'{cat.geometry.centroid.coords[0][0]+10:.0f}' paved_drr.at[cat.code, 'py'] = f'{cat.geometry.centroid.coords[0][1]:.0f}' paved_drr.at[cat.code, 'boundary'] = cat.lateraleknoopcode return paved_drr
def generate_compounds(idlist, structurelist, structures): # probably the coordinates should all be set to those of the first structure (still to do) compounds_dfm = ExtendedDataFrame( required_columns=['code', 'structurelist']) compounds_dfm.set_data(pd.DataFrame( np.zeros((len(idlist), 3)), columns=['code', 'numstructures', 'structurelist'], dtype='str'), index_col='code') compounds_dfm.index = idlist for ii, compound in enumerate(compounds_dfm.itertuples()): compounds_dfm.at[compound.Index, 'code'] = idlist[ii] compounds_dfm.at[compound.Index, 'numstructures'] = len(structurelist[ii]) # check the substructure coordinates. If they do not coincide, move subsequent structures to the coordinates of the first for s_i, struc in enumerate(structurelist[ii]): if s_i == 0: # find out what type the first structure it is and get its coordinates if struc in structures.pumps.keys(): branch = structures.pumps[struc]['branchid'] offset = structures.pumps[struc]['chainage'] elif struc in structures.weirs.keys(): branch = structures.weirs[struc]['branchid'] offset = structures.weirs[struc]['chainage'] elif struc in structures.uweirs.keys(): branch = structures.uweirs[struc]['branchid'] offset = structures.uweirs[struc]['chainage'] elif struc in structures.culverts.keys(): branch = structures.culverts[struc]['branchid'] offset = structures.culverts[struc]['chainage'] elif struc in structures.bridges.keys(): branch = structures.bridges[struc]['branchid'] offset = structures.bridges[struc]['chainage'] elif struc in structures.orifices.keys(): branch = structures.orifices[struc]['branchid'] offset = structures.orifices[struc]['chainage'] else: raise IndexError( 'Structure id not found. Make sure all other structures have been added to the model.' ) else: # move a subsequent structure to the location of the first if struc in structures.pumps.keys(): structures.pumps = move_structure(struc, structures.pumps, branch, offset) if struc in structures.weirs.keys(): structures.weirs = move_structure(struc, structures.weirs, branch, offset) if struc in structures.uweirs.keys(): structures.uweirs = move_structure(struc, structures.uweirs, branch, offset) if struc in structures.culverts.keys(): structures.culverts = move_structure( struc, structures.culverts, branch, offset) if struc in structures.bridges.keys(): structures.bridges = move_structure( struc, structures.bridges, branch, offset) if struc in structures.orifices.keys(): structures.orifices = move_structure( struc, structures.orifices, branch, offset) compounds_dfm.at[compound.Index, 'structurelist'] = ';'.join( [f'{s}' for s in structurelist[ii]]) return compounds_dfm