def snaptomap(points, mmap): """ Snap the points in _points_ to nearest non missing values in _mmap_. Can be used to move gauge locations to the nearest rivers. Input: - points - map with points to move - mmap - map with points to move to Return: - map with shifted points """ points = pcr.cover(points, 0) # Create unique id map of mmap cells unq = pcr.nominal(pcr.cover(pcr.uniqueid(pcr.defined(mmap)), pcr.scalar(0.0))) # Now fill holes in mmap map with lues indicating the closes mmap cell. dist_cellid = pcr.scalar(pcr.spreadzone(unq, 0, 1)) # Get map with values at location in points with closes mmap cell dist_cellid = pcr.ifthenelse(points > 0, dist_cellid, 0) # Spread this out dist_fill = pcr.spreadzone(pcr.nominal(dist_cellid), 0, 1) # Find the new (moved) locations npt = pcr.uniqueid(pcr.boolean(pcr.ifthen(dist_fill == unq, unq))) # Now recreate the original value in the points maps ptcover = pcr.spreadzone(pcr.cover(points, 0), 0, 1) # Now get the org point value in the pt map nptorg = pcr.ifthen(npt > 0, ptcover) return nptorg
def derive_HAND(dem, ldd, accuThreshold, rivers=None, basin=None, up_area=None): """ Function derives Height-Above-Nearest-Drain. See http://www.sciencedirect.com/science/article/pii/S003442570800120X Input: dem -- pcraster object float32, elevation data ldd -- pcraster object direction, local drain directions accuThreshold -- upstream amount of cells as threshold for river delineation rivers=None -- you can provide a rivers layer here. Pixels that are identified as river should have a value > 0, other pixels a value of zero. basin=None -- set a boolean pcraster map where areas with True are estimated using the nearest drain in ldd distance and areas with False by means of the nearest friction distance. Friction distance estimated using the upstream area as weight (i.e. drains with a bigger upstream area have a lower friction) the spreadzone operator is used in this case. up_area=None -- provide the upstream area (if not assigned a guesstimate is prepared, assuming the LDD covers a full catchment area) Output: hand -- pcraster bject float32, height, normalised to nearest stream dist -- distance to nearest stream measured in cell lengths according to D8 directions """ if rivers is None: # prepare stream from a strahler threshold stream = pcr.ifthenelse( pcr.accuflux(ldd, 1) >= accuThreshold, pcr.boolean(1), pcr.boolean(0)) else: # convert stream network to boolean stream = pcr.boolean(pcr.cover(rivers, 0)) # determine height in river (in DEM*100 unit as ordinal) height_river = pcr.ifthenelse(stream, pcr.ordinal(dem * 100), 0) if basin is None: up_elevation = pcr.scalar(pcr.subcatchment(ldd, height_river)) else: # use basin to allocate areas outside basin to the nearest stream. Nearest is weighted by upstream area if up_area is None: up_area = pcr.accuflux(ldd, 1) up_area = pcr.ifthen(stream, up_area) # mask areas outside streams friction = 1. / pcr.scalar( pcr.spreadzone(pcr.cover(pcr.ordinal(up_area), 0), 0, 0)) # if basin, use nearest river within subcatchment, if outside basin, use weighted-nearest river up_elevation = pcr.ifthenelse( basin, pcr.scalar(pcr.subcatchment(ldd, height_river)), pcr.scalar(pcr.spreadzone(height_river, 0, friction))) # replace areas outside of basin by a spread zone calculation. hand = pcr.max(pcr.scalar(pcr.ordinal(dem * 100)) - up_elevation, 0) / 100 # convert back to float in DEM units # hand = (pcr.scalar(pcr.ordinal(dem*100))-up_elevation)/100 # convert back to float in DEM units dist = pcr.ldddist(ldd, stream, 1) # compute horizontal distance estimate return hand, dist
def derive_HAND(dem, ldd, accuThreshold, rivers=None, basin=None): """ Function derives Height-Above-Nearest-Drain. See http://www.sciencedirect.com/science/article/pii/S003442570800120X Input: dem -- pcraster object float32, elevation data ldd -- pcraster object direction, local drain directions accuThreshold -- upstream amount of cells as threshold for river delineation rivers=None -- you can provide a rivers layer here. Pixels that are identified as river should have a value > 0, other pixels a value of zero. basin=None -- set a boolean pcraster map where areas with True are estimated using the nearest drain in ldd distance and areas with False by means of the nearest friction distance. Friction distance estimated using the upstream area as weight (i.e. drains with a bigger upstream area have a lower friction) the spreadzone operator is used in this case. Output: hand -- pcraster bject float32, height, normalised to nearest stream dist -- distance to nearest stream measured in cell lengths according to D8 directions """ if rivers is None: stream = pcr.ifthenelse( pcr.accuflux(ldd, 1) >= accuThreshold, pcr.boolean(1), pcr.boolean(0) ) else: stream = pcr.boolean(pcr.cover(rivers, 0)) height_river = pcr.ifthenelse(stream, pcr.ordinal(dem * 100), 0) if basin is None: up_elevation = pcr.scalar(pcr.subcatchment(ldd, height_river)) else: drainage_surf = pcr.ifthen(rivers, pcr.accuflux(ldd, 1)) weight = 1.0 / pcr.scalar( pcr.spreadzone(pcr.cover(pcr.ordinal(drainage_surf), 0), 0, 0) ) up_elevation = pcr.ifthenelse( basin, pcr.scalar(pcr.subcatchment(ldd, height_river)), pcr.scalar(pcr.spreadzone(height_river, 0, weight)), ) # replace areas outside of basin by a spread zone calculation. hand = pcr.max(pcr.scalar(pcr.ordinal(dem * 100)) - up_elevation, 0) / 100 dist = pcr.ldddist(ldd, stream, 1) return hand, dist
def spatialInterpolation2PCR(fieldArray, pcrType, MV): #-interpolates the field array to the full extent field = pcr.numpy2pcr(pcrType, fieldArray, MV) cellID = pcr.nominal(pcr.uniqueid(pcr.defined(field))) zoneID = pcr.spreadzone(cellID, 0, 1) if pcrType == pcr.Scalar: field = pcr.areaaverage(field, zoneID) else: field = pcr.areamajority(field, zoneID) return field
def derive_HAND(dem, ldd, accuThreshold, rivers=None, basin=None, up_area=None, neg_HAND=None): """ Function derives Height-Above-Nearest-Drain. See http://www.sciencedirect.com/science/article/pii/S003442570800120X Input: dem -- pcraster object float32, elevation data ldd -- pcraster object direction, local drain directions accuThreshold -- upstream amount of cells as threshold for river delineation rivers=None -- you can provide a rivers layer here. Pixels that are identified as river should have a value > 0, other pixels a value of zero. basin=None -- set a boolean pcraster map where areas with True are estimated using the nearest drain in ldd distance and areas with False by means of the nearest friction distance. Friction distance estimated using the upstream area as weight (i.e. drains with a bigger upstream area have a lower friction) the spreadzone operator is used in this case. up_area=None -- provide the upstream area (if not assigned a guesstimate is prepared, assuming the LDD covers a full catchment area) neg_HAND=None -- if set to 1, HAND maps can have negative values when elevation outside of stream is lower than stream (for example when there are natural embankments) Output: hand -- pcraster bject float32, height, normalised to nearest stream dist -- distance to nearest stream measured in cell lengths according to D8 directions """ if rivers is None: # prepare stream from a strahler threshold stream = pcr.ifthenelse(pcr.accuflux(ldd, 1) >= accuThreshold, pcr.boolean(1), pcr.boolean(0)) else: # convert stream network to boolean stream = pcr.boolean(pcr.cover(rivers, 0)) # determine height in river (in DEM*100 unit as ordinal) height_river = pcr.ifthenelse(stream, pcr.ordinal(dem*100), 0) if basin is None: up_elevation = pcr.scalar(pcr.subcatchment(ldd, height_river)) else: # use basin to allocate areas outside basin to the nearest stream. Nearest is weighted by upstream area if up_area is None: up_area = pcr.accuflux(ldd, 1) up_area = pcr.ifthen(stream, up_area) # mask areas outside streams friction = 1./pcr.scalar(pcr.spreadzone(pcr.cover(pcr.ordinal(up_area), 0), 0, 0)) # if basin, use nearest river within subcatchment, if outside basin, use weighted-nearest river up_elevation = pcr.ifthenelse(basin, pcr.scalar(pcr.subcatchment(ldd, height_river)), pcr.scalar(pcr.spreadzone(height_river, 0, friction))) # replace areas outside of basin by a spread zone calculation. # make negative HANDS also possible if neg_HAND == 1: hand = (pcr.scalar(pcr.ordinal(dem*100))-up_elevation)/100 # convert back to float in DEM units else: hand = pcr.max(pcr.scalar(pcr.ordinal(dem*100))-up_elevation, 0)/100 # convert back to float in DEM units dist = pcr.ldddist(ldd, stream, 1) # compute horizontal distance estimate return hand, dist
def interpolategauges(inputmap, method): """" Interpolate time series gauge data onto a grid using different methods inputmap: map with points data for a single timestep method: string indicating the method inv pol input: inputmap, method returns: interpolated map """ if method == "inv": result = pcr.inversedistance(1, inputmap, 3, 0, 0) elif method == "pol": Unq = pcr.uniqueid(pcr.boolean(inputmap + 1)) result = pcr.spreadzone(pcr.ordinal(pcr.cover(Unq, 0)), 0, 1) result = pcr.areaaverage(inputmap, result) else: Unq = pcr.uniqueid(pcr.boolean(inputmap + 1)) result = pcr.spreadzone(pcr.ordinal(pcr.cover(Unq, 0)), 0, 1) result = pcr.areaaverage(inputmap, result) return result
def pcr_coast(dem, points): """ project points to coast with nearest neighbourhood finds coastal cells based on dem with NoDataValues and the locations of boundary conditions at sea using pcr spread the a nearest neighbor interpolation of the point ids is done for coastal cells :param dem: pcr dem :param points: pcrmap with ids in cells :returns: pcr map with location ids projected to coastline """ # clump areas based on NoDataValues in dem dem_NoDataValues = pcr.cover(pcr.ifthenelse(dem > -9999, pcr.boolean(0), pcr.boolean(1)), pcr.boolean(1)) # find number of boundary conditions in area where dem_novalue pcr.setglobaloption("nondiagonal") # only top, bottom, left, right area_nbounds = pcr.areatotal(pcr.scalar(points), pcr.clump(dem_NoDataValues)) * pcr.scalar(dem_NoDataValues) pcr.setglobaloption("diagonal") # diagonal again # make sea (True) and land (False) mask if np.any(pcr.pcr2numpy(area_nbounds,-9999) > 0): sea = pcr.ifthenelse(area_nbounds > 0, pcr.boolean(1), pcr.boolean(0)) else: sea = dem_NoDataValues # find coast based on sea in neighboring cells and at land (sea = 0) coast = pcr.ifthenelse((pcr.window4total(pcr.scalar(sea)) > pcr.scalar(0)) & (sea == pcr.boolean(0)), pcr.boolean(1), pcr.boolean(0)) # move points to nearest sea cell(s) point_dist = pcr.ifthenelse(sea, pcr.spread(points, 0, 1), 1E31) # distance from each point for sea cells nnpoints = pcr.ifthenelse(sea, pcr.spreadzone(points, 0, 1), 0) # closest point for sea cells dist2sea = pcr.areaminimum(point_dist, nnpoints) # shortest distance to each point to sea points_in_sea = pcr.nominal(pcr.ifthenelse(dist2sea == point_dist, nnpoints, 0)) # map points to nearest sea cell # map point at sea to coastline according to shortest distance over sea res = pcr.ifthenelse((pcr.scalar(sea) + pcr.scalar(coast)) >= 1, pcr.scalar(1), 1E31) # mask out non sea or coast cells ids_coastline = pcr.scalar(pcr.spreadzone(points_in_sea, 0, res)) * pcr.scalar(coast) return ids_coastline, points_in_sea
def subcatch_stream(ldd, threshold, stream=None, min_strahler=-999, max_strahler=999, assign_edge=False, assign_existing=False, up_area=None, basin=None): """ Derive catchments based upon strahler threshold Input: ldd -- pcraster object direction, local drain directions threshold -- integer, strahler threshold, subcatchments ge threshold are derived stream=None -- pcraster object ordinal, stream order map (made with pcr.streamorder), if provided, stream order map is not generated on the fly but used from this map. Useful when a subdomain within a catchment is provided, which would cause edge effects in the stream order map min_strahler=-999 -- integer, minimum strahler threshold of river catchments to return max_strahler=999 -- integer, maximum strahler threshold of river catchments to return assign_unique=False -- if set to True, unassigned connected areas at the edges of the domain are assigned a unique id as well. If set to False, edges are not assigned assign_existing=False == if set to True, unassigned edges are assigned to existing basins with an upstream weighting. If set to False, edges are assigned to unique IDs, or not assigned output: stream_ge -- pcraster object, streams of strahler order ge threshold subcatch -- pcraster object, subcatchments of strahler order ge threshold """ # derive stream order if stream is None: stream = pcr.streamorder(ldd) stream_ge = pcr.ifthen(stream >= threshold, stream) stream_up_sum = pcr.ordinal(pcr.upstream(ldd, pcr.cover(pcr.scalar(stream_ge), 0))) # detect any transfer of strahler order, to a higher strahler order. transition_strahler = pcr.ifthenelse(pcr.downstream(ldd, stream_ge) != stream_ge, pcr.boolean(1), pcr.ifthenelse(pcr.nominal(ldd) == 5, pcr.boolean(1), pcr.ifthenelse(pcr.downstream(ldd, pcr.scalar(stream_up_sum)) > pcr.scalar(stream_ge), pcr.boolean(1), pcr.boolean(0)))) # make unique ids (write to file) transition_unique = pcr.ordinal(pcr.uniqueid(transition_strahler)) # derive upstream catchment areas (write to file) subcatch = pcr.nominal(pcr.subcatchment(ldd, transition_unique)) # mask out areas outside basin if basin is not None: subcatch = pcr.ifthen(basin, subcatch) if assign_edge: # fill unclassified areas (in pcraster equal to zero) with a unique id, above the maximum id assigned so far unique_edge = pcr.clump(pcr.ifthen(subcatch==0, pcr.ordinal(0))) subcatch = pcr.ifthenelse(subcatch==0, pcr.nominal(pcr.mapmaximum(pcr.scalar(subcatch)) + pcr.scalar(unique_edge)), pcr.nominal(subcatch)) elif assign_existing: # unaccounted areas are added to largest nearest draining basin if up_area is None: up_area = pcr.ifthen(pcr.boolean(pcr.cover(stream_ge, 0)), pcr.accuflux(ldd, 1)) riverid = pcr.ifthen(pcr.boolean(pcr.cover(stream_ge, 0)), subcatch) friction = 1./pcr.scalar(pcr.spreadzone(pcr.cover(pcr.ordinal(up_area), 0), 0, 0)) # *(pcr.scalar(ldd)*0+1) delta = pcr.ifthen(pcr.scalar(ldd)>=0, pcr.ifthen(pcr.cover(subcatch, 0)==0, pcr.spreadzone(pcr.cover(riverid, 0), 0, friction))) subcatch = pcr.ifthenelse(pcr.boolean(pcr.cover(subcatch, 0)), subcatch, delta) # finally, only keep basins with minimum and maximum river order flowing through them strahler_subcatch = pcr.areamaximum(stream, subcatch) subcatch = pcr.ifthen(pcr.ordinal(strahler_subcatch) >= min_strahler, pcr.ifthen(pcr.ordinal(strahler_subcatch) <= max_strahler, subcatch)) return stream_ge, pcr.ordinal(subcatch)
workdir + 'temp.shp', catchments_tif)) else: call(('gdal_rasterize', '-a', 'ID', '-l', "temp", workdir + 'temp.shp', catchments_tif)) call(('gdal_translate', '-of', 'PCRaster', '-a_srs', clone_EPSG, catchments_tif, catchments_map)) catchments = pcr.readmap(catchments_map) riverunique = pcr.clump(pcr.nominal(pcr.ifthen(riverburn > 0, riverburn))) rivercatch = pcr.areamajority(pcr.ordinal(catchments), riverunique) #catchments = pcr.cover(pcr.ordinal(rivercatch),pcr.ordinal(pcr.ifthen(catchments > 0, catchments)),pcr.ordinal(0)) catchments = pcr.cover( pcr.ifthen(catchments > 0, pcr.ordinal(catchments)), pcr.ifthen( riverburn > 0, pcr.ordinal( pcr.spreadzone(pcr.nominal(catchments), pcr.ifthen(riverburn > 0, pcr.scalar(1)), 1)))) rivercatch_map = workdir + "catchments_river.map" catchclip_map = workdir + "catchments_clip.map" pcr.report(rivercatch, rivercatch_map) pcr.report(catchments, catchclip_map) ds = ogr.Open(workdir + "temp.shp") lyr = ds.GetLayerByName("temp") print 'calculating ldd' for i in range(lyr.GetFeatureCount()): feature = lyr.GetFeature(i) catch = int(feature.GetField("ID")) print "calculating ldd for catchment: " + str(i + 1) + "/" + str( lyr.GetFeatureCount()) + "...." ldddem_select = pcr.scalar(pcr.ifthen(catchments == catch,
def main(): clone_map = "mask\mask.map" clone_shp = "mask\mask.shp" clone_prj = "mask\mask.prj" workdir = "work\\" resultdir = "staticmaps\\" ''' read commandline arguments ''' argv = sys.argv clone_EPSG = False try: opts, args = getopt.getopt(argv[1:], 'i:g:p:r:c:d:l:s:CA') except getopt.error: print 'fout' Usage() sys.exit(1) inifile = None rivshp = None catchshp = None dem_in = None landuse = None soiltype = None clean = False gaugeshp = None alltouching = False for o, a in opts: if o == '-i': inifile = a if o == '-p': clone_EPSG = 'EPSG:' + a if o == '-r': rivshp = a if o == '-c': catchshp = a if o == '-d': dem_in = a if o == '-l': landuse = a if o == '-s': soiltype = a if o == '-C': clean = True if o == '-g': gaugeshp = a if o == '-A': alltouching = True if inifile == None or rivshp == None or catchshp == None or dem_in == None: print 'the following files are compulsory:' print ' - ini-file' print ' - DEM (raster)' print ' - river (shape)' print ' - catchment (shape)' Usage() sys.exit(1) if landuse == None: print 'no raster with landuse classifications is specified. 1 class will be applied for the entire domain' if soiltype == None: print 'no raster with soil classifications is specified. 1 class will be applied for the entire domain' ''' read mask ''' if not os.path.exists(clone_map): print 'Mask not found. Make sure the file mask\mask.map exists' print 'This file is usually created with the CreateGrid script' sys.exit(1) else: pcr.setclone(clone_map) ds = gdal.Open(clone_map, GA_ReadOnly) clone_trans = ds.GetGeoTransform() cellsize = clone_trans[1] clone_rows = ds.RasterYSize clone_columns = ds.RasterXSize extent_mask = [ clone_trans[0], clone_trans[3] - ds.RasterYSize * cellsize, clone_trans[0] + ds.RasterXSize * cellsize, clone_trans[3] ] xmin, ymin, xmax, ymax = map(str, extent_mask) ds = None ones = pcr.scalar(pcr.readmap(clone_map)) zeros = ones * 0 empty = pcr.ifthen(ones == 0, pcr.scalar(0)) ''' read projection from mask.shp ''' # TODO: check how to deal with projections (add .prj to mask.shp in creategrid) if not os.path.exists(clone_prj): print 'please add prj-file to mask.shp' sys.exit(1) if os.path.exists(clone_shp): ds = ogr.Open(clone_shp) file_att = os.path.splitext(os.path.basename(clone_shp))[0] lyr = ds.GetLayerByName(file_att) spatialref = lyr.GetSpatialRef() if not spatialref == None: srs_clone = osr.SpatialReference() srs_clone.ImportFromWkt(spatialref.ExportToWkt()) srs_clone.AutoIdentifyEPSG() unit_clone = False unit_clone = srs_clone.GetAttrValue('UNIT').lower() #clone_EPSG = 'EPSG:'+srs_clone.GetAttrValue("AUTHORITY",1) # TODO: fix hard EPSG code below clone_EPSG = 'EPSG:' + '4167' print 'EPSG-code is read from mask.shp: ' + clone_EPSG spatialref == None if not clone_EPSG: print 'EPSG-code cannot be read from mask.shp' print 'please add prj-file to mask.shp or specify on command line' print 'e.g. -p EPSG:4326 (for WGS84 lat lon projection)' ds = None clone_EPSG_int = int(clone_EPSG[5:len(clone_EPSG)]) ''' open config-file ''' config = wt.OpenConf(inifile) ''' read settings ''' snapgaugestoriver = bool( int(wt.configget(config, "settings", "snapgaugestoriver", "1"))) burnalltouching = bool( int(wt.configget(config, "settings", "burncatchalltouching", "1"))) burninorder = bool( int(wt.configget(config, "settings", "burncatchalltouching", "0"))) verticetollerance = float( wt.configget(config, "settings", "vertice_tollerance", "0.0001")) ''' read parameters ''' burn_outlets = int( wt.configget(config, "parameters", "burn_outlets", 10000)) burn_rivers = int(wt.configget(config, "parameters", "burn_rivers", 200)) burn_connections = int( wt.configget(config, "parameters", "burn_connections", 100)) burn_gauges = int(wt.configget(config, "parameters", "burn_gauges", 100)) minorder = int(wt.configget(config, "parameters", "riverorder_min", 3)) exec "percentile=tr.array(" + wt.configget(config, "parameters", "statisticmaps", [0, 100]) + ")" if not unit_clone: print 'failed to read unit (meter or degree) from mask projection' unit_clone = str(wt.configget(config, "settings", "unit", 'meter')) print 'unit read from settings: ' + unit_clone if unit_clone == 'degree': cellsize_hr = float( wt.configget(config, "parameters", "highres_degree", 0.0005)) elif (unit_clone == 'metre') or (unit_clone == 'meter'): cellsize_hr = float( wt.configget(config, "parameters", "highres_metre", 50)) cols_hr = int((float(xmax) - float(xmin)) / cellsize_hr + 2) rows_hr = int((float(ymax) - float(ymin)) / cellsize_hr + 2) hr_trans = (float(xmin), cellsize_hr, float(0), float(ymax), 0, -cellsize_hr) ''' read staticmap locations ''' catchment_map = wt.configget(config, "staticmaps", "catchment", "wflow_catchment.map") dem_map = wt.configget(config, "staticmaps", "dem", "wflow_dem.map") demmax_map = wt.configget(config, "staticmaps", "demmax", "wflow_demmax.map") demmin_map = wt.configget(config, "staticmaps", "demmin", "wflow_demmin.map") gauges_map = wt.configget(config, "staticmaps", "gauges", "wflow_gauges.map") landuse_map = wt.configget(config, "staticmaps", "landuse", "wflow_landuse.map") ldd_map = wt.configget(config, "staticmaps", "ldd", "wflow_ldd.map") river_map = wt.configget(config, "staticmaps", "river", "wflow_river.map") outlet_map = wt.configget(config, "staticmaps", "outlet", "wflow_outlet.map") riverlength_fact_map = wt.configget(config, "staticmaps", "riverlength_fact", "wflow_riverlength_fact.map") soil_map = wt.configget(config, "staticmaps", "soil", "wflow_soil.map") streamorder_map = wt.configget(config, "staticmaps", "streamorder", "wflow_streamorder.map") subcatch_map = wt.configget(config, "staticmaps", "subcatch", "wflow_subcatch.map") ''' read mask location (optional) ''' masklayer = wt.configget(config, "mask", "masklayer", catchshp) ''' create directories ''' if os.path.isdir(workdir): shutil.rmtree(workdir) os.makedirs(workdir) if os.path.isdir(resultdir): shutil.rmtree(resultdir) os.makedirs(resultdir) ''' Preperation steps ''' zero_map = workdir + "zero.map" zero_tif = workdir + "zero.tif" pcr.report(zeros, zero_map) # TODO: replace gdal_translate call call(('gdal_translate', '-of', 'GTiff', '-a_srs', clone_EPSG, '-ot', 'Float32', zero_map, zero_tif)) pcr.setglobaloption("lddin") ''' resample DEM ''' dem_resample = workdir + "dem_resampled.tif" ds = gdal.Open(dem_in, GA_ReadOnly) band = ds.GetRasterBand(1) nodata = band.GetNoDataValue() proj = ds.GetGeoTransform() cellsize_dem = proj[1] ''' read DEM projection ''' spatialref == None spatialref = ds.GetProjection() if not spatialref == None: srs = osr.SpatialReference() srs.ImportFromWkt(spatialref) srs.AutoIdentifyEPSG() dem_EPSG = 'EPSG:' + srs.GetAttrValue("AUTHORITY", 1) print 'EPSG-code is read from ' + os.path.basename( dem_in) + ': ' + dem_EPSG spatialref == None dem_EPSG_int = int(dem_EPSG[5:len(dem_EPSG)]) srs_DEM = osr.SpatialReference() srs_DEM.ImportFromEPSG(dem_EPSG_int) clone2dem_transform = osr.CoordinateTransformation(srs_clone, srs_DEM) else: dem_EPSG = clone_EPSG print 'No projection defined for ' + os.path.basename(dem_in) print 'Assumed to be the same as model projection (' + clone_EPSG + ')' ds = None print 'Resampling DEM...' if nodata == None: call(('gdalwarp', '-overwrite', '-t_srs', clone_prj, '-te', xmin, ymin, xmax, ymax, '-tr', str(cellsize), str(-cellsize), '-dstnodata', str(-9999), '-r', 'cubic', dem_in, dem_resample)) else: call(('gdalwarp', '-overwrite', '-t_srs', clone_prj, '-te', xmin, ymin, xmax, ymax, '-tr', str(cellsize), str(-cellsize), '-srcnodata', str(nodata), '-dstnodata', str(nodata), '-r', 'cubic', dem_in, dem_resample)) ''' create dem.map and statistic maps ''' dem_resample_map = resultdir + dem_map call(('gdal_translate', '-of', 'PCRaster', '-a_srs', clone_EPSG, '-ot', 'Float32', dem_resample, dem_resample_map)) print 'Computing DEM statistics ....' stats = wt.windowstats(dem_in, clone_rows, clone_columns, clone_trans, srs_clone, resultdir, percentile) ''' burn DEM ''' ds = ogr.Open(rivshp) file_att = os.path.splitext(os.path.basename(rivshp))[0] lyr = ds.GetLayerByName(file_att) spatialref = lyr.GetSpatialRef() # if not spatialref == None: # srs = osr.SpatialReference() # srs.ImportFromWkt(spatialref.ExportToWkt()) # srs.AutoIdentifyEPSG() # rivshp_EPSG = 'EPSG:'+srs.GetAttrValue("AUTHORITY",1) # spatialref == None # else: rivshp_EPSG = clone_EPSG print 'No projection defined for ' + file_att + '.shp' print 'Assumed to be the same as model projection (' + clone_EPSG + ')' # strip rivers to nodes xminc = str(float(xmin) + 0.5 * cellsize) yminc = str(float(ymin) + 0.5 * cellsize) xmaxc = str(float(xmax) - 0.5 * cellsize) ymaxc = str(float(ymax) - 0.5 * cellsize) if rivshp_EPSG == clone_EPSG: rivclipshp = workdir + 'rivshape_clip.shp' call(('ogr2ogr', '-s_srs', clone_EPSG, '-t_srs', clone_EPSG, '-spat', xmin, ymin, xmax, ymax, '-clipsrc', xminc, yminc, xmaxc, ymaxc, rivclipshp, rivshp)) else: rivprojshp = workdir + 'rivshape_proj.shp' rivclipshp = workdir + 'rivshape_clip.shp' call(('ogr2ogr', '-s_srs', rivshp_EPSG, '-t_srs', clone_EPSG, '-spat', xmin, ymin, xmax, ymax, rivprojshp, rivshp)) call(('ogr2ogr', '-s_srs', clone_EPSG, '-t_srs', clone_EPSG, '-spat', xmin, ymin, xmax, ymax, '-clipsrc', xminc, yminc, xmaxc, ymaxc, rivclipshp, rivprojshp)) rivshp = rivclipshp #### BURNING BELOW #### # TODO: check if extraction can be done within memory and retun a burn layer shapes = wt.Reach2Nodes(rivclipshp, clone_EPSG_int, cellsize * verticetollerance, workdir) outlets = shapes[1] connections = shapes[2] outlets_att = os.path.splitext(os.path.basename(outlets))[0] connections_att = os.path.splitext(os.path.basename(connections))[0] dem_resample_att = os.path.splitext(os.path.basename(dem_resample))[0] connections_tif = workdir + connections_att + ".tif" outlets_tif = workdir + outlets_att + ".tif" # TODO: make the burning in memory call(('gdal_translate', '-of', 'GTiff', '-a_srs', clone_EPSG, '-ot', 'Float32', zero_map, connections_tif)) call(('gdal_translate', '-of', 'GTiff', '-a_srs', clone_EPSG, '-ot', 'Float32', zero_map, outlets_tif)) call(('gdal_rasterize', '-burn', '1', '-l', outlets_att, outlets, outlets_tif)) call(('gdal_rasterize', '-burn', '1', '-l', connections_att, connections, connections_tif)) # convert rivers to order rivshp_att = os.path.splitext(os.path.basename(rivshp))[0] rivers_tif = workdir + rivshp_att + ".tif" call(('gdal_translate', '-of', 'GTiff', '-a_srs', clone_EPSG, '-ot', 'Float32', zero_map, rivers_tif)) if burninorder: # make river shape with an order attribute OrderSHPs = wt.ReachOrder(rivshp, clone_EPSG_int, cellsize * verticetollerance, workdir) wt.Burn2Tif(OrderSHPs, 'order', rivers_tif) else: call(('gdal_rasterize', '-burn', '1', '-l', rivshp_att, rivshp, rivers_tif)) # convert 2 maps connections_map = workdir + connections_att + ".map" rivers_map = workdir + rivshp_att + ".map" outlets_map = workdir + outlets_att + ".map" call(('gdal_translate', '-of', 'PCRaster', '-a_srs', clone_EPSG, '-ot', 'Float32', connections_tif, connections_map)) call(('gdal_translate', '-of', 'PCRaster', '-a_srs', clone_EPSG, '-ot', 'Float32', rivers_tif, rivers_map)) call(('gdal_translate', '-of', 'PCRaster', '-a_srs', clone_EPSG, '-ot', 'Float32', outlets_tif, outlets_map)) # burn the layers in DEM outletsburn = pcr.scalar( pcr.readmap(outlets_map)) * pcr.scalar(burn_outlets) connectionsburn = pcr.scalar( pcr.readmap(connections_map)) * pcr.scalar(burn_connections) riverburn = pcr.scalar(pcr.readmap(rivers_map)) * pcr.scalar(burn_rivers) ldddem = pcr.cover(dem_resample_map, pcr.ifthen(riverburn > 0, pcr.scalar(0))) ldddem = ldddem - outletsburn - connectionsburn - riverburn ldddem = pcr.cover(ldddem, pcr.scalar(0)) pcr.report(ldddem, workdir + "dem_burn.map") ''' create ldd for multi-catchments ''' ldd = pcr.ldd(empty) # reproject catchment shape-file ds = ogr.Open(catchshp) file_att = os.path.splitext(os.path.basename(catchshp))[0] lyr = ds.GetLayerByName(file_att) spatialref = lyr.GetSpatialRef() # if not spatialref == None: # srs = osr.SpatialReference() # srs.ImportFromWkt(spatialref.ExportToWkt()) # srs.AutoIdentifyEPSG() # catchshp_EPSG = 'EPSG:'+srs.GetAttrValue("AUTHORITY",1) # spatialref == None # else: catchshp_EPSG = clone_EPSG print 'No projection defined for ' + file_att + '.shp' print 'Assumed to be the same as model projection (' + clone_EPSG + ')' if not rivshp_EPSG == clone_EPSG: catchprojshp = workdir + 'catchshape_proj.shp' call(('ogr2ogr', '-s_srs', catchshp_EPSG, '-t_srs', clone_ESPG, catchprojshp, catchshp)) catchshp = catchprojshp ds.Destroy() ds = ogr.Open(catchshp) file_att = os.path.splitext(os.path.basename(catchshp))[0] lyr = ds.GetLayerByName(file_att) fieldDef = ogr.FieldDefn("ID", ogr.OFTString) fieldDef.SetWidth(12) TEMP_out = Driver.CreateDataSource(workdir + "temp.shp") if not srs == None: TEMP_LYR = TEMP_out.CreateLayer("temp", srs, geom_type=ogr.wkbMultiPolygon) else: TEMP_LYR = TEMP_out.CreateLayer("temp", geom_type=ogr.wkbMultiPolygon) TEMP_LYR.CreateField(fieldDef) for i in range(lyr.GetFeatureCount()): orgfeature = lyr.GetFeature(i) geometry = orgfeature.geometry() feature = ogr.Feature(TEMP_LYR.GetLayerDefn()) feature.SetGeometry(geometry) feature.SetField("ID", str(i + 1)) TEMP_LYR.CreateFeature(feature) TEMP_out.Destroy() ds.Destroy # rasterize catchment map catchments_tif = workdir + "catchments.tif" catchments_map = workdir + "catchments.map" call(('gdal_translate', '-of', 'GTiff', '-a_srs', clone_EPSG, zero_map, catchments_tif)) if alltouching: call(('gdal_rasterize', '-at', '-a', 'ID', '-l', "temp", workdir + 'temp.shp', catchments_tif)) else: call(('gdal_rasterize', '-a', 'ID', '-l', "temp", workdir + 'temp.shp', catchments_tif)) call(('gdal_translate', '-of', 'PCRaster', '-a_srs', clone_EPSG, catchments_tif, catchments_map)) catchments = pcr.readmap(catchments_map) riverunique = pcr.clump(pcr.nominal(pcr.ifthen(riverburn > 0, riverburn))) rivercatch = pcr.areamajority(pcr.ordinal(catchments), riverunique) #catchments = pcr.cover(pcr.ordinal(rivercatch),pcr.ordinal(pcr.ifthen(catchments > 0, catchments)),pcr.ordinal(0)) catchments = pcr.cover( pcr.ifthen(catchments > 0, pcr.ordinal(catchments)), pcr.ifthen( riverburn > 0, pcr.ordinal( pcr.spreadzone(pcr.nominal(catchments), pcr.ifthen(riverburn > 0, pcr.scalar(1)), 1)))) rivercatch_map = workdir + "catchments_river.map" catchclip_map = workdir + "catchments_clip.map" pcr.report(rivercatch, rivercatch_map) pcr.report(catchments, catchclip_map) ds = ogr.Open(workdir + "temp.shp") lyr = ds.GetLayerByName("temp") print 'calculating ldd' for i in range(lyr.GetFeatureCount()): feature = lyr.GetFeature(i) catch = int(feature.GetField("ID")) print "calculating ldd for catchment: " + str(i + 1) + "/" + str( lyr.GetFeatureCount()) + "...." ldddem_select = pcr.scalar(pcr.ifthen(catchments == catch, catchments)) * 0 + 1 * ldddem ldd_select = pcr.lddcreate(ldddem_select, float("1E35"), float("1E35"), float("1E35"), float("1E35")) ldd = pcr.cover(ldd, ldd_select) pcr.report(ldd, resultdir + ldd_map) ds.Destroy() ''' report stream order, river and dem ''' streamorder = pcr.ordinal(pcr.streamorder(ldd)) river = pcr.ifthen(streamorder >= pcr.ordinal(minorder), pcr.boolean(1)) mindem = int(np.min(pcr.pcr2numpy(pcr.ordinal(dem_resample_map), 9999999))) dem_resample_map = pcr.cover(dem_resample_map, pcr.scalar(river) * 0 + mindem) pcr.report(dem_resample_map, resultdir + dem_map) pcr.report(streamorder, resultdir + streamorder_map) pcr.report(river, resultdir + river_map) ''' deal with your catchments ''' if gaugeshp == None: print 'No gauges defined, using outlets instead' gauges = pcr.ordinal( pcr.uniqueid( pcr.boolean(pcr.ifthen(pcr.scalar(ldd) == 5, pcr.boolean(1))))) pcr.report(gauges, resultdir + gauges_map) # ds = ogr.Open(gaugeshp) # file_att = os.path.splitext(os.path.basename(gaugeshp))[0] # lyr = ds.GetLayerByName(file_att) # spatialref = lyr.GetSpatialRef() ## if not spatialref == None: ## srs = osr.SpatialReference() ## srs.ImportFromWkt(spatialref.ExportToWkt()) ## srs.AutoIdentifyEPSG() ## gaugeshp_EPSG = 'EPSG:'+srs.GetAttrValue("AUTHORITY",1) ## spatialref == None # #else: # gaugeshp_EPSG = clone_EPSG # print 'No projection defined for ' + file_att + '.shp' # print 'Assumed to be the same as model projection (' + clone_EPSG + ')' # # # reproject gauge shape if necesarry # if not gaugeshp_EPSG == clone_EPSG: # gaugeprojshp = workdir + 'gaugeshape_proj.shp' # call(('ogr2ogr','-s_srs',rivshp_EPSG,'-t_srs',clone_ESPG,gaugeprojshp,gaugeshp)) # gaugeshp = gaugeprojshp # # file_att = os.path.splitext(os.path.basename(gaugeshp))[0] # gaugestif = workdir + file_att + '.tif' # gaugesmap = workdir + file_att + '.map' # call(('gdal_translate','-of','GTiff','-a_srs',clone_EPSG,zero_map,gaugestif)) # call(('gdal_rasterize','-burn','1','-l',file_att,gaugeshp,gaugestif)) # call(('gdal_translate','-of','PCRaster','-a_srs',clone_EPSG,gaugestif,gaugesmap)) # gaugelocs = pcr.readmap(gaugesmap) # snapgaugestoriver = True # # if snapgaugestoriver: # print "Snapping gauges to river" # gauges = pcr.uniqueid(pcr.boolean(gaugelocs)) # gauges= wt.snaptomap(pcr.ordinal(gauges),river) # # gaugesmap = pcr.ifthen(gauges > 0, gauges) ''' report riverlengthfrac ''' riv_hr = workdir + 'river_highres.tif' wt.CreateTif(riv_hr, rows_hr, cols_hr, hr_trans, srs_clone, 0) file_att = os.path.splitext(os.path.basename(rivshp))[0] call(('gdal_rasterize', '-burn', '1', '-l', file_att, rivshp, riv_hr)) print 'Computing river length...' #riverlength = wt.windowstats(riv_hr,clone_rows,clone_columns,clone_trans,srs_clone,resultdir,'frac',clone2dem_transform) riverlength = wt.windowstats(riv_hr, clone_rows, clone_columns, clone_trans, srs_clone, resultdir, 'frac') ''' report outlet map ''' pcr.report(pcr.ifthen(pcr.ordinal(ldd) == 5, pcr.ordinal(1)), resultdir + outlet_map) ''' report map ''' catchment = pcr.ifthen(catchments > 0, pcr.ordinal(1)) pcr.report(catchment, resultdir + catchment_map) ''' report subcatchment map ''' subcatchment = pcr.subcatchment(ldd, gauges) pcr.report(pcr.ordinal(subcatchment), resultdir + subcatch_map) ''' report landuse map ''' if landuse == None: pcr.report(pcr.nominal(ones), resultdir + landuse_map) else: landuse_resample = workdir + 'landuse.tif' landuse_map = resultdir + landuse_map transform = wt.GetRasterTranform(landuse, srs_clone) if not transform[0]: call(('gdalwarp', '-overwrite', '-s_srs', clone_EPSG, '-t_srs', clone_EPSG, '-te', xmin, ymin, xmax, ymax, '-tr', str(cellsize), str(-cellsize), '-r', 'mode', landuse, landuse_resample)) else: call(('gdalwarp', '-overwrite', '-s_srs', transform[1], '-t_srs', clone_EPSG, '-te', xmin, ymin, xmax, ymax, '-tr', str(cellsize), str(-cellsize), '-r', 'mode', landuse, landuse_resample)) call(('gdal_translate', '-of', 'PCRaster', '-ot', 'Float32', landuse_resample, landuse_map)) landuse_work = pcr.readmap(landuse_map) pcr.report(pcr.nominal(landuse_work), landuse_map) ''' report soil map ''' if soiltype == None: pcr.report(pcr.nominal(ones), resultdir + soil_map) else: soiltype_resample = workdir + 'soiltype.tif' soil_map = resultdir + soil_map #transform = wt.GetRasterTranform(soiltype,srs_clone) # if not transform[0]: call(('gdalwarp', '-overwrite', '-s_srs', clone_EPSG, '-t_srs', clone_EPSG, '-te', xmin, ymin, xmax, ymax, '-tr', str(cellsize), str(-cellsize), '-r', 'mode', soiltype, soiltype_resample)) # else: # call(('gdalwarp','-overwrite','-s_srs',transform[1],'-t_srs',clone_EPSG,'-te', xmin, ymin, xmax, ymax,'-tr',str(cellsize),str(-cellsize),'-r','mode',soiltype, soiltype_resample)) call(('gdal_translate', '-of', 'PCRaster', '-ot', 'Float32', soiltype_resample, soil_map)) soiltype_work = pcr.readmap(soil_map) pcr.report(pcr.nominal(soiltype_work), soil_map) if clean: wt.DeleteList(glob.glob(os.getcwd() + '\\' + resultdir + '/*.xml'))
def main(): ### Read input arguments ##### parser = OptionParser() usage = "usage: %prog [options]" parser = OptionParser(usage=usage) parser.add_option('-q', '--quiet', dest='verbose', default=True, action='store_false', help='do not print status messages to stdout') parser.add_option('-i', '--ini', dest='inifile', default='hand_contour_inun.ini', nargs=1, help='ini configuration file') parser.add_option('-f', '--flood_map', nargs=1, dest='flood_map', help='Flood map file (NetCDF point time series file') parser.add_option('-v', '--flood_variable', nargs=1, dest='flood_variable', default='water_level', help='variable name of flood water level') parser.add_option( '-b', '--bankfull_map', dest='bankfull_map', default='', help= 'Map containing bank full level (is subtracted from flood map, in NetCDF)' ) parser.add_option( '-c', '--catchment', dest='catchment_strahler', default=7, type='int', help='Strahler order threshold >= are selected as catchment boundaries' ) parser.add_option('-s', '--hand_strahler', dest='hand_strahler', default=7, type='int', help='Strahler order threshold >= selected as riverine') parser.add_option('-d', '--destination', dest='dest_path', default='inun', help='Destination path') (options, args) = parser.parse_args() if not os.path.exists(options.inifile): print 'path to ini file cannot be found' sys.exit(1) options.dest_path = os.path.abspath(options.dest_path) if not (os.path.isdir(options.dest_path)): os.makedirs(options.dest_path) # set up the logger flood_name = os.path.split(options.flood_map)[1].split('.')[0] case_name = 'inun_{:s}_hand_{:02d}_catch_{:02d}'.format( flood_name, options.hand_strahler, options.catchment_strahler) logfilename = os.path.join(options.dest_path, 'hand_contour_inun.log') logger, ch = inun_lib.setlogger(logfilename, 'HAND_INUN', options.verbose) logger.info('$Id: $') logger.info('Flood map: {:s}'.format(options.flood_map)) logger.info('Bank full map: {:s}'.format(options.bankfull_map)) logger.info('Destination path: {:s}'.format(options.dest_path)) # read out ini file ### READ CONFIG FILE # open config-file config = inun_lib.open_conf(options.inifile) # read settings options.dem_file = inun_lib.configget(config, 'maps', 'dem_file', True) options.ldd_file = inun_lib.configget(config, 'maps', 'ldd_file', True) options.stream_file = inun_lib.configget(config, 'maps', 'stream_file', True) options.riv_length_file = inun_lib.configget(config, 'maps', 'riv_length_file', True) options.riv_width_file = inun_lib.configget(config, 'maps', 'riv_width_file', True) options.file_format = inun_lib.configget(config, 'maps', 'file_format', 0, datatype='int') options.x_tile = inun_lib.configget(config, 'tiling', 'x_tile', 10000, datatype='int') options.y_tile = inun_lib.configget(config, 'tiling', 'y_tile', 10000, datatype='int') options.x_overlap = inun_lib.configget(config, 'tiling', 'x_overlap', 1000, datatype='int') options.y_overlap = inun_lib.configget(config, 'tiling', 'y_overlap', 1000, datatype='int') options.iterations = inun_lib.configget(config, 'inundation', 'iterations', 20, datatype='int') options.initial_level = inun_lib.configget(config, 'inundation', 'initial_level', 32., datatype='float') options.area_multiplier = inun_lib.configget(config, 'inundation', 'area_multiplier', 1., datatype='float') logger.info('DEM file: {:s}'.format(options.dem_file)) logger.info('LDD file: {:s}'.format(options.ldd_file)) logger.info('Columns per tile: {:d}'.format(options.x_tile)) logger.info('Rows per tile: {:d}'.format(options.y_tile)) logger.info('Columns overlap: {:d}'.format(options.x_overlap)) logger.info('Rows overlap: {:d}'.format(options.y_overlap)) metadata_global = {} # add metadata from the section [metadata] meta_keys = config.options('metadata_global') for key in meta_keys: metadata_global[key] = config.get('metadata_global', key) # add a number of metadata variables that are mandatory metadata_global['config_file'] = os.path.abspath(options.inifile) metadata_var = {} metadata_var['units'] = 'm' metadata_var[ 'standard_name'] = 'water_surface_height_above_reference_datum' metadata_var['long_name'] = 'Coastal flooding' metadata_var[ 'comment'] = 'water_surface_reference_datum_altitude is given in file {:s}'.format( options.dem_file) if not os.path.exists(options.dem_file): logger.error('path to dem file {:s} cannot be found'.format( options.dem_file)) sys.exit(1) if not os.path.exists(options.ldd_file): logger.error('path to ldd file {:s} cannot be found'.format( options.ldd_file)) sys.exit(1) # Read extent from a GDAL compatible file try: extent = inun_lib.get_gdal_extent(options.dem_file) except: msg = 'Input file {:s} not a gdal compatible file'.format( options.dem_file) inun_lib.close_with_error(logger, ch, msg) sys.exit(1) try: x, y = inun_lib.get_gdal_axes(options.dem_file, logging=logger) srs = inun_lib.get_gdal_projection(options.dem_file, logging=logger) except: msg = 'Input file {:s} not a gdal compatible file'.format( options.dem_file) inun_lib.close_with_error(logger, ch, msg) sys.exit(1) # read history from flood file if options.file_format == 0: a = nc.Dataset(options.flood_map, 'r') metadata_global[ 'history'] = 'Created by: $Id: $, boundary conditions from {:s},\nhistory: {:s}'.format( os.path.abspath(options.flood_map), a.history) a.close() else: metadata_global[ 'history'] = 'Created by: $Id: $, boundary conditions from {:s},\nhistory: {:s}'.format( os.path.abspath(options.flood_map), 'PCRaster file, no history') # first write subcatch maps and hand maps ############### TODO ###### # setup a HAND file dem_name = os.path.split(options.dem_file)[1].split('.')[0] hand_file = os.path.join( options.dest_path, '{:s}_hand_strahler_{:02d}.tif'.format(dem_name, options.hand_strahler)) if not (os.path.isfile(hand_file)): # hand file does not exist yet! Generate it, otherwise skip! logger.info( 'HAND file {:s} setting up...please wait...'.format(hand_file)) hand_file_tmp = os.path.join( options.dest_path, '{:s}_hand_strahler_{:02d}.tif.tmp'.format(dem_name, options.hand_strahler)) ds_hand = inun_lib.prepare_gdal(hand_file_tmp, x, y, logging=logger, srs=srs) band_hand = ds_hand.GetRasterBand(1) # Open terrain data for reading ds_dem, rasterband_dem = inun_lib.get_gdal_rasterband(options.dem_file) ds_ldd, rasterband_ldd = inun_lib.get_gdal_rasterband(options.ldd_file) ds_stream, rasterband_stream = inun_lib.get_gdal_rasterband( options.stream_file) n = 0 for x_loop in range(0, len(x), options.x_tile): x_start = np.maximum(x_loop, 0) x_end = np.minimum(x_loop + options.x_tile, len(x)) # determine actual overlap for cutting for y_loop in range(0, len(y), options.y_tile): x_overlap_min = x_start - np.maximum( x_start - options.x_overlap, 0) x_overlap_max = np.minimum(x_end + options.x_overlap, len(x)) - x_end n += 1 # print('tile {:001d}:'.format(n)) y_start = np.maximum(y_loop, 0) y_end = np.minimum(y_loop + options.y_tile, len(y)) y_overlap_min = y_start - np.maximum( y_start - options.y_overlap, 0) y_overlap_max = np.minimum(y_end + options.y_overlap, len(y)) - y_end # cut out DEM logger.debug( 'Computing HAND for xmin: {:d} xmax: {:d} ymin {:d} ymax {:d}' .format(x_start, x_end, y_start, y_end)) terrain = rasterband_dem.ReadAsArray( x_start - x_overlap_min, y_start - y_overlap_min, (x_end + x_overlap_max) - (x_start - x_overlap_min), (y_end + y_overlap_max) - (y_start - y_overlap_min)) drainage = rasterband_ldd.ReadAsArray( x_start - x_overlap_min, y_start - y_overlap_min, (x_end + x_overlap_max) - (x_start - x_overlap_min), (y_end + y_overlap_max) - (y_start - y_overlap_min)) stream = rasterband_stream.ReadAsArray( x_start - x_overlap_min, y_start - y_overlap_min, (x_end + x_overlap_max) - (x_start - x_overlap_min), (y_end + y_overlap_max) - (y_start - y_overlap_min)) # write to temporary file terrain_temp_file = os.path.join(options.dest_path, 'terrain_temp.map') drainage_temp_file = os.path.join(options.dest_path, 'drainage_temp.map') stream_temp_file = os.path.join(options.dest_path, 'stream_temp.map') if rasterband_dem.GetNoDataValue() is not None: inun_lib.gdal_writemap(terrain_temp_file, 'PCRaster', np.arange(0, terrain.shape[1]), np.arange(0, terrain.shape[0]), terrain, rasterband_dem.GetNoDataValue(), gdal_type=gdal.GDT_Float32, logging=logger) else: # in case no nodata value is found logger.warning( 'No nodata value found in {:s}. assuming -9999'.format( options.dem_file)) inun_lib.gdal_writemap(terrain_temp_file, 'PCRaster', np.arange(0, terrain.shape[1]), np.arange(0, terrain.shape[0]), terrain, -9999., gdal_type=gdal.GDT_Float32, logging=logger) inun_lib.gdal_writemap(drainage_temp_file, 'PCRaster', np.arange(0, terrain.shape[1]), np.arange(0, terrain.shape[0]), drainage, rasterband_ldd.GetNoDataValue(), gdal_type=gdal.GDT_Int32, logging=logger) inun_lib.gdal_writemap(stream_temp_file, 'PCRaster', np.arange(0, terrain.shape[1]), np.arange(0, terrain.shape[0]), stream, rasterband_ldd.GetNoDataValue(), gdal_type=gdal.GDT_Int32, logging=logger) # read as pcr objects pcr.setclone(terrain_temp_file) terrain_pcr = pcr.readmap(terrain_temp_file) drainage_pcr = pcr.lddrepair( pcr.ldd(pcr.readmap( drainage_temp_file))) # convert to ldd type map stream_pcr = pcr.scalar( pcr.readmap(stream_temp_file)) # convert to ldd type map # compute streams stream_ge, subcatch = inun_lib.subcatch_stream( drainage_pcr, stream_pcr, options.hand_strahler) # generate streams basin = pcr.boolean(subcatch) hand_pcr, dist_pcr = inun_lib.derive_HAND( terrain_pcr, drainage_pcr, 3000, rivers=pcr.boolean(stream_ge), basin=basin) # convert to numpy hand = pcr.pcr2numpy(hand_pcr, -9999.) # cut relevant part if y_overlap_max == 0: y_overlap_max = -hand.shape[0] if x_overlap_max == 0: x_overlap_max = -hand.shape[1] hand_cut = hand[0 + y_overlap_min:-y_overlap_max, 0 + x_overlap_min:-x_overlap_max] band_hand.WriteArray(hand_cut, x_start, y_start) os.unlink(terrain_temp_file) os.unlink(drainage_temp_file) band_hand.FlushCache() ds_dem = None ds_ldd = None ds_stream = None band_hand.SetNoDataValue(-9999.) ds_hand = None logger.info('Finalizing {:s}'.format(hand_file)) # rename temporary file to final hand file os.rename(hand_file_tmp, hand_file) else: logger.info( 'HAND file {:s} already exists...skipping...'.format(hand_file)) ##################################################################################### # HAND file has now been prepared, moving to flood mapping part # ##################################################################################### # load the staticmaps needed to estimate volumes across all xax, yax, riv_length, fill_value = inun_lib.gdal_readmap( options.riv_length_file, 'GTiff') riv_length = np.ma.masked_where(riv_length == fill_value, riv_length) xax, yax, riv_width, fill_value = inun_lib.gdal_readmap( options.riv_width_file, 'GTiff') riv_width[riv_width == fill_value] = 0 x_res = np.abs((xax[-1] - xax[0]) / (len(xax) - 1)) y_res = np.abs((yax[-1] - yax[0]) / (len(yax) - 1)) flood_folder = os.path.join(options.dest_path, case_name) flood_vol_map = os.path.join( flood_folder, '{:s}_vol.tif'.format( os.path.split(options.flood_map)[1].split('.')[0])) if not (os.path.isdir(flood_folder)): os.makedirs(flood_folder) inun_file_tmp = os.path.join(flood_folder, '{:s}.tif.tmp'.format(case_name)) inun_file = os.path.join(flood_folder, '{:s}.tif'.format(case_name)) hand_temp_file = os.path.join(flood_folder, 'hand_temp.map') drainage_temp_file = os.path.join(flood_folder, 'drainage_temp.map') stream_temp_file = os.path.join(flood_folder, 'stream_temp.map') flood_vol_temp_file = os.path.join(flood_folder, 'flood_warp_temp.tif') # load the data with river levels and compute the volumes if options.file_format == 0: # assume we need the maximum value in a NetCDF time series grid a = nc.Dataset(options.flood_map, 'r') xax = a.variables['x'][:] yax = a.variables['y'][:] flood_series = a.variables[options.flood_variable][:] flood_data = flood_series.max(axis=0) if np.ma.is_masked(flood_data): flood = flood_data.data flood[flood_data.mask] = 0 if yax[-1] > yax[0]: yax = np.flipud(yax) flood = np.flipud(flood) a.close() elif options.file_format == 1: xax, yax, flood, flood_fill_value = inun_lib.gdal_readmap( options.flood_map, 'PCRaster') flood[flood == flood_fill_value] = 0. #res_x = x[1]-x[0] #res_y = y[1]-y[0] # load the bankfull depths if options.bankfull_map == '': bankfull = np.zeros(flood.shape) else: if options.file_format == 0: a = nc.Dataset(options.bankfull_map, 'r') xax = a.variables['x'][:] yax = a.variables['y'][:] bankfull = a.variables[options.flood_variable][0, :, :] if yax[-1] > yax[0]: yax = np.flipud(yax) bankfull = np.flipud(bankful) a.close() elif options.file_format == 1: xax, yax, bankfull, bankfull_fill_value = inun_lib.gdal_readmap( options.bankfull_map, 'PCRaster') # flood = bankfull*2 # res_x = 2000 # res_y = 2000 # subtract the bankfull water level to get flood levels (above bankfull) flood_vol = np.maximum(flood - bankfull, 0) flood_vol_m = riv_length * riv_width * flood_vol / ( x_res * y_res ) # volume expressed in meters water disc (1e6 is the surface area of one wflow grid cell) flood_vol_m_data = flood_vol_m.data flood_vol_m_data[flood_vol_m.mask] = -999. print('Saving water layer map to {:s}'.format(flood_vol_map)) # write to a tiff file inun_lib.gdal_writemap(flood_vol_map, 'GTiff', xax, yax, np.maximum(flood_vol_m_data, 0), -999.) ds_hand, rasterband_hand = inun_lib.get_gdal_rasterband(hand_file) ds_ldd, rasterband_ldd = inun_lib.get_gdal_rasterband(options.ldd_file) ds_stream, rasterband_stream = inun_lib.get_gdal_rasterband( options.stream_file) logger.info( 'Preparing flood map in {:s} ...please wait...'.format(inun_file)) ds_inun = inun_lib.prepare_gdal(inun_file_tmp, x, y, logging=logger, srs=srs) band_inun = ds_inun.GetRasterBand(1) # loop over all the tiles n = 0 for x_loop in range(0, len(x), options.x_tile): x_start = np.maximum(x_loop, 0) x_end = np.minimum(x_loop + options.x_tile, len(x)) # determine actual overlap for cutting for y_loop in range(0, len(y), options.y_tile): x_overlap_min = x_start - np.maximum(x_start - options.x_overlap, 0) x_overlap_max = np.minimum(x_end + options.x_overlap, len(x)) - x_end n += 1 # print('tile {:001d}:'.format(n)) y_start = np.maximum(y_loop, 0) y_end = np.minimum(y_loop + options.y_tile, len(y)) y_overlap_min = y_start - np.maximum(y_start - options.y_overlap, 0) y_overlap_max = np.minimum(y_end + options.y_overlap, len(y)) - y_end x_tile_ax = x[x_start - x_overlap_min:x_end + x_overlap_max] y_tile_ax = y[y_start - y_overlap_min:y_end + y_overlap_max] # cut out DEM logger.debug( 'handling xmin: {:d} xmax: {:d} ymin {:d} ymax {:d}'.format( x_start, x_end, y_start, y_end)) hand = rasterband_hand.ReadAsArray( x_start - x_overlap_min, y_start - y_overlap_min, (x_end + x_overlap_max) - (x_start - x_overlap_min), (y_end + y_overlap_max) - (y_start - y_overlap_min)) drainage = rasterband_ldd.ReadAsArray( x_start - x_overlap_min, y_start - y_overlap_min, (x_end + x_overlap_max) - (x_start - x_overlap_min), (y_end + y_overlap_max) - (y_start - y_overlap_min)) stream = rasterband_stream.ReadAsArray( x_start - x_overlap_min, y_start - y_overlap_min, (x_end + x_overlap_max) - (x_start - x_overlap_min), (y_end + y_overlap_max) - (y_start - y_overlap_min)) print('len x-ax: {:d} len y-ax {:d} x-shape {:d} y-shape {:d}'. format(len(x_tile_ax), len(y_tile_ax), hand.shape[1], hand.shape[0])) inun_lib.gdal_writemap(hand_temp_file, 'PCRaster', x_tile_ax, y_tile_ax, hand, rasterband_hand.GetNoDataValue(), gdal_type=gdal.GDT_Float32, logging=logger) inun_lib.gdal_writemap(drainage_temp_file, 'PCRaster', x_tile_ax, y_tile_ax, drainage, rasterband_ldd.GetNoDataValue(), gdal_type=gdal.GDT_Int32, logging=logger) inun_lib.gdal_writemap(stream_temp_file, 'PCRaster', x_tile_ax, y_tile_ax, stream, rasterband_stream.GetNoDataValue(), gdal_type=gdal.GDT_Int32, logging=logger) # read as pcr objects pcr.setclone(hand_temp_file) hand_pcr = pcr.readmap(hand_temp_file) drainage_pcr = pcr.lddrepair( pcr.ldd(pcr.readmap( drainage_temp_file))) # convert to ldd type map stream_pcr = pcr.scalar( pcr.readmap(drainage_temp_file)) # convert to ldd type map # prepare a subcatchment map stream_ge, subcatch = inun_lib.subcatch_stream( drainage_pcr, stream_pcr, options.catchment_strahler) # generate subcatchments drainage_surf = pcr.ifthen( stream_ge > 0, pcr.accuflux( drainage_pcr, 1)) # proxy of drainage surface inaccurate at tile edges # compute weights for spreadzone (1/drainage_surf) subcatch = pcr.spreadzone(subcatch, 0, 0) # TODO check weighting scheme, perhaps not necessary # weight = 1./pcr.scalar(pcr.spreadzone(pcr.cover(pcr.ordinal(drainage_surf), 0), 0, 0)) # subcatch_fill = pcr.scalar(pcr.spreadzone(subcatch, 0, weight)) # # cover subcatch with subcatch_fill # pcr.report(weight, 'weight_{:02d}.map'.format(n)) # pcr.report(subcatch, 'subcatch_{:02d}.map'.format(n)) # pcr.report(pcr.nominal(subcatch_fill), 'subcatch_fill_{:02d}.map'.format(n)) inun_lib.gdal_warp(flood_vol_map, hand_temp_file, flood_vol_temp_file, gdal_interp=gdalconst.GRA_NearestNeighbour) # , x_tile_ax, y_tile_ax, flood_meter, fill_value = inun_lib.gdal_readmap( flood_vol_temp_file, 'GTiff') # convert meter depth to volume [m3] flood_vol = pcr.numpy2pcr(pcr.Scalar, flood_meter, fill_value) * ( (x_tile_ax[1] - x_tile_ax[0]) * (y_tile_ax[0] - y_tile_ax[1]) ) # resolution of SRTM *1166400000. ## now we have some nice volume. Now we need to redistribute! inundation_pcr = inun_lib.volume_spread( drainage_pcr, hand_pcr, subcatch, flood_vol, volume_thres=0., iterations=options.iterations, area_multiplier=options.area_multiplier) # 1166400000. inundation = pcr.pcr2numpy(inundation_pcr, -9999.) # cut relevant part if y_overlap_max == 0: y_overlap_max = -inundation.shape[0] if x_overlap_max == 0: x_overlap_max = -inundation.shape[1] inundation_cut = inundation[0 + y_overlap_min:-y_overlap_max, 0 + x_overlap_min:-x_overlap_max] # inundation_cut band_inun.WriteArray(inundation_cut, x_start, y_start) band_inun.FlushCache() # clean up os.unlink(flood_vol_temp_file) os.unlink(drainage_temp_file) os.unlink(hand_temp_file) # if n == 35: # band_inun.SetNoDataValue(-9999.) # ds_inun = None # sys.exit(0) os.unlink(flood_vol_map) logger.info('Finalizing {:s}'.format(inun_file)) # add the metadata to the file and band band_inun.SetNoDataValue(-9999.) ds_inun.SetMetadata(metadata_global) band_inun.SetMetadata(metadata_var) ds_inun = None ds_hand = None ds_ldd = None # rename temporary file to final hand file if os.path.isfile(inun_file): # remove an old result if available os.unlink(inun_file) os.rename(inun_file_tmp, inun_file) logger.info('Done! Thank you for using hand_contour_inun.py') logger, ch = inun_lib.closeLogger(logger, ch) del logger, ch sys.exit(0)
def main(): ### Read input arguments ##### parser = OptionParser() usage = "usage: %prog [options]" parser = OptionParser(usage=usage) parser.add_option('-q', '--quiet', dest='verbose', default=True, action='store_false', help='do not print status messages to stdout') parser.add_option('-i', '--ini', dest='inifile', default='hand_contour_inun.ini', nargs=1, help='ini configuration file') parser.add_option('-f', '--flood_map', nargs=1, dest='flood_map', help='Flood map file (NetCDF point time series file') parser.add_option('-v', '--flood_variable', nargs=1, dest='flood_variable', default='water_level', help='variable name of flood water level') parser.add_option('-b', '--bankfull_map', dest='bankfull_map', default='', help='Map containing bank full level (is subtracted from flood map, in NetCDF)') parser.add_option('-c', '--catchment', dest='catchment_strahler', default=7, type='int', help='Strahler order threshold >= are selected as catchment boundaries') parser.add_option('-s', '--hand_strahler', dest='hand_strahler', default=7, type='int', help='Strahler order threshold >= selected as riverine') parser.add_option('-d', '--destination', dest='dest_path', default='inun', help='Destination path') (options, args) = parser.parse_args() if not os.path.exists(options.inifile): print 'path to ini file cannot be found' sys.exit(1) options.dest_path = os.path.abspath(options.dest_path) if not(os.path.isdir(options.dest_path)): os.makedirs(options.dest_path) # set up the logger flood_name = os.path.split(options.flood_map)[1].split('.')[0] case_name = 'inun_{:s}_hand_{:02d}_catch_{:02d}'.format(flood_name, options.hand_strahler, options.catchment_strahler) logfilename = os.path.join(options.dest_path, 'hand_contour_inun.log') logger, ch = inun_lib.setlogger(logfilename, 'HAND_INUN', options.verbose) logger.info('$Id: $') logger.info('Flood map: {:s}'.format(options.flood_map)) logger.info('Bank full map: {:s}'.format(options.bankfull_map)) logger.info('Destination path: {:s}'.format(options.dest_path)) # read out ini file ### READ CONFIG FILE # open config-file config = inun_lib.open_conf(options.inifile) # read settings options.dem_file = inun_lib.configget(config, 'maps', 'dem_file', True) options.ldd_file = inun_lib.configget(config, 'maps', 'ldd_file', True) options.stream_file = inun_lib.configget(config, 'maps', 'stream_file', True) options.riv_length_file = inun_lib.configget(config, 'maps', 'riv_length_file', True) options.riv_width_file = inun_lib.configget(config, 'maps', 'riv_width_file', True) options.file_format = inun_lib.configget(config, 'maps', 'file_format', 0, datatype='int') options.x_tile = inun_lib.configget(config, 'tiling', 'x_tile', 10000, datatype='int') options.y_tile = inun_lib.configget(config, 'tiling', 'y_tile', 10000, datatype='int') options.x_overlap = inun_lib.configget(config, 'tiling', 'x_overlap', 1000, datatype='int') options.y_overlap = inun_lib.configget(config, 'tiling', 'y_overlap', 1000, datatype='int') options.iterations = inun_lib.configget(config, 'inundation', 'iterations', 20, datatype='int') options.initial_level = inun_lib.configget(config, 'inundation', 'initial_level', 32., datatype='float') options.area_multiplier = inun_lib.configget(config, 'inundation', 'area_multiplier', 1., datatype='float') logger.info('DEM file: {:s}'.format(options.dem_file)) logger.info('LDD file: {:s}'.format(options.ldd_file)) logger.info('Columns per tile: {:d}'.format(options.x_tile)) logger.info('Rows per tile: {:d}'.format(options.y_tile)) logger.info('Columns overlap: {:d}'.format(options.x_overlap)) logger.info('Rows overlap: {:d}'.format(options.y_overlap)) metadata_global = {} # add metadata from the section [metadata] meta_keys = config.options('metadata_global') for key in meta_keys: metadata_global[key] = config.get('metadata_global', key) # add a number of metadata variables that are mandatory metadata_global['config_file'] = os.path.abspath(options.inifile) metadata_var = {} metadata_var['units'] = 'm' metadata_var['standard_name'] = 'water_surface_height_above_reference_datum' metadata_var['long_name'] = 'Coastal flooding' metadata_var['comment'] = 'water_surface_reference_datum_altitude is given in file {:s}'.format(options.dem_file) if not os.path.exists(options.dem_file): logger.error('path to dem file {:s} cannot be found'.format(options.dem_file)) sys.exit(1) if not os.path.exists(options.ldd_file): logger.error('path to ldd file {:s} cannot be found'.format(options.ldd_file)) sys.exit(1) # Read extent from a GDAL compatible file try: extent = inun_lib.get_gdal_extent(options.dem_file) except: msg = 'Input file {:s} not a gdal compatible file'.format(options.dem_file) inun_lib.close_with_error(logger, ch, msg) sys.exit(1) try: x, y = inun_lib.get_gdal_axes(options.dem_file, logging=logger) srs = inun_lib.get_gdal_projection(options.dem_file, logging=logger) except: msg = 'Input file {:s} not a gdal compatible file'.format(options.dem_file) inun_lib.close_with_error(logger, ch, msg) sys.exit(1) # read history from flood file if options.file_format == 0: a = nc.Dataset(options.flood_map, 'r') metadata_global['history'] = 'Created by: $Id: $, boundary conditions from {:s},\nhistory: {:s}'.format(os.path.abspath(options.flood_map), a.history) a.close() else: metadata_global['history'] = 'Created by: $Id: $, boundary conditions from {:s},\nhistory: {:s}'.format(os.path.abspath(options.flood_map), 'PCRaster file, no history') # first write subcatch maps and hand maps ############### TODO ###### # setup a HAND file dem_name = os.path.split(options.dem_file)[1].split('.')[0] hand_file = os.path.join(options.dest_path, '{:s}_hand_strahler_{:02d}.tif'.format(dem_name, options.hand_strahler)) if not(os.path.isfile(hand_file)): # hand file does not exist yet! Generate it, otherwise skip! logger.info('HAND file {:s} setting up...please wait...'.format(hand_file)) hand_file_tmp = os.path.join(options.dest_path, '{:s}_hand_strahler_{:02d}.tif.tmp'.format(dem_name, options.hand_strahler)) ds_hand = inun_lib.prepare_gdal(hand_file_tmp, x, y, logging=logger, srs=srs) band_hand = ds_hand.GetRasterBand(1) # Open terrain data for reading ds_dem, rasterband_dem = inun_lib.get_gdal_rasterband(options.dem_file) ds_ldd, rasterband_ldd = inun_lib.get_gdal_rasterband(options.ldd_file) ds_stream, rasterband_stream = inun_lib.get_gdal_rasterband(options.stream_file) n = 0 for x_loop in range(0, len(x), options.x_tile): x_start = np.maximum(x_loop, 0) x_end = np.minimum(x_loop + options.x_tile, len(x)) # determine actual overlap for cutting for y_loop in range(0, len(y), options.y_tile): x_overlap_min = x_start - np.maximum(x_start - options.x_overlap, 0) x_overlap_max = np.minimum(x_end + options.x_overlap, len(x)) - x_end n += 1 # print('tile {:001d}:'.format(n)) y_start = np.maximum(y_loop, 0) y_end = np.minimum(y_loop + options.y_tile, len(y)) y_overlap_min = y_start - np.maximum(y_start - options.y_overlap, 0) y_overlap_max = np.minimum(y_end + options.y_overlap, len(y)) - y_end # cut out DEM logger.debug('Computing HAND for xmin: {:d} xmax: {:d} ymin {:d} ymax {:d}'.format(x_start, x_end,y_start, y_end)) terrain = rasterband_dem.ReadAsArray(x_start - x_overlap_min, y_start - y_overlap_min, (x_end + x_overlap_max) - (x_start - x_overlap_min), (y_end + y_overlap_max) - (y_start - y_overlap_min) ) drainage = rasterband_ldd.ReadAsArray(x_start - x_overlap_min, y_start - y_overlap_min, (x_end + x_overlap_max) - (x_start - x_overlap_min), (y_end + y_overlap_max) - (y_start - y_overlap_min) ) stream = rasterband_stream.ReadAsArray(x_start - x_overlap_min, y_start - y_overlap_min, (x_end + x_overlap_max) - (x_start - x_overlap_min), (y_end + y_overlap_max) - (y_start - y_overlap_min) ) # write to temporary file terrain_temp_file = os.path.join(options.dest_path, 'terrain_temp.map') drainage_temp_file = os.path.join(options.dest_path, 'drainage_temp.map') stream_temp_file = os.path.join(options.dest_path, 'stream_temp.map') if rasterband_dem.GetNoDataValue() is not None: inun_lib.gdal_writemap(terrain_temp_file, 'PCRaster', np.arange(0, terrain.shape[1]), np.arange(0, terrain.shape[0]), terrain, rasterband_dem.GetNoDataValue(), gdal_type=gdal.GDT_Float32, logging=logger) else: # in case no nodata value is found logger.warning('No nodata value found in {:s}. assuming -9999'.format(options.dem_file)) inun_lib.gdal_writemap(terrain_temp_file, 'PCRaster', np.arange(0, terrain.shape[1]), np.arange(0, terrain.shape[0]), terrain, -9999., gdal_type=gdal.GDT_Float32, logging=logger) inun_lib.gdal_writemap(drainage_temp_file, 'PCRaster', np.arange(0, terrain.shape[1]), np.arange(0, terrain.shape[0]), drainage, rasterband_ldd.GetNoDataValue(), gdal_type=gdal.GDT_Int32, logging=logger) inun_lib.gdal_writemap(stream_temp_file, 'PCRaster', np.arange(0, terrain.shape[1]), np.arange(0, terrain.shape[0]), stream, rasterband_ldd.GetNoDataValue(), gdal_type=gdal.GDT_Int32, logging=logger) # read as pcr objects pcr.setclone(terrain_temp_file) terrain_pcr = pcr.readmap(terrain_temp_file) drainage_pcr = pcr.lddrepair(pcr.ldd(pcr.readmap(drainage_temp_file))) # convert to ldd type map stream_pcr = pcr.scalar(pcr.readmap(stream_temp_file)) # convert to ldd type map # compute streams stream_ge, subcatch = inun_lib.subcatch_stream(drainage_pcr, stream_pcr, options.hand_strahler) # generate streams basin = pcr.boolean(subcatch) hand_pcr, dist_pcr = inun_lib.derive_HAND(terrain_pcr, drainage_pcr, 3000, rivers=pcr.boolean(stream_ge), basin=basin) # convert to numpy hand = pcr.pcr2numpy(hand_pcr, -9999.) # cut relevant part if y_overlap_max == 0: y_overlap_max = -hand.shape[0] if x_overlap_max == 0: x_overlap_max = -hand.shape[1] hand_cut = hand[0+y_overlap_min:-y_overlap_max, 0+x_overlap_min:-x_overlap_max] band_hand.WriteArray(hand_cut, x_start, y_start) os.unlink(terrain_temp_file) os.unlink(drainage_temp_file) band_hand.FlushCache() ds_dem = None ds_ldd = None ds_stream = None band_hand.SetNoDataValue(-9999.) ds_hand = None logger.info('Finalizing {:s}'.format(hand_file)) # rename temporary file to final hand file os.rename(hand_file_tmp, hand_file) else: logger.info('HAND file {:s} already exists...skipping...'.format(hand_file)) ##################################################################################### # HAND file has now been prepared, moving to flood mapping part # ##################################################################################### # load the staticmaps needed to estimate volumes across all xax, yax, riv_length, fill_value = inun_lib.gdal_readmap(options.riv_length_file, 'GTiff') riv_length = np.ma.masked_where(riv_length==fill_value, riv_length) xax, yax, riv_width, fill_value = inun_lib.gdal_readmap(options.riv_width_file, 'GTiff') riv_width[riv_width == fill_value] = 0 x_res = np.abs((xax[-1]-xax[0])/(len(xax)-1)) y_res = np.abs((yax[-1]-yax[0])/(len(yax)-1)) flood_folder = os.path.join(options.dest_path, case_name) flood_vol_map = os.path.join(flood_folder, '{:s}_vol.tif'.format(os.path.split(options.flood_map)[1].split('.')[0])) if not(os.path.isdir(flood_folder)): os.makedirs(flood_folder) inun_file_tmp = os.path.join(flood_folder, '{:s}.tif.tmp'.format(case_name)) inun_file = os.path.join(flood_folder, '{:s}.tif'.format(case_name)) hand_temp_file = os.path.join(flood_folder, 'hand_temp.map') drainage_temp_file = os.path.join(flood_folder, 'drainage_temp.map') stream_temp_file = os.path.join(flood_folder, 'stream_temp.map') flood_vol_temp_file = os.path.join(flood_folder, 'flood_warp_temp.tif') # load the data with river levels and compute the volumes if options.file_format == 0: # assume we need the maximum value in a NetCDF time series grid a = nc.Dataset(options.flood_map, 'r') xax = a.variables['x'][:] yax = a.variables['y'][:] flood_series = a.variables[options.flood_variable][:] flood_data = flood_series.max(axis=0) if np.ma.is_masked(flood_data): flood = flood_data.data flood[flood_data.mask] = 0 if yax[-1] > yax[0]: yax = np.flipud(yax) flood = np.flipud(flood) a.close() elif options.file_format == 1: xax, yax, flood, flood_fill_value = inun_lib.gdal_readmap(options.flood_map, 'PCRaster') flood[flood==flood_fill_value] = 0. #res_x = x[1]-x[0] #res_y = y[1]-y[0] # load the bankfull depths if options.bankfull_map == '': bankfull = np.zeros(flood.shape) else: if options.file_format == 0: a = nc.Dataset(options.bankfull_map, 'r') xax = a.variables['x'][:] yax = a.variables['y'][:] bankfull = a.variables[options.flood_variable][0, :, :] if yax[-1] > yax[0]: yax = np.flipud(yax) bankfull = np.flipud(bankful) a.close() elif options.file_format == 1: xax, yax, bankfull, bankfull_fill_value = inun_lib.gdal_readmap(options.bankfull_map, 'PCRaster') # flood = bankfull*2 # res_x = 2000 # res_y = 2000 # subtract the bankfull water level to get flood levels (above bankfull) flood_vol = np.maximum(flood-bankfull, 0) flood_vol_m = riv_length*riv_width*flood_vol/(x_res * y_res) # volume expressed in meters water disc (1e6 is the surface area of one wflow grid cell) flood_vol_m_data = flood_vol_m.data flood_vol_m_data[flood_vol_m.mask] = -999. print('Saving water layer map to {:s}'.format(flood_vol_map)) # write to a tiff file inun_lib.gdal_writemap(flood_vol_map, 'GTiff', xax, yax, np.maximum(flood_vol_m_data, 0), -999.) ds_hand, rasterband_hand = inun_lib.get_gdal_rasterband(hand_file) ds_ldd, rasterband_ldd = inun_lib.get_gdal_rasterband(options.ldd_file) ds_stream, rasterband_stream = inun_lib.get_gdal_rasterband(options.stream_file) logger.info('Preparing flood map in {:s} ...please wait...'.format(inun_file)) ds_inun = inun_lib.prepare_gdal(inun_file_tmp, x, y, logging=logger, srs=srs) band_inun = ds_inun.GetRasterBand(1) # loop over all the tiles n = 0 for x_loop in range(0, len(x), options.x_tile): x_start = np.maximum(x_loop, 0) x_end = np.minimum(x_loop + options.x_tile, len(x)) # determine actual overlap for cutting for y_loop in range(0, len(y), options.y_tile): x_overlap_min = x_start - np.maximum(x_start - options.x_overlap, 0) x_overlap_max = np.minimum(x_end + options.x_overlap, len(x)) - x_end n += 1 # print('tile {:001d}:'.format(n)) y_start = np.maximum(y_loop, 0) y_end = np.minimum(y_loop + options.y_tile, len(y)) y_overlap_min = y_start - np.maximum(y_start - options.y_overlap, 0) y_overlap_max = np.minimum(y_end + options.y_overlap, len(y)) - y_end x_tile_ax = x[x_start - x_overlap_min:x_end + x_overlap_max] y_tile_ax = y[y_start - y_overlap_min:y_end + y_overlap_max] # cut out DEM logger.debug('handling xmin: {:d} xmax: {:d} ymin {:d} ymax {:d}'.format(x_start, x_end, y_start, y_end)) hand = rasterband_hand.ReadAsArray(x_start - x_overlap_min, y_start - y_overlap_min, (x_end + x_overlap_max) - (x_start - x_overlap_min), (y_end + y_overlap_max) - (y_start - y_overlap_min) ) drainage = rasterband_ldd.ReadAsArray(x_start - x_overlap_min, y_start - y_overlap_min, (x_end + x_overlap_max) - (x_start - x_overlap_min), (y_end + y_overlap_max) - (y_start - y_overlap_min) ) stream = rasterband_stream.ReadAsArray(x_start - x_overlap_min, y_start - y_overlap_min, (x_end + x_overlap_max) - (x_start - x_overlap_min), (y_end + y_overlap_max) - (y_start - y_overlap_min) ) print('len x-ax: {:d} len y-ax {:d} x-shape {:d} y-shape {:d}'.format(len(x_tile_ax), len(y_tile_ax), hand.shape[1], hand.shape[0])) inun_lib.gdal_writemap(hand_temp_file, 'PCRaster', x_tile_ax, y_tile_ax, hand, rasterband_hand.GetNoDataValue(), gdal_type=gdal.GDT_Float32, logging=logger) inun_lib.gdal_writemap(drainage_temp_file, 'PCRaster', x_tile_ax, y_tile_ax, drainage, rasterband_ldd.GetNoDataValue(), gdal_type=gdal.GDT_Int32, logging=logger) inun_lib.gdal_writemap(stream_temp_file, 'PCRaster', x_tile_ax, y_tile_ax, stream, rasterband_stream.GetNoDataValue(), gdal_type=gdal.GDT_Int32, logging=logger) # read as pcr objects pcr.setclone(hand_temp_file) hand_pcr = pcr.readmap(hand_temp_file) drainage_pcr = pcr.lddrepair(pcr.ldd(pcr.readmap(drainage_temp_file))) # convert to ldd type map stream_pcr = pcr.scalar(pcr.readmap(drainage_temp_file)) # convert to ldd type map # prepare a subcatchment map stream_ge, subcatch = inun_lib.subcatch_stream(drainage_pcr, stream_pcr, options.catchment_strahler) # generate subcatchments drainage_surf = pcr.ifthen(stream_ge > 0, pcr.accuflux(drainage_pcr, 1)) # proxy of drainage surface inaccurate at tile edges # compute weights for spreadzone (1/drainage_surf) subcatch = pcr.spreadzone(subcatch, 0, 0) # TODO check weighting scheme, perhaps not necessary # weight = 1./pcr.scalar(pcr.spreadzone(pcr.cover(pcr.ordinal(drainage_surf), 0), 0, 0)) # subcatch_fill = pcr.scalar(pcr.spreadzone(subcatch, 0, weight)) # # cover subcatch with subcatch_fill # pcr.report(weight, 'weight_{:02d}.map'.format(n)) # pcr.report(subcatch, 'subcatch_{:02d}.map'.format(n)) # pcr.report(pcr.nominal(subcatch_fill), 'subcatch_fill_{:02d}.map'.format(n)) inun_lib.gdal_warp(flood_vol_map, hand_temp_file, flood_vol_temp_file, gdal_interp=gdalconst.GRA_NearestNeighbour) # , x_tile_ax, y_tile_ax, flood_meter, fill_value = inun_lib.gdal_readmap(flood_vol_temp_file, 'GTiff') # convert meter depth to volume [m3] flood_vol = pcr.numpy2pcr(pcr.Scalar, flood_meter, fill_value)*((x_tile_ax[1] - x_tile_ax[0]) * (y_tile_ax[0] - y_tile_ax[1])) # resolution of SRTM *1166400000. ## now we have some nice volume. Now we need to redistribute! inundation_pcr = inun_lib.volume_spread(drainage_pcr, hand_pcr, subcatch, flood_vol, volume_thres=0., iterations=options.iterations, area_multiplier=options.area_multiplier) # 1166400000. inundation = pcr.pcr2numpy(inundation_pcr, -9999.) # cut relevant part if y_overlap_max == 0: y_overlap_max = -inundation.shape[0] if x_overlap_max == 0: x_overlap_max = -inundation.shape[1] inundation_cut = inundation[0+y_overlap_min:-y_overlap_max, 0+x_overlap_min:-x_overlap_max] # inundation_cut band_inun.WriteArray(inundation_cut, x_start, y_start) band_inun.FlushCache() # clean up os.unlink(flood_vol_temp_file) os.unlink(drainage_temp_file) os.unlink(hand_temp_file) # if n == 35: # band_inun.SetNoDataValue(-9999.) # ds_inun = None # sys.exit(0) os.unlink(flood_vol_map) logger.info('Finalizing {:s}'.format(inun_file)) # add the metadata to the file and band band_inun.SetNoDataValue(-9999.) ds_inun.SetMetadata(metadata_global) band_inun.SetMetadata(metadata_var) ds_inun = None ds_hand = None ds_ldd = None # rename temporary file to final hand file if os.path.isfile(inun_file): # remove an old result if available os.unlink(inun_file) os.rename(inun_file_tmp, inun_file) logger.info('Done! Thank you for using hand_contour_inun.py') logger, ch = inun_lib.closeLogger(logger, ch) del logger, ch sys.exit(0)
def subcatch_stream( ldd, threshold, min_strahler=-999, max_strahler=999, assign_edge=False, assign_existing=False, up_area=None, ): """ (From Deltares Hydrotools) Derive catchments based upon strahler threshold Input: ldd -- pcraster object direction, local drain directions threshold -- integer, strahler threshold, subcatchments ge threshold are derived min_strahler -- integer, minimum strahler threshold of river catchments to return max_strahler -- integer, maximum strahler threshold of river catchments to return assign_unique=False -- if set to True, unassigned connected areas at the edges of the domain are assigned a unique id as well. If set to False, edges are not assigned assign_existing=False == if set to True, unassigned edges are assigned to existing basins with an upstream weighting. If set to False, edges are assigned to unique IDs, or not assigned output: stream_ge -- pcraster object, streams of strahler order ge threshold subcatch -- pcraster object, subcatchments of strahler order ge threshold """ # derive stream order stream = pcr.streamorder(ldd) stream_ge = pcr.ifthen(stream >= threshold, stream) stream_up_sum = pcr.ordinal(pcr.upstream(ldd, pcr.cover(pcr.scalar(stream_ge), 0))) # detect any transfer of strahler order, to a higher strahler order. transition_strahler = pcr.ifthenelse( pcr.downstream(ldd, stream_ge) != stream_ge, pcr.boolean(1), pcr.ifthenelse( pcr.nominal(ldd) == 5, pcr.boolean(1), pcr.ifthenelse( pcr.downstream(ldd, pcr.scalar(stream_up_sum)) > pcr.scalar(stream_ge), pcr.boolean(1), pcr.boolean(0), ), ), ) # make unique ids (write to file) transition_unique = pcr.ordinal(pcr.uniqueid(transition_strahler)) # derive upstream catchment areas (write to file) subcatch = pcr.nominal(pcr.subcatchment(ldd, transition_unique)) if assign_edge: # fill unclassified areas (in pcraster equal to zero) with a unique id, above the maximum id assigned so far unique_edge = pcr.clump(pcr.ifthen(subcatch == 0, pcr.ordinal(0))) subcatch = pcr.ifthenelse( subcatch == 0, pcr.nominal(pcr.mapmaximum(pcr.scalar(subcatch)) + pcr.scalar(unique_edge)), pcr.nominal(subcatch), ) elif assign_existing: # unaccounted areas are added to largest nearest draining basin if up_area is None: up_area = pcr.ifthen( pcr.boolean(pcr.cover(stream_ge, 0)), pcr.accuflux(ldd, 1) ) riverid = pcr.ifthen(pcr.boolean(pcr.cover(stream_ge, 0)), subcatch) friction = 1.0 / pcr.scalar( pcr.spreadzone(pcr.cover(pcr.ordinal(up_area), 0), 0, 0) ) # *(pcr.scalar(ldd)*0+1) delta = pcr.ifthen( pcr.scalar(ldd) >= 0, pcr.ifthen( pcr.cover(subcatch, 0) == 0, pcr.spreadzone(pcr.cover(riverid, 0), 0, friction), ), ) subcatch = pcr.ifthenelse(pcr.boolean(pcr.cover(subcatch, 0)), subcatch, delta) # finally, only keep basins with minimum and maximum river order flowing through them strahler_subcatch = pcr.areamaximum(stream, subcatch) subcatch = pcr.ifthen( pcr.ordinal(strahler_subcatch) >= min_strahler, pcr.ifthen(pcr.ordinal(strahler_subcatch) <= max_strahler, subcatch), ) return stream_ge, pcr.ordinal(subcatch)
def main(): # output folder (and tmp folder) clean_out_folder = True if os.path.exists(out_folder): if clean_out_folder: shutil.rmtree(out_folder) os.makedirs(out_folder) else: os.makedirs(out_folder) os.chdir(out_folder) os.system("pwd") # set the clone map print("set the clone") pcr.setclone(global_ldd_30min_inp_file) # define the landmask print("define the landmask") # - based on the 30min input landmask_30min = define_landmask(input_file = global_landmask_30min_file,\ clone_map_file = global_ldd_30min_inp_file,\ output_map_file = "landmask_30min_only.map") # - based on the 05min input landmask_05min = define_landmask(input_file = global_landmask_05min_file,\ clone_map_file = global_ldd_30min_inp_file,\ output_map_file = "landmask_05min_only.map") # - based on the 06min input landmask_06min = define_landmask(input_file = global_landmask_06min_file,\ clone_map_file = global_ldd_30min_inp_file,\ output_map_file = "landmask_06min_only.map") # - based on the 30sec input landmask_30sec = define_landmask(input_file = global_landmask_30sec_file,\ clone_map_file = global_ldd_30min_inp_file,\ output_map_file = "landmask_30sec_only.map") # - based on the 30sec input landmask_03sec = define_landmask(input_file = global_landmask_03sec_file,\ clone_map_file = global_ldd_30min_inp_file,\ output_map_file = "landmask_03sec_only.map") # # - merge all landmasks landmask = pcr.cover(landmask_30min, landmask_05min, landmask_06min, landmask_30sec, landmask_03sec) pcr.report(landmask, "global_landmask_extended_30min.map") # ~ pcr.aguila(landmask) # extend ldd print("extend/define the ldd") ldd_map = pcr.readmap(global_ldd_30min_inp_file) ldd_map = pcr.ifthen(landmask, pcr.cover(ldd_map, pcr.ldd(5))) pcr.report(ldd_map, "global_ldd_extended_30min.map") # ~ pcr.aguila(ldd_map) # catchment map and size catchment_map = pcr.catchment(ldd_map, pcr.pit(ldd_map)) catchment_size = pcr.areatotal(pcr.spatial(pcr.scalar(1.0)), catchment_map) # ~ pcr.aguila(catchment_size) # identify small islands print("identify small islands") # - maps of islands smaller than 15000 cells (at half arc degree resolution) island_map = pcr.ifthen(landmask, pcr.clump(pcr.defined(ldd_map))) island_size = pcr.areatotal(pcr.spatial(pcr.scalar(1.0)), island_map) island_map = pcr.ifthen(island_size < 15000., island_map) # ~ # - use catchments (instead of islands) # ~ island_map = catchment_map # ~ island_size = catchment_size # ~ island_map = pcr.ifthen(island_size < 10000., island_map) # - sort from the largest island # -- take one cell per island as a representative island_map_rep_size = pcr.ifthen( pcr.areaorder(island_size, island_map) == 1.0, island_size) # -- sort from the largest island island_map_rep_ids = pcr.areaorder( island_map_rep_size * -1.00, pcr.ifthen(pcr.defined(island_map_rep_size), pcr.nominal(1.0))) # -- map of smaller islands, sorted from the largest one island_map = pcr.areamajority(pcr.nominal(island_map_rep_ids), island_map) # identify the biggest island for every group of small islands within a certain window (arcdeg cells) print("the biggest island for every group of small islands") large_island_map = pcr.ifthen( pcr.scalar(island_map) == pcr.windowminimum(pcr.scalar(island_map), 15.), island_map) # ~ pcr.aguila(large_island_map) # identify big catchments print("identify large catchments") catchment_map = pcr.catchment(ldd_map, pcr.pit(ldd_map)) catchment_size = pcr.areatotal(pcr.spatial(pcr.scalar(1.0)), catchment_map) # ~ # - identify all large catchments with size >= 50 cells (at the resolution of 30 arcmin) = 50 x (50^2) km2 = 125000 km2 # ~ large_catchment_map = pcr.ifthen(catchment_size >= 50, catchment_map) # ~ # - identify all large catchments with size >= 10 cells (at the resolution of 30 arcmin) # ~ large_catchment_map = pcr.ifthen(catchment_size >= 10, catchment_map) # ~ # - identify all large catchments with size >= 5 cells (at the resolution of 30 arcmin) # ~ large_catchment_map = pcr.ifthen(catchment_size >= 5, catchment_map) # ~ # - identify all large catchments with size >= 20 cells (at the resolution of 30 arcmin) # ~ large_catchment_map = pcr.ifthen(catchment_size >= 20, catchment_map) # - identify all large catchments with size >= 25 cells (at the resolution of 30 arcmin) large_catchment_map = pcr.ifthen(catchment_size >= 25, catchment_map) # - give the codes that are different than islands large_catchment_map = pcr.nominal( pcr.scalar(large_catchment_map) + 10. * vos.getMinMaxMean(pcr.scalar(large_island_map))[1]) # merge biggest islands and big catchments print("merge large catchments and islands") large_catchment_and_island_map = pcr.cover(large_catchment_map, large_island_map) # ~ large_catchment_and_island_map = pcr.cover(large_island_map, large_catchment_map) large_catchment_and_island_map_size = pcr.areatotal( pcr.spatial(pcr.scalar(1.0)), large_catchment_and_island_map) # - sort from the largest one # -- take one cell per island as a representative large_catchment_and_island_map_rep_size = pcr.ifthen( pcr.areaorder(large_catchment_and_island_map_size, large_catchment_and_island_map) == 1.0, large_catchment_and_island_map_size) # -- sort from the largest large_catchment_and_island_map_rep_ids = pcr.areaorder( large_catchment_and_island_map_rep_size * -1.00, pcr.ifthen(pcr.defined(large_catchment_and_island_map_rep_size), pcr.nominal(1.0))) # -- map of largest catchments and islands, sorted from the largest one large_catchment_and_island_map = pcr.areamajority( pcr.nominal(large_catchment_and_island_map_rep_ids), large_catchment_and_island_map) # ~ pcr.report(large_catchment_and_island_map, "large_catchments_and_islands.map") # ~ # perform cdo fillmiss2 in order to merge the small catchments to the nearest large catchments # ~ print("spatial interpolation/extrapolation using cdo fillmiss2 to get initial subdomains") # ~ cmd = "gdal_translate -of NETCDF large_catchments_and_islands.map large_catchments_and_islands.nc" # ~ print(cmd); os.system(cmd) # ~ cmd = "cdo fillmiss2 large_catchments_and_islands.nc large_catchments_and_islands_filled.nc" # ~ print(cmd); os.system(cmd) # ~ cmd = "gdal_translate -of PCRaster large_catchments_and_islands_filled.nc large_catchments_and_islands_filled.map" # ~ print(cmd); os.system(cmd) # ~ cmd = "mapattr -c " + global_ldd_30min_inp_file + " " + "large_catchments_and_islands_filled.map" # ~ print(cmd); os.system(cmd) # ~ # - initial subdomains # ~ subdomains_initial = pcr.nominal(pcr.readmap("large_catchments_and_islands_filled.map")) # ~ subdomains_initial = pcr.areamajority(subdomains_initial, catchment_map) # ~ pcr.aguila(subdomains_initial) # spatial interpolation/extrapolation in order to merge the small catchments to the nearest large catchments print("spatial interpolation/extrapolation to get initial subdomains") field = large_catchment_and_island_map cellID = pcr.nominal(pcr.uniqueid(pcr.defined(field))) zoneID = pcr.spreadzone(cellID, 0, 1) field = pcr.areamajority(field, zoneID) subdomains_initial = field subdomains_initial = pcr.areamajority(subdomains_initial, catchment_map) pcr.aguila(subdomains_initial) pcr.report(subdomains_initial, "global_subdomains_30min_initial.map") print(str(int(vos.getMinMaxMean(pcr.scalar(subdomains_initial))[0]))) print(str(int(vos.getMinMaxMean(pcr.scalar(subdomains_initial))[1]))) # ~ print(str(int(vos.getMinMaxMean(pcr.scalar(subdomains_initial_clump))[0]))) # ~ print(str(int(vos.getMinMaxMean(pcr.scalar(subdomains_initial_clump))[1]))) print("Checking all subdomains, avoid too large subdomains") num_of_masks = int(vos.getMinMaxMean(pcr.scalar(subdomains_initial))[1]) # clone code that will be assigned assigned_number = 0 subdomains_final = pcr.ifthen( pcr.scalar(subdomains_initial) < -7777, pcr.nominal(0)) for nr in range(1, num_of_masks + 1, 1): msg = "Processing the landmask %s" % (str(nr)) print(msg) mask_selected_boolean = pcr.ifthen(subdomains_initial == nr, pcr.boolean(1.0)) # ~ if nr == 1: pcr.aguila(mask_selected_boolean) xmin, ymin, xmax, ymax = boundingBox(mask_selected_boolean) area_in_degree2 = (xmax - xmin) * (ymax - ymin) # ~ print(str(area_in_degree2)) # check whether the size of bounding box is ok # - initial check value check_ok = True reference_area_in_degree2 = 2500. if area_in_degree2 > 1.50 * reference_area_in_degree2: check_ok = False if (xmax - xmin) > 10 * (ymax - ymin): check_ok = False if check_ok == True: msg = "Clump is not needed." msg = "\n\n" + str(msg) + "\n\n" print(msg) # assign the clone code assigned_number = assigned_number + 1 # update global landmask for river and land mask_selected_nominal = pcr.ifthen(mask_selected_boolean, pcr.nominal(assigned_number)) subdomains_final = pcr.cover(subdomains_final, mask_selected_nominal) if check_ok == False: msg = "Clump is needed." msg = "\n\n" + str(msg) + "\n\n" print(msg) # make clump clump_ids = pcr.nominal(pcr.clump(mask_selected_boolean)) # merge clumps that are close together clump_ids_window_majority = pcr.windowmajority(clump_ids, 10.0) clump_ids = pcr.areamajority(clump_ids_window_majority, clump_ids) # ~ pcr.aguila(clump_ids) # minimimum and maximum values min_clump_id = int( pcr.cellvalue(pcr.mapminimum(pcr.scalar(clump_ids)), 1)[0]) max_clump_id = int( pcr.cellvalue(pcr.mapmaximum(pcr.scalar(clump_ids)), 1)[0]) for clump_id in range(min_clump_id, max_clump_id + 1, 1): msg = "Processing the clump %s of %s from the landmask %s" % ( str(clump_id), str(max_clump_id), str(nr)) msg = "\n\n" + str(msg) + "\n\n" print(msg) # identify mask based on the clump mask_selected_boolean_from_clump = pcr.ifthen( clump_ids == pcr.nominal(clump_id), mask_selected_boolean) mask_selected_boolean_from_clump = pcr.ifthen( mask_selected_boolean_from_clump, mask_selected_boolean_from_clump) # check whether the clump is empty check_mask_selected_boolean_from_clump = pcr.ifthen( mask_selected_boolean, mask_selected_boolean_from_clump) check_if_empty = float( pcr.cellvalue( pcr.mapmaximum( pcr.scalar( pcr.defined( check_mask_selected_boolean_from_clump))), 1)[0]) if check_if_empty == 0.0: msg = "Map is empty !" msg = "\n\n" + str(msg) + "\n\n" print(msg) else: msg = "Map is NOT empty !" msg = "\n\n" + str(msg) + "\n\n" print(msg) # assign the clone code assigned_number = assigned_number + 1 # update global landmask for river and land mask_selected_nominal = pcr.ifthen( mask_selected_boolean_from_clump, pcr.nominal(assigned_number)) subdomains_final = pcr.cover(subdomains_final, mask_selected_nominal) # ~ # kill all aguila processes if exist # ~ os.system('killall aguila') pcr.aguila(subdomains_final) print("") print("") print("") print("The subdomain map is READY.") pcr.report(subdomains_final, "global_subdomains_30min_final.map") num_of_masks = int(vos.getMinMaxMean(pcr.scalar(subdomains_final))[1]) print(num_of_masks) print("") print("") print("") for nr in range(1, num_of_masks + 1, 1): mask_selected_boolean = pcr.ifthen(subdomains_final == nr, pcr.boolean(1.0)) xmin, ymin, xmax, ymax = boundingBox(mask_selected_boolean) area_in_degree2 = (xmax - xmin) * (ymax - ymin) print( str(nr) + " ; " + str(area_in_degree2) + " ; " + str((xmax - xmin)) + " ; " + str((ymax - ymin))) print("") print("") print("") print("Number of subdomains: " + str(num_of_masks)) print("") print("") print("") # spatial extrapolation in order to cover the entire map print("spatial interpolation/extrapolation to cover the entire map") field = subdomains_final cellID = pcr.nominal(pcr.uniqueid(pcr.defined(field))) zoneID = pcr.spreadzone(cellID, 0, 1) field = pcr.areamajority(field, zoneID) subdomains_final_filled = field pcr.aguila(subdomains_final_filled) pcr.report(subdomains_final_filled, "global_subdomains_30min_final_filled.map")