def __init__(self, iniItems, landmask, Dir, cloneMap, tmpDir): object.__init__(self) # clone map file names, temporary directory and global/absolute path of input directory self.cloneMap = cloneMap #iniItems.cloneMap self.tmpDir = tmpDir #iniItems.tmpDir self.inputDir = Dir #iniItems.globalOptions['inputDir'] self.landmask = landmask # local drainage direction: self.lddMap = vos.readPCRmapClone( iniItems.get("routingOptions", "lddMap"), self.cloneMap, self.tmpDir, self.inputDir, True) self.lddMap = pcr.lddrepair(pcr.ldd(self.lddMap)) self.lddMap = pcr.lddrepair(self.lddMap) # option to activate water balance check self.debugWaterBalance = True if configget(iniItems, "routingOptions", "debugWaterBalance", "True") == "False": self.debugWaterBalance = False # option to perform a run with only natural lakes (without reservoirs) self.onlyNaturalWaterBodies = False if "onlyNaturalWaterBodies" in iniItems._sections[ 'routingOptions'] and configget(iniItems, "routingOptions", "onlyNaturalWaterBodies", "False") == "True": logger.info( "Using only natural water bodies identified in the year 1900. All reservoirs in 1900 are assumed as lakes." ) self.onlyNaturalWaterBodies = True self.dateForNaturalCondition = "1900-01-01" # The run for a natural condition should access only this date. # names of files containing water bodies parameters if configget(iniItems, "routingOptions", "waterBodyInputNC", "None") == str(None): self.useNetCDF = False self.fracWaterInp = iniItems.get("routingOptions", "fracWaterInp") self.waterBodyIdsInp = iniItems.get("routingOptions", "waterBodyIds") self.waterBodyTypInp = iniItems.get("routingOptions", "waterBodyTyp") self.resMaxCapInp = iniItems.get("routingOptions", "resMaxCapInp") self.resSfAreaInp = iniItems.get("routingOptions", "resSfAreaInp") else: self.useNetCDF = True self.ncFileInp = vos.getFullPath(\ iniItems.get("routingOptions","waterBodyInputNC"),\ self.inputDir) # minimum width (m) used in the weir formula # TODO: define minWeirWidth based on the GLWD, GRanD database and/or bankfull discharge formula self.minWeirWidth = 10. # lower and upper limits at which reservoir release is terminated and # at which reservoir release is equal to long-term average outflow self.minResvrFrac = 0.10 self.maxResvrFrac = 0.75
def __init__(self, configuration, currTimeStep, initialState = None): self._configuration = configuration self._modelTime = currTimeStep pcr.setclone(configuration.cloneMap) # Read the ldd map. self.lddMap = vos.readPCRmapClone(\ configuration.routingOptions['lddMap'], configuration.cloneMap,configuration.tmpDir,configuration.globalOptions['inputDir'],True) #ensure ldd map is correct, and actually of type "ldd" self.lddMap = pcr.lddrepair(pcr.ldd(self.lddMap)) if configuration.globalOptions['landmask'] != "None": self.landmask = vos.readPCRmapClone(\ configuration.globalOptions['landmask'], configuration.cloneMap,configuration.tmpDir,configuration.globalOptions['inputDir']) else: self.landmask = pcr.defined(self.lddMap) # ADDED: variables necessary for 2-way coupling functions # ---------------------------------------------------------------------------------------------------------------- # variable to control activation of 2-way coupling functions (can be changed through BMI) self.ActivateCoupling = self._configuration.globalOptions['ActivateCoupling'] # ---------------------------------------------------------------------------------------------------------------- # defining catchment areas self.catchment_class = 1.0 # number of upperSoilLayers: self.numberOfSoilLayers = int(configuration.landSurfaceOptions['numberOfUpperSoilLayers']) self.createSubmodels(initialState)
def __init__(self, configuration, currTimeStep, initialState = None): self._configuration = configuration self._modelTime = currTimeStep pcr.setclone(configuration.cloneMap) # Read the ldd map. self.lddMap = vos.readPCRmapClone(\ configuration.routingOptions['lddMap'], configuration.cloneMap,configuration.tmpDir,configuration.globalOptions['inputDir'],True) #ensure ldd map is correct, and actually of type "ldd" self.lddMap = pcr.lddrepair(pcr.ldd(self.lddMap)) if configuration.globalOptions['landmask'] != "None": self.landmask = vos.readPCRmapClone(\ configuration.globalOptions['landmask'], configuration.cloneMap,configuration.tmpDir,configuration.globalOptions['inputDir']) else: self.landmask = pcr.defined(self.lddMap) # defining catchment areas self.catchment_class = 1.0 # number of upperSoilLayers: self.numberOfSoilLayers = int(configuration.landSurfaceOptions['numberOfUpperSoilLayers']) self.createSubmodels(initialState)
def initial(self): """ initial part of the evapo water module """ # ************************************************************ # ***** EVAPORATION # ************************************************************ self.var.EvaCumM3 = MaskInfo.instance().in_zero() # water use cumulated amount # water use substep amount settings = LisSettings.instance() option = settings.options binding = settings.binding maskinfo = MaskInfo.instance() if option['openwaterevapo']: LakeMask = loadmap('LakeMask', pcr=True) lmask = ifthenelse(LakeMask != 0, self.var.LddStructuresKinematic, 5) LddEva = lddrepair(lmask) lddC = compressArray(LddEva) inAr = decompress(np.arange(maskinfo.info.mapC[0], dtype="int32")) self.var.downEva = (compressArray(downstream( LddEva, inAr))).astype("int32") # each upstream pixel gets the id of the downstream pixel self.var.downEva[lddC == 5] = maskinfo.info.mapC[0] self.var.maxNoEva = int(loadmap('maxNoEva')) # all pits gets a high number # still to test if this works # ldd only inside lakes for calculating evaporation if option['varfractionwater']: self.var.diffmaxwater = loadmap( 'FracMaxWater') - self.var.WaterFraction # Fraction of maximum extend of water - fraction of water in lakes and rivers varWNo = [ 1, 32, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 370 ] self.var.varW = [] # variable fraction of water self.var.varW1 = [] self.var.varW1.append(12) j = 0 for i in range(1, 367): if i >= varWNo[j + 1]: j += 1 self.var.varW1.append(j) for i in range(12): varWName = generateName(binding['WFractionMaps'], varWNo[i]) self.var.varW.append( loadLAI(binding['WFractionMaps'], varWName, i))
def initial(self): """ initial part of the structures module """ self.var.LddStructuresKinematic = self.var.LddKinematic settings = LisSettings.instance() option = settings.options if not option['InitLisflood']: # not done in Init Lisflood IsUpsOfStructureKinematic = downstream( self.var.LddKinematic, cover(boolean(decompress(self.var.IsStructureKinematic)), boolean(0)) ) # Get all pixels just upstream of kinematic structure locations self.var.IsUpsOfStructureKinematicC = compressArray(IsUpsOfStructureKinematic) # Unmodified version of LddKinematic is needed to connect inflow and outflow points # of each structure (called LddStructuresKinematic now) self.var.LddKinematic = lddrepair(ifthenelse(IsUpsOfStructureKinematic, 5, self.var.LddKinematic))
def __init__(self, configuration, currTimeStep, initialState=None): self._configuration = configuration self._modelTime = currTimeStep pcr.setclone(configuration.cloneMap) # Read the ldd map. self.lddMap = vos.readPCRmapClone(\ configuration.routingOptions['lddMap'], configuration.cloneMap,configuration.tmpDir,configuration.globalOptions['inputDir'],True) #ensure ldd map is correct, and actually of type "ldd" self.lddMap = pcr.lddrepair(pcr.ldd(self.lddMap)) if configuration.globalOptions['landmask'] != "None": self.landmask = vos.readPCRmapClone(\ configuration.globalOptions['landmask'], configuration.cloneMap,configuration.tmpDir,configuration.globalOptions['inputDir']) else: self.landmask = pcr.defined(self.lddMap) # defining catchment areas self.catchment_class = 1.0 # number of upperSoilLayers: self.numberOfSoilLayers = int( configuration.landSurfaceOptions['numberOfUpperSoilLayers']) # preparing sub-modules self.createSubmodels(initialState) # option for debugging to PCR-GLOBWB version 1.0 self.debug_to_version_one = False if configuration.debug_to_version_one: self.debug_to_version_one = True if self.debug_to_version_one: # preparing initial folder directory self.directory_for_initial_maps = vos.getFullPath( "initials/", self.configuration.mapsDir) if os.path.exists(self.directory_for_initial_maps): shutil.rmtree(self.directory_for_initial_maps) os.makedirs(self.directory_for_initial_maps) # dump the initial state self.dumpState(self.directory_for_initial_maps, "initial")
def pcr_preprocess(dem_in, x, y, itile, tempdir, ldd_in=None, test=False, create_ldd=True): """ function to set pcr clone and translate DEM (terrain) and ldd numpy 2d arrays to pcr maps :param terrain: masked numpy 2d array with elevation data :param x: numpy 1d array with x coordinates of elevation grid :param y: numpy 1d array with Y coordinates of elevation grid :param tempdir: string with directory to temporary save clone pcrmap :param ldd: numpy 2d array with ldd grid, make sure it uses the pcrmap definition of ldd :param test: if True do not remove clone maps :return: pcr maps for dem and ldd """ # create clone in temp_dir fn_clone = os.path.join(tempdir, '_{:03d}_dem.map'.format(itile)) cl.makeDir(tempdir) # make dir if not exist # DEM gdal_writemap(fn_clone, 'PCRaster', x, y, dem_in, -9999) # note: missing value needs conversion in python item pcr.setclone(fn_clone) pcr.setglobaloption("unitcell") dem = pcr.readmap(fn_clone) # cleanup if not test: os.unlink(fn_clone) # cleanup clone file os.unlink(fn_clone+'.aux.xml') # LDD if create_ldd: if ldd_in is None: print('Calculating LDD') ldd = pcr.lddcreate(dem, 1E31, 1E31, 1E31, 1E31) else: # TODO note that np.nan is default NoDataValue for ldd file. check this when reading data # TODO: x and y axis got mixed up when translating with numpy2pcr. check if it works here! # in process_tile function in coastal_inun.py ldd = pcr.lddrepair(pcr.ldd(pcr.numpy2pcr(pcr.Ldd, ldd_in, np.nan))) else: ldd = None return dem, ldd
def __init__(self, configuration, currTimeStep): self._configuration = configuration self._modelTime = currTimeStep pcr.setclone(configuration.cloneMap) # read the ldd map self.lddMap = vos.netcdf2PCRobjCloneWithoutTime(configuration.modflowParameterOptions['channelNC'],'lddMap',\ configuration.cloneMap) # ensure ldd map is correct, and actually of type "ldd" self.lddMap = pcr.lddrepair(pcr.ldd(self.lddMap)) # defining the landmask map if configuration.globalOptions['landmask'] != "None": self.landmask = vos.readPCRmapClone(\ configuration.globalOptions['landmask'], configuration.cloneMap,configuration.tmpDir,configuration.globalOptions['inputDir']) else: self.landmask = pcr.defined(self.lddMap) # preparing the sub-model(s) - Currently, there is only one sub-model. self.createSubmodels()
def __init__(self, iniItems, landmask): object.__init__(self) # cloneMap, temporary directory for the resample process, temporary directory for the modflow process, absolute path for input directory, landmask self.cloneMap = iniItems.cloneMap self.tmpDir = iniItems.tmpDir self.tmp_modflow_dir = iniItems.tmp_modflow_dir self.inputDir = iniItems.globalOptions['inputDir'] self.landmask = landmask # configuration from the ini file self.iniItems = iniItems # topography properties: read several variables from the netcdf file for var in ['dem_minimum','dem_maximum','dem_average','dem_standard_deviation',\ 'slopeLength','orographyBeta','tanslope',\ 'dzRel0000','dzRel0001','dzRel0005',\ 'dzRel0010','dzRel0020','dzRel0030','dzRel0040','dzRel0050',\ 'dzRel0060','dzRel0070','dzRel0080','dzRel0090','dzRel0100']: vars(self)[var] = vos.netcdf2PCRobjCloneWithoutTime(self.iniItems.modflowParameterOptions['topographyNC'], \ var, self.cloneMap) vars(self)[var] = pcr.cover(vars(self)[var], 0.0) # channel properties: read several variables from the netcdf file for var in ['lddMap','cellAreaMap','gradient','bankfull_width', 'bankfull_depth','dem_floodplain','dem_riverbed']: vars(self)[var] = vos.netcdf2PCRobjCloneWithoutTime(self.iniItems.modflowParameterOptions['channelNC'], \ var, self.cloneMap) vars(self)[var] = pcr.cover(vars(self)[var], 0.0) # minimum channel width minimum_channel_width = 0.5 # TODO: Define this one in the configuration file self.bankfull_width = pcr.max(minimum_channel_width, self.bankfull_width) #~ # cell fraction if channel water reaching the flood plan # NOT USED YET #~ self.flood_plain_fraction = self.return_innundation_fraction(pcr.max(0.0, self.dem_floodplain - self.dem_minimum)) # coefficient of Manning self.manningsN = vos.readPCRmapClone(self.iniItems.modflowParameterOptions['manningsN'],\ self.cloneMap,self.tmpDir,self.inputDir) # minimum channel gradient minGradient = 0.00005 # TODO: Define this one in the configuration file self.gradient = pcr.max(minGradient, pcr.cover(self.gradient, minGradient)) # correcting lddMap self.lddMap = pcr.ifthen(pcr.scalar(self.lddMap) > 0.0, self.lddMap) self.lddMap = pcr.lddrepair(pcr.ldd(self.lddMap)) # channelLength = approximation of channel length (unit: m) # This is approximated by cell diagonal. cellSizeInArcMin = np.round(pcr.clone().cellSize()*60.) # FIXME: This one will not work if you use the resolution: 0.5, 1.5, 2.5 arc-min verticalSizeInMeter = cellSizeInArcMin*1852. horizontalSizeInMeter = self.cellAreaMap/verticalSizeInMeter self.channelLength = ((horizontalSizeInMeter)**(2)+\ (verticalSizeInMeter)**(2))**(0.5) # option for lakes and reservoir self.onlyNaturalWaterBodies = False if self.iniItems.modflowParameterOptions['onlyNaturalWaterBodies'] == "True": self.onlyNaturalWaterBodies = True # groundwater linear recession coefficient (day-1) ; the linear reservoir concept is still being used to represent fast response flow # particularly from karstic aquifer in mountainous regions self.recessionCoeff = vos.netcdf2PCRobjCloneWithoutTime(self.iniItems.modflowParameterOptions['groundwaterPropertiesNC'],\ 'recessionCoeff', self.cloneMap) self.recessionCoeff = pcr.cover(self.recessionCoeff,0.00) self.recessionCoeff = pcr.min(1.0000,self.recessionCoeff) # if 'minRecessionCoeff' in iniItems.modflowParameterOptions.keys(): minRecessionCoeff = float(iniItems.modflowParameterOptions['minRecessionCoeff']) else: minRecessionCoeff = 1.0e-4 # This is the minimum value used in Van Beek et al. (2011). self.recessionCoeff = pcr.max(minRecessionCoeff,self.recessionCoeff) # aquifer saturated conductivity (m/day) self.kSatAquifer = vos.netcdf2PCRobjCloneWithoutTime(self.iniItems.modflowParameterOptions['groundwaterPropertiesNC'],\ 'kSatAquifer', self.cloneMap) self.kSatAquifer = pcr.cover(self.kSatAquifer,pcr.mapmaximum(self.kSatAquifer)) self.kSatAquifer = pcr.max(0.001,self.kSatAquifer) # TODO: Define the minimum value as part of the configuration file # aquifer specific yield (dimensionless) self.specificYield = vos.netcdf2PCRobjCloneWithoutTime(self.iniItems.modflowParameterOptions['groundwaterPropertiesNC'],\ 'specificYield', self.cloneMap) self.specificYield = pcr.cover(self.specificYield,pcr.mapmaximum(self.specificYield)) self.specificYield = pcr.max(0.010,self.specificYield) # TODO: TO BE CHECKED: The resample process of specificYield self.specificYield = pcr.min(1.000,self.specificYield) # TODO: Define the minimum value as part of the configuration file # estimate of thickness (unit: m) of accesible groundwater totalGroundwaterThickness = vos.netcdf2PCRobjCloneWithoutTime(self.iniItems.modflowParameterOptions['estimateOfTotalGroundwaterThicknessNC'],\ 'thickness', self.cloneMap) # extrapolation totalGroundwaterThickness = pcr.cover(totalGroundwaterThickness,\ pcr.windowaverage(totalGroundwaterThickness, 1.0)) totalGroundwaterThickness = pcr.cover(totalGroundwaterThickness,\ pcr.windowaverage(totalGroundwaterThickness, 1.5)) totalGroundwaterThickness = pcr.cover(totalGroundwaterThickness, 0.0) # # set minimum thickness minimumThickness = pcr.scalar(float(\ self.iniItems.modflowParameterOptions['minimumTotalGroundwaterThickness'])) totalGroundwaterThickness = pcr.max(minimumThickness, totalGroundwaterThickness) # # set maximum thickness: 250 m. # TODO: Define this one as part of the ini file maximumThickness = 250. self.totalGroundwaterThickness = pcr.min(maximumThickness, totalGroundwaterThickness) # TODO: Define the maximum value as part of the configuration file # surface water bed thickness (unit: m) bed_thickness = 0.1 # TODO: Define this as part of the configuration file # surface water bed resistance (unit: day) bed_resistance = bed_thickness / (self.kSatAquifer) minimum_bed_resistance = 1.0 # TODO: Define this as part of the configuration file self.bed_resistance = pcr.max(minimum_bed_resistance,\ bed_resistance,) # option to ignore capillary rise self.ignoreCapRise = True if self.iniItems.modflowParameterOptions['ignoreCapRise'] == "False": self.ignoreCapRise = False # a variable to indicate if the modflow has been called or not self.modflow_has_been_called = False # list of the convergence criteria for HCLOSE (unit: m) # - Deltares default's value is 0.001 m # check this value with Jarno self.criteria_HCLOSE = [0.001, 0.005, 0.01, 0.02, 0.05, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0] self.criteria_HCLOSE = sorted(self.criteria_HCLOSE) # list of the convergence criteria for RCLOSE (unit: m3) # - Deltares default's value for their 25 and 250 m resolution models is 10 m3 # check this value with Jarno cell_area_assumption = verticalSizeInMeter * float(pcr.cellvalue(pcr.mapmaximum(horizontalSizeInMeter),1)[0]) self.criteria_RCLOSE = [10., 10.* cell_area_assumption/(250.*250.), 10.* cell_area_assumption/(25.*25.)] self.criteria_RCLOSE = sorted(self.criteria_RCLOSE) # initiate the index for HCLOSE and RCLOSE self.iteration_HCLOSE = 0 self.iteration_RCLOSE = 0 # initiate old style reporting # TODO: remove this! self.initiate_old_style_groundwater_reporting(iniItems)
def __init__(self, iniItems, landmask, onlyNaturalWaterBodies=False, lddMap=None): object.__init__(self) # clone map file names, temporary directory and global/absolute path of input directory self.cloneMap = iniItems.cloneMap self.tmpDir = iniItems.tmpDir self.inputDir = iniItems.globalOptions['inputDir'] self.landmask = landmask self.iniItems = iniItems # local drainage direction: if lddMap is None: self.lddMap = vos.readPCRmapClone( iniItems.routingOptions['lddMap'], self.cloneMap, self.tmpDir, self.inputDir, True) self.lddMap = pcr.lddrepair(pcr.ldd(self.lddMap)) self.lddMap = pcr.lddrepair(self.lddMap) else: self.lddMap = lddMap # the following is needed for a modflowOfflineCoupling run if 'modflowOfflineCoupling' in list(iniItems.globalOptions.keys( )) and iniItems.globalOptions[ 'modflowOfflineCoupling'] == "True" and 'routingOptions' not in iniItems.allSections: logger.info( "The 'routingOptions' are not defined in the configuration ini file. We will adopt them from the 'modflowParameterOptions'." ) iniItems.routingOptions = iniItems.modflowParameterOptions # option to activate water balance check self.debugWaterBalance = True if 'debugWaterBalance' in list(iniItems.routingOptions.keys( )) and iniItems.routingOptions['debugWaterBalance'] == "False": self.debugWaterBalance = False # option to perform a run with only natural lakes (without reservoirs) self.onlyNaturalWaterBodies = onlyNaturalWaterBodies if "onlyNaturalWaterBodies" in list(iniItems.routingOptions.keys( )) and iniItems.routingOptions['onlyNaturalWaterBodies'] == "True": logger.info( "Using only natural water bodies identified in the year 1900. All reservoirs in 1900 are assumed as lakes." ) self.onlyNaturalWaterBodies = True self.dateForNaturalCondition = "1900-01-01" # The run for a natural condition should access only this date. # names of files containing water bodies parameters if iniItems.routingOptions['waterBodyInputNC'] == str(None): self.useNetCDF = False self.fracWaterInp = iniItems.routingOptions['fracWaterInp'] self.waterBodyIdsInp = iniItems.routingOptions['waterBodyIds'] self.waterBodyTypInp = iniItems.routingOptions['waterBodyTyp'] self.resMaxCapInp = iniItems.routingOptions['resMaxCapInp'] self.resSfAreaInp = iniItems.routingOptions['resSfAreaInp'] else: self.useNetCDF = True self.ncFileInp = vos.getFullPath(\ iniItems.routingOptions['waterBodyInputNC'],\ self.inputDir) # minimum width (m) used in the weir formula # TODO: define minWeirWidth based on the GLWD, GRanD database and/or bankfull discharge formula self.minWeirWidth = 10. # lower and upper limits at which reservoir release is terminated and # at which reservoir release is equal to long-term average outflow # - default values self.minResvrFrac = 0.10 self.maxResvrFrac = 0.75 # - from the ini file if "minResvrFrac" in list(iniItems.routingOptions.keys()): minResvrFrac = iniItems.routingOptions['minResvrFrac'] self.minResvrFrac = vos.readPCRmapClone(minResvrFrac, self.cloneMap, self.tmpDir, self.inputDir) if "maxResvrFrac" in list(iniItems.routingOptions.keys()): maxResvrFrac = iniItems.routingOptions['maxResvrFrac'] self.maxResvrFrac = vos.readPCRmapClone(maxResvrFrac, self.cloneMap, self.tmpDir, self.inputDir)
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 __init__(self, iniItems, landmask): object.__init__(self) # cloneMap, temporary directory, absolute path for input directory, landmask self.cloneMap = iniItems.cloneMap self.tmpDir = iniItems.tmpDir self.inputDir = iniItems.globalOptions['inputDir'] self.landmask = landmask # configuration from the ini file self.iniItems = iniItems # topography properties: read several variables from the netcdf file for var in ['dem_minimum','dem_maximum','dem_average','dem_standard_deviation',\ 'slopeLength','orographyBeta','tanslope',\ 'dzRel0000','dzRel0001','dzRel0005',\ 'dzRel0010','dzRel0020','dzRel0030','dzRel0040','dzRel0050',\ 'dzRel0060','dzRel0070','dzRel0080','dzRel0090','dzRel0100']: vars(self)[var] = vos.netcdf2PCRobjCloneWithoutTime(self.iniItems.modflowParameterOptions['topographyNC'], \ var, self.cloneMap) vars(self)[var] = pcr.cover(vars(self)[var], 0.0) # channel properties: read several variables from the netcdf file for var in [ 'lddMap', 'cellAreaMap', 'gradient', 'bankfull_width', 'bankfull_depth', 'dem_floodplain', 'dem_riverbed' ]: vars(self)[var] = vos.netcdf2PCRobjCloneWithoutTime(self.iniItems.modflowParameterOptions['channelNC'], \ var, self.cloneMap) vars(self)[var] = pcr.cover(vars(self)[var], 0.0) # minimum channel width minimum_channel_width = 0.1 self.bankfull_width = pcr.max(minimum_channel_width, self.bankfull_width) #~ # cell fraction if channel water reaching the flood plan # NOT USED #~ self.flood_plain_fraction = self.return_innundation_fraction(pcr.max(0.0, self.dem_floodplain - self.dem_minimum)) # coefficient of Manning self.manningsN = vos.readPCRmapClone(self.iniItems.modflowParameterOptions['manningsN'],\ self.cloneMap,self.tmpDir,self.inputDir) # minimum channel gradient minGradient = 0.00005 self.gradient = pcr.max(minGradient, pcr.cover(self.gradient, minGradient)) # correcting lddMap self.lddMap = pcr.ifthen(pcr.scalar(self.lddMap) > 0.0, self.lddMap) self.lddMap = pcr.lddrepair(pcr.ldd(self.lddMap)) # channelLength = approximation of channel length (unit: m) # This is approximated by cell diagonal. cellSizeInArcMin = np.round(pcr.clone().cellSize() * 60.) verticalSizeInMeter = cellSizeInArcMin * 1852. self.channelLength = ((self.cellAreaMap/verticalSizeInMeter)**(2)+\ (verticalSizeInMeter)**(2))**(0.5) # option for lakes and reservoir self.onlyNaturalWaterBodies = False if self.iniItems.modflowParameterOptions[ 'onlyNaturalWaterBodies'] == "True": self.onlyNaturalWaterBodies = True # groundwater linear recession coefficient (day-1) ; the linear reservoir concept is still being used to represent fast response flow # particularly from karstic aquifer in mountainous regions self.recessionCoeff = vos.netcdf2PCRobjCloneWithoutTime(self.iniItems.modflowParameterOptions['groundwaterPropertiesNC'],\ 'recessionCoeff', self.cloneMap) self.recessionCoeff = pcr.cover(self.recessionCoeff, 0.00) self.recessionCoeff = pcr.min(1.0000, self.recessionCoeff) # if 'minRecessionCoeff' in iniItems.modflowParameterOptions.keys(): minRecessionCoeff = float( iniItems.modflowParameterOptions['minRecessionCoeff']) else: minRecessionCoeff = 1.0e-4 # This is the minimum value used in Van Beek et al. (2011). self.recessionCoeff = pcr.max(minRecessionCoeff, self.recessionCoeff) # aquifer saturated conductivity (m/day) self.kSatAquifer = vos.netcdf2PCRobjCloneWithoutTime(self.iniItems.modflowParameterOptions['groundwaterPropertiesNC'],\ 'kSatAquifer', self.cloneMap) self.kSatAquifer = pcr.cover(self.kSatAquifer, pcr.mapmaximum(self.kSatAquifer)) self.kSatAquifer = pcr.max(0.010, self.kSatAquifer) self.kSatAquifer *= 0.001 # aquifer specific yield (dimensionless) self.specificYield = vos.netcdf2PCRobjCloneWithoutTime(self.iniItems.modflowParameterOptions['groundwaterPropertiesNC'],\ 'specificYield', self.cloneMap) self.specificYield = pcr.cover(self.specificYield, pcr.mapmaximum(self.specificYield)) self.specificYield = pcr.max( 0.010, self.specificYield ) # TODO: TO BE CHECKED: The resample process of specificYield self.specificYield = pcr.min(1.000, self.specificYield) # estimate of thickness (unit: m) of accesible groundwater totalGroundwaterThickness = vos.netcdf2PCRobjCloneWithoutTime(self.iniItems.modflowParameterOptions['estimateOfTotalGroundwaterThicknessNC'],\ 'thickness', self.cloneMap) # extrapolation totalGroundwaterThickness = pcr.cover(totalGroundwaterThickness,\ pcr.windowaverage(totalGroundwaterThickness, 1.0)) totalGroundwaterThickness = pcr.cover(totalGroundwaterThickness,\ pcr.windowaverage(totalGroundwaterThickness, 1.5)) totalGroundwaterThickness = pcr.cover(totalGroundwaterThickness, 0.0) # # set minimum thickness minimumThickness = pcr.scalar(float(\ self.iniItems.modflowParameterOptions['minimumTotalGroundwaterThickness'])) totalGroundwaterThickness = pcr.max(minimumThickness, totalGroundwaterThickness) # # set maximum thickness: 250 m. maximumThickness = 250. self.totalGroundwaterThickness = pcr.min(maximumThickness, totalGroundwaterThickness) # river bed resistance (unit: day) self.bed_resistance = 1.0 # option to ignore capillary rise self.ignoreCapRise = True if self.iniItems.modflowParameterOptions['ignoreCapRise'] == "False": self.ignoreCapRise = False # initiate old style reporting # TODO: remove this! self.initiate_old_style_groundwater_reporting(iniItems)
def subcatch_order_b( ldd, oorder, sizelimit=0, fill=False, fillcomplete=False, stoporder=0 ): """ Determines subcatchments using the catchment order This version tries to keep the number op upstream/downstream catchment the small by first dederivingatchment connected to the major river(the order) given, and fill up from there. Input: - ldd - oorder - order to use - sizelimit - smallest catchments to include, default is all (sizelimit=0) in number of cells - if fill is set to True the higer order catchment are filled also - if fillcomplete is set to True the whole ldd is filled with catchments. :returns sc, dif, nldd; Subcatchment, Points, subcatchldd """ # outl = find_outlet(ldd) # large = pcr.subcatchment(ldd,pcr.boolean(outl)) if stoporder == 0: stoporder = oorder stt = pcr.streamorder(ldd) sttd = pcr.downstream(ldd, stt) pts = pcr.ifthen((pcr.scalar(sttd) - pcr.scalar(stt)) > 0.0, sttd) maxorder = pcraster.framework.getCellValue(pcr.mapmaximum(stt), 1, 1) dif = pcr.uniqueid(pcr.boolean(pcr.ifthen(stt == pcr.ordinal(oorder), pts))) if fill: for order in range(oorder, maxorder): m_pts = pcr.ifthen((pcr.scalar(sttd) - pcr.scalar(order)) > 0.0, sttd) m_dif = pcr.uniqueid( pcr.boolean(pcr.ifthen(stt == pcr.ordinal(order), m_pts)) ) dif = pcr.uniqueid(pcr.boolean(pcr.cover(m_dif, dif))) for myorder in range(oorder - 1, stoporder, -1): sc = pcr.subcatchment(ldd, pcr.nominal(dif)) m_pts = pcr.ifthen((pcr.scalar(sttd) - pcr.scalar(stt)) > 0.0, sttd) m_dif = pcr.uniqueid( pcr.boolean(pcr.ifthen(stt == pcr.ordinal(myorder - 1), m_pts)) ) dif = pcr.uniqueid( pcr.boolean(pcr.cover(pcr.ifthen(pcr.scalar(sc) == 0, m_dif), dif)) ) if fillcomplete: sc = pcr.subcatchment(ldd, pcr.nominal(dif)) cs, m_dif, stt = subcatch_order_a(ldd, stoporder) dif = pcr.uniqueid( pcr.boolean( pcr.cover( pcr.ifthen(pcr.scalar(sc) == 0, pcr.ordinal(m_dif)), pcr.ordinal(dif), ) ) ) scsize = pcr.catchmenttotal(1, ldd) dif = pcr.ordinal(pcr.uniqueid(pcr.boolean(pcr.ifthen(scsize >= sizelimit, dif)))) sc = pcr.subcatchment(ldd, dif) # Make pit ldd nldd = pcr.lddrepair(pcr.ifthenelse(pcr.cover(dif, 0) > 0, 5, ldd)) return sc, dif, nldd
def main(): # output 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") # tmp folder tmp_folder = out_folder + "/tmp/" if os.path.exists(tmp_folder): shutil.rmtree(tmp_folder) os.makedirs(tmp_folder) # set the clone map print("set the clone map") pcr.setclone(global_clone_map_file) # read ldd map print("define the ldd") # ~ ldd_map = pcr.readmap(global_ldd_inp_file) ldd_map = pcr.lddrepair(pcr.lddrepair(pcr.ldd(vos.readPCRmapClone(v = global_ldd_inp_file, \ cloneMapFileName = global_clone_map_file, \ tmpDir = tmp_folder, \ absolutePath = None, \ isLddMap = True, \ cover = None, \ isNomMap = False)))) # define the landmask if landmask_map_file == None: print("define the landmask based on the ldd input") # ~ landmask = pcr.defined(pcr.readmap(global_ldd_inp_file)) landmask = pcr.defined(ldd_map) landmask = pcr.ifthen(landmask, landmask) else: print("define the landmask based on the input landmask_map_file") landmask = pcr.readmap(landmask_map_file) ldd_map = pcr.ifthen(landmask, pcr.cover(ldd_map, pcr.ldd(5))) ldd_map = pcr.lddrepair(pcr.lddrepair(pcr.ldd(ldd_map))) landmask = pcr.defined(ldd_map) landmask = pcr.ifthen(landmask, landmask) # save ldd files used # - global ldd cmd = "cp " + str(global_ldd_inp_file) + " ." print(cmd) os.system(cmd) # - ldd map that is used pcr.report(ldd_map, "lddmap_used.map") # make catchment map print("make catchment map") catchment_map = pcr.catchment(ldd_map, pcr.pit(ldd_map)) # read global subdomain file print("read global subdomain file") global_subdomain_map = vos.readPCRmapClone( v=global_subdomain_file, cloneMapFileName=global_clone_map_file, tmpDir=tmp_folder, absolutePath=None, isLddMap=False, cover=None, isNomMap=True) # set initial subdomain print("assign subdomains to all catchments") subdomains_initial = pcr.areamajority(global_subdomain_map, catchment_map) subdomains_initial = pcr.ifthen(landmask, subdomains_initial) pcr.aguila(subdomains_initial) pcr.report(subdomains_initial, "global_subdomains_initial.map") print(str(int(vos.getMinMaxMean(pcr.scalar(subdomains_initial))[0]))) print(str(int(vos.getMinMaxMean(pcr.scalar(subdomains_initial))[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)) process_this_clone = False if pcr.cellvalue(pcr.mapmaximum(pcr.scalar(mask_selected_boolean)), 1, 1)[0] > 0: process_this_clone = True # ~ if nr == 1: pcr.aguila(mask_selected_boolean) # - initial check value check_ok = True if process_this_clone: 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 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 # ~ # ignore checking # ~ check_ok = True if check_ok == True and process_this_clone == 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 and process_this_clone == True: 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_final.map") num_of_masks = int(vos.getMinMaxMean(pcr.scalar(subdomains_final))[1]) print(num_of_masks) print("") print("") print("") print("Making the clone and landmask maps for all subdomains") num_of_masks = int(vos.getMinMaxMean(pcr.scalar(subdomains_final))[1]) # clone and mask folders clone_folder = out_folder + "/clone/" if os.path.exists(clone_folder): shutil.rmtree(clone_folder) os.makedirs(clone_folder) mask_folder = out_folder + "/mask/" if os.path.exists(mask_folder): shutil.rmtree(mask_folder) os.makedirs(mask_folder) print("") print("") for nr in range(1, num_of_masks + 1, 1): msg = "Processing the subdomain %s" % (str(nr)) print(msg) # set the global clone pcr.setclone(global_clone_map_file) mask_selected_boolean = pcr.ifthen(subdomains_final == nr, pcr.boolean(1.0)) mask_selected_nominal = pcr.ifthen(subdomains_final == nr, pcr.nominal(nr)) mask_file = "mask/mask_%s.map" % (str(nr)) pcr.report(mask_selected_nominal, mask_file) 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))) # cellsize in arcdegree cellsize = cellsize_in_arcmin / 60. # number of rows and cols num_rows = int(round(ymax - ymin) / cellsize) num_cols = int(round(xmax - xmin) / cellsize) # make the clone map using mapattr clonemap_mask_file = "clone/clonemap_mask_%s.map" % (str(nr)) cmd = "mapattr -s -R %s -C %s -B -P yb2t -x %s -y %s -l %s %s" % ( str(num_rows), str(num_cols), str(xmin), str(ymax), str(cellsize), clonemap_mask_file) print(cmd) os.system(cmd) # set the local landmask for the clump pcr.setclone(clonemap_mask_file) local_mask = vos.readPCRmapClone(v = mask_file, \ cloneMapFileName = clonemap_mask_file, tmpDir = tmp_folder, \ absolutePath = None, isLddMap = False, cover = None, isNomMap = True) local_mask_boolean = pcr.defined(local_mask) local_mask_boolean = pcr.ifthen(local_mask_boolean, local_mask_boolean) pcr.report(local_mask_boolean, mask_file) print("") print("") print("") print(num_of_masks)
def evaluateAllModelResults(self,globalCloneMapFileName,\ catchmentClassFileName,\ lddMapFileName,\ cellAreaMapFileName,\ pcrglobwb_output,\ analysisOutputDir="",\ tmpDir = "/dev/shm/edwin_grdc_"): # output directory for all analyses for all stations analysisOutputDir = str(analysisOutputDir) self.chartOutputDir = analysisOutputDir+"/chart/" self.tableOutputDir = analysisOutputDir+"/table/" # if analysisOutputDir == "": self.chartOutputDir = "chart/" if analysisOutputDir == "": self.tableOutputDir = "table/" # # make the chart and table directories: os.system('rm -r '+self.chartOutputDir+"*") os.system('rm -r '+self.tableOutputDir+"*") os.makedirs(self.chartOutputDir) os.makedirs(self.tableOutputDir) # cloneMap for all pcraster operations pcr.setclone(globalCloneMapFileName) cloneMap = pcr.boolean(1) self.cell_size_in_arc_degree = vos.getMapAttributesALL(globalCloneMapFileName)['cellsize'] lddMap = pcr.lddrepair(pcr.readmap(lddMapFileName)) cellArea = pcr.scalar(pcr.readmap(cellAreaMapFileName)) # The landMaskClass map contains the nominal classes for all landmask regions. landMaskClass = pcr.nominal(cloneMap) # default: if catchmentClassFileName is not given if catchmentClassFileName != None: landMaskClass = pcr.nominal(pcr.readmap(catchmentClassFileName)) # model catchment areas and cordinates catchmentAreaAll = pcr.catchmenttotal(cellArea, lddMap) / (1000*1000) # unit: km2 xCoordinate = pcr.xcoordinate(cloneMap) yCoordinate = pcr.ycoordinate(cloneMap) print "Jaaaaaa" for id in self.list_of_grdc_ids: logger.info("Evaluating simulated discharge to the grdc observation at "+str(self.attributeGRDC["id_from_grdc"][str(id)])+".") # identify model pixel self.identifyModelPixel(tmpDir,catchmentAreaAll,landMaskClass,xCoordinate,yCoordinate,str(id)) # evaluate model results to GRDC data self.evaluateModelResultsToGRDC(str(id),pcrglobwb_output,catchmentClassFileName,tmpDir) # write the summary to a table summary_file = analysisOutputDir+"summary.txt" # logger.info("Writing the summary for all stations to the file: "+str(summary_file)+".") # # prepare the file: summary_file_handle = open(summary_file,"w") # # write the header summary_file_handle.write( ";".join(self.grdc_dict_keys)+"\n") # # write the content for id in self.list_of_grdc_ids: rowLine = "" for key in self.grdc_dict_keys: rowLine += str(self.attributeGRDC[key][str(id)]) + ";" rowLine = rowLine[0:-1] + "\n" summary_file_handle.write(rowLine) summary_file_handle.close()
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 __init__(self, clone_map_file, \ dem_average_netcdf, dem_floodplain_netcdf, ldd_netcdf, \ lookup_table_average_thickness, lookup_table_zscore, \ number_of_samples, include_percentile = True,\ threshold_sedimentary_basin = 50.0, elevation_F_min = 0.0, elevation_F_max = 50.0): # values defined in de Graaf et al. (2014) DynamicModel.__init__(self) MonteCarloModel.__init__(self) msg = "\n" msg += "\n" msg += 'For each step, please refer to de Graaf et al. (2014).' msg += "\n" logger.info(msg) # set clone self.clone_map_file = clone_map_file pcr.setclone(clone_map_file) # an option to include_percentile or not self.include_percentile = include_percentile # number of samples self.number_of_samples = pcr.scalar(number_of_samples) logger.info( "Step 1: Identify the cells belonging to the sedimentary basin region." ) dem_average = vos.netcdf2PCRobjCloneWithoutTime(dem_average_netcdf['file_name'],\ dem_average_netcdf['variable_name'],\ clone_map_file) dem_average = pcr.max(0.0, dem_average) self.dem_average = pcr.cover(dem_average, 0.0) dem_floodplain = vos.netcdf2PCRobjCloneWithoutTime( dem_floodplain_netcdf['file_name'], dem_floodplain_netcdf['variable_name'], clone_map_file) dem_floodplain = pcr.max(0.0, dem_floodplain) lddMap = vos.netcdf2PCRobjCloneWithoutTime(ldd_netcdf['file_name'], ldd_netcdf['variable_name'], clone_map_file) self.lddMap = pcr.lddrepair(pcr.lddrepair(pcr.ldd(lddMap))) self.landmask = pcr.defined(self.lddMap) elevation_F = dem_average - dem_floodplain sedimentary_basin_extent = pcr.ifthen( elevation_F < pcr.scalar(threshold_sedimentary_basin), pcr.boolean(1)) # include the continuity along the river network sedimentary_basin_extent = pcr.windowmajority( sedimentary_basin_extent, 3.00 * vos.getMapAttributes(clone_map_file, "cellsize")) sedimentary_basin_extent = pcr.cover(sedimentary_basin_extent, \ pcr.path(self.lddMap, pcr.defined(sedimentary_basin_extent))) # TODO: We should also include the extent of major aquifer basins and unconsolidated sediments in the GLiM map. elevation_F = pcr.ifthen(sedimentary_basin_extent, elevation_F) elevation_F = pcr.max(0.0, elevation_F) elevation_F = pcr.min(50., elevation_F) logger.info( "Step 2: Calculate relative difference and associate z_score.") relative_elevation_F = pcr.scalar( 1.0) - (elevation_F - elevation_F_min) / (elevation_F_max - elevation_F_min) z_score_relat_elev_F = pcr.lookupscalar(lookup_table_zscore, relative_elevation_F) self.F = z_score_relat_elev_F # zscore (varying over the map) # maximum and minimum z_score self.F = pcr.min(3.75, self.F) self.F = pcr.max(-10.00, self.F) logger.info( "Step 3: Assign average and variation of aquifer thickness.") self.lookup_table_average_thickness = lookup_table_average_thickness self.lnCV = pcr.scalar( 0.1 ) # According to Inge, this lnCV value corresponds to the table "lookup_table_average_thickness".
# - set the landmask landmask_map_file = "/projects/0/dfguu/data/hydroworld/others/05ArcMinCloneMaps/new_masks_from_top/mask_" + str(mask_code) + ".map" msg = "Set the landmask to : " + str(landmask_map_file) logger.info(msg) landmask = pcr.readmap(landmask_map_file) # resampling low resolution ldd map msg = "Resample the low resolution ldd map." logger.info(msg) ldd_map_low_resolution_file_name = "/projects/0/dfguu/data/hydroworld/PCRGLOBWB20/input5min/routing/lddsound_05min.map" ldd_map_low_resolution = vos.readPCRmapClone(ldd_map_low_resolution_file_name, \ clone_map_file, \ tmp_folder, \ None, True, None, False) ldd_map_low_resolution = pcr.ifthen(landmask, ldd_map_low_resolution) # NOTE THAT YOU MAY NOT HAVE TO MASK-OUT THE LDD. ldd_map_low_resolution = pcr.lddrepair(pcr.ldd(ldd_map_low_resolution)) ldd_map_low_resolution = pcr.lddrepair(ldd_map_low_resolution) pcr.report(ldd_map_low_resolution, "resampled_low_resolution_ldd.map") # permanent water bodies files (at 5 arc-minute resolution) reservoir_capacity_file = "/projects/0/dfguu/data/hydroworld/PCRGLOBWB20/input5min/routing/reservoirs/waterBodiesFinal_version15Sept2013/maps/reservoircapacity_2010.map" fracwat_file = "/projects/0/dfguu/data/hydroworld/PCRGLOBWB20/input5min/routing/reservoirs/waterBodiesFinal_version15Sept2013/maps/fracwat_2010.map" water_body_id_file = "/projects/0/dfguu/data/hydroworld/PCRGLOBWB20/input5min/routing/reservoirs/waterBodiesFinal_version15Sept2013/maps/waterbodyid_2010.map" # cell_area_file cell_area_file = "/projects/0/dfguu/data/hydroworld/PCRGLOBWB20/input5min/routing/cellsize05min.correct.map" # bankfull capacity (5 arcmin, volume: m3)
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('-t', '--time', dest='time', default='', help='time in YYYYMMDDHHMMSS, overrides time in NetCDF input if set') # parser.add_option('-s', '--hand_strahler', # dest='hand_strahler', default=7, type='int', # help='Strahler order threshold >= selected as riverine') parser.add_option('-m', '--max_strahler', dest = 'max_strahler', default=1000, type='int', help='Maximum Strahler order to loop over') parser.add_option('-d', '--destination', dest='dest_path', default='inun', help='Destination path') parser.add_option('-H', '--hand_file_prefix', dest='hand_file_prefix', default='', help='optional HAND file prefix of already generated HAND files') parser.add_option('-n', '--neg_HAND', dest='neg_HAND', default=0, type='int', help='if set to 1, allow for negative HAND values in HAND maps') (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) case_name = 'inun_{:s}_catch_{:02d}'.format(flood_name, 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, 'HighResMaps', 'dem_file', True) options.ldd_file = inun_lib.configget(config, 'HighResMaps', 'ldd_file', True) options.stream_file = inun_lib.configget(config, 'HighResMaps', 'stream_file', True) options.riv_length_fact_file = inun_lib.configget(config, 'wflowResMaps', 'riv_length_fact_file', True) options.ldd_wflow = inun_lib.configget(config, 'wflowResMaps', 'ldd_wflow', True) options.riv_width_file = inun_lib.configget(config, 'wflowResMaps', 'riv_width_file', True) options.file_format = inun_lib.configget(config, 'file_settings', 'file_format', 0, datatype='int') options.out_format = inun_lib.configget(config, 'file_settings', 'out_format', 0, datatype='int') options.latlon = inun_lib.configget(config, 'file_settings', 'latlon', 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.flood_volume_type = inun_lib.configget(config, 'inundation', 'flood_volume_type', 0, datatype='int') # 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'] = '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 for each strahler order max_s = inun_lib.define_max_strahler(options.stream_file, logging=logger) stream_max = np.minimum(max_s, options.max_strahler) for hand_strahler in range(options.catchment_strahler, stream_max + 1, 1): dem_name = os.path.split(options.dem_file)[1].split('.')[0] if os.path.isfile('{:s}_{:02d}.tif'.format(options.hand_file_prefix, hand_strahler)): hand_file = '{:s}_{:02d}.tif'.format(options.hand_file_prefix, hand_strahler) else: logger.info('No HAND files with HAND prefix were found, checking {:s}_hand_strahler_{:02d}.tif'.format(dem_name, hand_strahler)) hand_file = os.path.join(options.dest_path, '{:s}_hand_strahler_{:02d}.tif'.format(dem_name, hand_strahler)) if not(os.path.isfile(hand_file)): # hand file does not exist yet! Generate it, otherwise skip! logger.info('HAND file {:s} not found, start 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, hand_strahler)) ds_hand, band_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 #check if the highest stream order of the tile is below the hand_strahler # if the highest stream order of the tile is smaller than hand_strahler, than DEM values are taken instead of HAND values. max_stream_tile = inun_lib.define_max_strahler(stream_temp_file, logging=logger) if max_stream_tile < hand_strahler: hand_pcr = terrain_pcr logger.info('For this tile, DEM values are used instead of HAND because there is no stream order larger than {:02d}'.format(hand_strahler)) else: # compute streams stream_ge, subcatch = inun_lib.subcatch_stream(drainage_pcr, hand_strahler, stream=stream_pcr) # generate streams # compute basins stream_ge_dummy, subcatch = inun_lib.subcatch_stream(drainage_pcr, options.catchment_strahler, stream=stream_pcr) # 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, neg_HAND=options.neg_HAND) # 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) os.unlink(stream_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 # ##################################################################################### # set the clone pcr.setclone(options.ldd_wflow) # read wflow ldd as pcraster object ldd_pcr = pcr.readmap(options.ldd_wflow) xax, yax, riv_width, fill_value = inun_lib.gdal_readmap(options.riv_width_file, 'GTiff', logging=logger) # determine cell length in meters using ldd_pcr as clone (if latlon=True, values are converted to m2 x_res, y_res, reallength_wflow = pcrut.detRealCellLength(pcr.scalar(ldd_pcr), not(bool(options.latlon))) cell_surface_wflow = pcr.pcr2numpy(x_res * y_res, 0) if options.flood_volume_type == 0: # load the staticmaps needed to estimate volumes across all # xax, yax, riv_length, fill_value = inun_lib.gdal_readmap(options.riv_length_file, 'GTiff', logging=logger) # 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', logging=logger) riv_width[riv_width == fill_value] = 0 # read river length factor file (multiplier) xax, yax, riv_length_fact, fill_value = inun_lib.gdal_readmap(options.riv_length_fact_file, 'GTiff', logging=logger) riv_length_fact = np.ma.masked_where(riv_length_fact==fill_value, riv_length_fact) drain_length = wflow_lib.detdrainlength(ldd_pcr, x_res, y_res) # compute river length in each cell riv_length = pcr.pcr2numpy(drain_length, 0) * riv_length_fact # riv_length_pcr = pcr.numpy2pcr(pcr.Scalar, riv_length, 0) 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) if options.out_format == 0: 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)) else: inun_file_tmp = os.path.join(flood_folder, '{:s}.nc.tmp'.format(case_name)) inun_file = os.path.join(flood_folder, '{:s}.nc'.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 logger.info('Reading flood from {:s} NetCDF file'.format(options.flood_map)) a = nc.Dataset(options.flood_map, 'r') if options.latlon == 0: xax = a.variables['x'][:] yax = a.variables['y'][:] else: xax = a.variables['lon'][:] yax = a.variables['lat'][:] if options.time == '': time_list = nc.num2date(a.variables['time'][:], units = a.variables['time'].units, calendar=a.variables['time'].calendar) time = [time_list[len(time_list)/2]] else: time = [dt.datetime.strptime(options.time, '%Y%m%d%H%M%S')] 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: logger.info('Reading flood from {:s} PCRaster file'.format(options.flood_map)) xax, yax, flood, flood_fill_value = inun_lib.gdal_readmap(options.flood_map, 'PCRaster', logging=logger) flood = np.ma.masked_equal(flood, flood_fill_value) if options.time == '': options.time = '20000101000000' time = [dt.datetime.strptime(options.time, '%Y%m%d%H%M%S')] flood[flood==flood_fill_value] = 0. # load the bankfull depths if options.bankfull_map == '': bankfull = np.zeros(flood.shape) else: if options.file_format == 0: logger.info('Reading bankfull from {:s} NetCDF file'.format(options.bankfull_map)) a = nc.Dataset(options.bankfull_map, 'r') xax = a.variables['x'][:] yax = a.variables['y'][:] bankfull_series = a.variables[options.flood_variable][:] bankfull_data = bankfull_series.max(axis=0) if np.ma.is_masked(bankfull_data): bankfull = bankfull_data.data bankfull[bankfull_data.mask] = 0 if yax[-1] > yax[0]: yax = np.flipud(yax) bankfull = np.flipud(bankfull) a.close() elif options.file_format == 1: logger.info('Reading bankfull from {:s} PCRaster file'.format(options.bankfull_map)) xax, yax, bankfull, bankfull_fill_value = inun_lib.gdal_readmap(options.bankfull_map, 'PCRaster', logging=logger) bankfull = np.ma.masked_equal(bankfull, bankfull_fill_value) # 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) if options.flood_volume_type == 0: flood_vol_m = riv_length*riv_width*flood_vol/cell_surface_wflow # volume expressed in meters water disc flood_vol_m_pcr = pcr.numpy2pcr(pcr.Scalar, flood_vol_m, 0) else: flood_vol_m = flood_vol/cell_surface_wflow flood_vol_m_data = flood_vol_m.data flood_vol_m_data[flood_vol_m.mask] = -999. logger.info('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., logging=logger) # this is placed later in the hand loop # 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)) if options.out_format == 0: ds_inun, band_inun = inun_lib.prepare_gdal(inun_file_tmp, x, y, logging=logger, srs=srs) # band_inun = ds_inun.GetRasterBand(1) else: ds_inun, band_inun = inun_lib.prepare_nc(inun_file_tmp, time, x, np.flipud(y), metadata=metadata_global, metadata_var=metadata_var, logging=logger) # 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)) 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) ) # stream_max = np.minimum(stream.max(), options.max_strahler) 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(stream_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 # warp of flood volume to inundation resolution inun_lib.gdal_warp(flood_vol_map, stream_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', logging=logger) # make sure that the option unittrue is on !! (if unitcell was is used in another function) x_res_tile, y_res_tile, reallength = pcrut.detRealCellLength(pcr.scalar(stream_pcr), not(bool(options.latlon))) cell_surface_tile = pcr.pcr2numpy(x_res_tile * y_res_tile, 0) # convert meter depth to volume [m3] flood_vol = pcr.numpy2pcr(pcr.Scalar, flood_meter*cell_surface_tile, fill_value) # first prepare a basin map, belonging to the lowest order we are looking at inundation_pcr = pcr.scalar(stream_pcr) * 0 for hand_strahler in range(options.catchment_strahler, stream_max + 1, 1): # hand_temp_file = os.path.join(flood_folder, 'hand_temp.map') if os.path.isfile(os.path.join(options.dest_path, '{:s}_hand_strahler_{:02d}.tif'.format(dem_name, hand_strahler))): hand_file = os.path.join(options.dest_path, '{:s}_hand_strahler_{:02d}.tif'.format(dem_name, hand_strahler)) else: hand_file = '{:s}_{:02d}.tif'.format(options.hand_file_prefix, hand_strahler) ds_hand, rasterband_hand = inun_lib.get_gdal_rasterband(hand_file) 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) ) 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) hand_pcr = pcr.readmap(hand_temp_file) stream_ge_hand, subcatch_hand = inun_lib.subcatch_stream(drainage_pcr, options.catchment_strahler, stream=stream_pcr) # stream_ge_hand, subcatch_hand = inun_lib.subcatch_stream(drainage_pcr, hand_strahler, stream=stream_pcr) stream_ge, subcatch = inun_lib.subcatch_stream(drainage_pcr, options.catchment_strahler, stream=stream_pcr, basin=pcr.boolean(pcr.cover(subcatch_hand, 0)), assign_existing=True, min_strahler=hand_strahler, max_strahler=hand_strahler) # generate subcatchments, only within basin for HAND flood_vol_strahler = pcr.ifthenelse(pcr.boolean(pcr.cover(subcatch, 0)), flood_vol, 0) # mask the flood volume map with the created subcatch map for strahler order = hand_strahler inundation_pcr_step = inun_lib.volume_spread(drainage_pcr, hand_pcr, pcr.subcatchment(drainage_pcr, subcatch), # to make sure backwater effects can occur from higher order rivers to lower order rivers flood_vol_strahler, volume_thres=0., iterations=options.iterations, cell_surface=pcr.numpy2pcr(pcr.Scalar, cell_surface_tile, -9999), logging=logger, order=hand_strahler, neg_HAND=options.neg_HAND) # 1166400000. # use maximum value of inundation_pcr_step and new inundation for higher strahler order inundation_pcr = pcr.max(inundation_pcr, inundation_pcr_step) 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 if options.out_format == 0: band_inun.WriteArray(inundation_cut, x_start, y_start) band_inun.FlushCache() else: # with netCDF, data is up-side-down. inun_lib.write_tile_nc(band_inun, inundation_cut, x_start, y_start) # clean up os.unlink(flood_vol_temp_file) os.unlink(drainage_temp_file) os.unlink(hand_temp_file) os.unlink(stream_temp_file) #also remove temp stream file from output folder # 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) if options.out_format == 0: ds_inun = None ds_hand = None else: ds_inun.close() 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 __init__(self, modelTime, output_folder, totat_runoff_input_file): DynamicModel.__init__(self) self.modelTime = modelTime # netcdf input files - based on PCR-GLOBWB output # - total runoff (m/month) self.totat_runoff_input_file = "/scratch-shared/edwin/05min_runs_for_gmd_paper_30_oct_2017/05min_runs_4LCs_accutraveltime_cru-forcing_1958-2015/non-natural_starting_from_1958/merged_1958_to_2015/totalRunoff_monthTot_output_1958-01-31_to_2015-12-31.nc" self.totat_runoff_input_file = totat_runoff_input_file # #~ # - discharge (m3/s) - NOT USED anymore #~ self.discharge_input_file = "/scratch-shared/edwin/05min_runs_for_gmd_paper_30_oct_2017/05min_runs_4LCs_accutraveltime_cru-forcing_1958-2015/non-natural_starting_from_1958/merged_1958_to_2015/discharge_monthAvg_output_1958-01-31_to_2015-12-31.nc" # output files - in netcdf format self.total_flow_output_file = output_folder + "/total_flow.nc" self.internal_flow_output_file = output_folder + "/internal_flow.nc" # - all will have unit m3/s # preparing temporary directory self.temporary_directory = output_folder + "/tmp/" os.makedirs(self.temporary_directory) # clone map logger.info("Set the clone map") self.clonemap_file_name = "/home/edwinvua/github/edwinkost/estimate_discharge_from_local_runoff/making_subcatchment_map/version_20180202/clone_version_20180202.map" pcr.setclone(self.clonemap_file_name) # pcraster input files landmask_file_name = None # - river network map and sub-catchment map ldd_file_name = "/projects/0/dfguu/data/hydroworld/PCRGLOBWB20/input5min/routing/lddsound_05min.map" sub_catchment_file_name = "/home/edwinvua/github/edwinkost/estimate_discharge_from_local_runoff/making_subcatchment_map/version_20180202/subcatchments_of_station_pcraster_ids.nom.bigger_than_zero.map" # - cell area (unit: m2) cell_area_file_name = "/projects/0/dfguu/data/hydroworld/PCRGLOBWB20/input5min/routing/cellsize05min.correct.map" # loading pcraster input maps self.sub_catchment = vos.readPCRmapClone(sub_catchment_file_name, \ self.clonemap_file_name, \ self.temporary_directory, \ None, False, None, \ True) self.ldd_network = vos.readPCRmapClone(ldd_file_name, \ self.clonemap_file_name, \ self.temporary_directory, \ None, \ True) self.ldd_network = pcr.lddrepair(pcr.ldd(self.ldd_network)) self.ldd_network = pcr.lddrepair(self.ldd_network) self.cell_area = vos.readPCRmapClone(cell_area_file_name, \ self.clonemap_file_name, \ self.temporary_directory, \ None) # define the landmask self.landmask = pcr.defined(self.ldd_network) if landmask_file_name != None: self.landmask = vos.readPCRmapClone(landmask_file_name, \ self.clonemap_file_name, \ self.temporary_directory, \ None) self.landmask = pcr.ifthen(pcr.defined(self.ldd_network), self.landmask) self.landmask = pcr.ifthen(self.landmask, self.landmask) # set/limit all input maps to the defined landmask self.sub_catchment = pcr.ifthen(self.landmask, self.sub_catchment) self.ldd_network = pcr.ifthen(self.landmask, self.ldd_network) self.cell_area = pcr.ifthen(self.landmask, self.cell_area) # preparing an object for reporting netcdf files: self.netcdf_report = netcdf_writer.PCR2netCDF(self.clonemap_file_name) # preparing netcdf output files: # - for total inflow self.netcdf_report.createNetCDF(self.total_flow_output_file,\ "total_flow",\ "m3/s") self.netcdf_report.createNetCDF(self.internal_flow_output_file,\ "internal_flow",\ "m3/s")
def main( source, destination, inifile, dem_in, rivshp, catchshp, gaugeshp=None, landuse=None, soil=None, lai=None, other_maps=None, logfilename="wtools_static_maps.log", verbose=True, clean=True, alltouch=False, outlets=([], []), ): # parse other maps into an array if not other_maps == None: if type(other_maps) == str: print other_maps other_maps = (other_maps.replace(" ", "").replace("[", "").replace( "]", "").split(",")) source = os.path.abspath(source) clone_map = os.path.join(source, "mask.map") clone_shp = os.path.join(source, "mask.shp") clone_prj = os.path.join(source, "mask.prj") if None in (rivshp, catchshp, dem_in): msg = """The following files are compulsory: - DEM (raster) - river (shape) - catchment (shape) """ print(msg) parser.print_help() sys.exit(1) if (inifile is not None) and (not os.path.exists(inifile)): print "path to ini file cannot be found" sys.exit(1) if not os.path.exists(rivshp): print "path to river shape cannot be found" sys.exit(1) if not os.path.exists(catchshp): print "path to catchment shape cannot be found" sys.exit(1) if not os.path.exists(dem_in): print "path to DEM cannot be found" sys.exit(1) # open a logger, dependent on verbose print to screen or not logger, ch = wt.setlogger(logfilename, "WTOOLS", verbose) # create directories # TODO: check if workdir is still necessary, try to # keep in memory as much as possible # delete old files (when the source and destination folder are different) if np.logical_and(os.path.isdir(destination), destination is not source): shutil.rmtree(destination) if destination is not source: os.makedirs(destination) # Read mask if not (os.path.exists(clone_map)): logger.error( "Clone file {:s} not found. Please run create_grid first.".format( clone_map)) sys.exit(1) else: # set clone pcr.setclone(clone_map) # get the extent from clone.tif xax, yax, clone, fill_value = wt.gdal_readmap(clone_map, "GTiff") trans = wt.get_geotransform(clone_map) extent = wt.get_extent(clone_map) xmin, ymin, xmax, ymax = extent zeros = np.zeros(clone.shape) ones = pcr.numpy2pcr(pcr.Scalar, np.ones(clone.shape), -9999) # get the projection from clone.tif srs = wt.get_projection(clone_map) unit_clone = srs.GetAttrValue("UNIT").lower() # READ CONFIG FILE # open config-file if inifile is None: config = ConfigParser.SafeConfigParser() config.optionxform = str else: config = wt.OpenConf(inifile) # read settings snapgaugestoriver = wt.configget(config, "settings", "snapgaugestoriver", True, datatype="boolean") burnalltouching = wt.configget(config, "settings", "burncatchalltouching", True, datatype="boolean") burninorder = wt.configget(config, "settings", "burncatchalltouching", False, datatype="boolean") verticetollerance = wt.configget(config, "settings", "vertice_tollerance", 0.0001, datatype="float") """ read parameters """ burn_outlets = wt.configget(config, "parameters", "burn_outlets", 10000, datatype="int") burn_rivers = wt.configget(config, "parameters", "burn_rivers", 200, datatype="int") burn_connections = wt.configget(config, "parameters", "burn_connections", 100, datatype="int") burn_gauges = wt.configget(config, "parameters", "burn_gauges", 100, datatype="int") minorder = wt.configget(config, "parameters", "riverorder_min", 3, datatype="int") try: percentiles = np.array( config.get("parameters", "statisticmaps", "0, 100").replace(" ", "").split(","), dtype="float", ) except ConfigParser.NoOptionError: percentiles = [0.0, 100.0] # read the parameters for generating a temporary very high resolution grid if unit_clone == "degree": cellsize_hr = wt.configget(config, "parameters", "highres_degree", 0.0005, datatype="float") elif (unit_clone == "metre") or (unit_clone == "meter"): cellsize_hr = wt.configget(config, "parameters", "highres_metre", 50, datatype="float") 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) clone_hr = os.path.join(destination, "clone_highres.tif") # make a highres clone as well! wt.CreateTif(clone_hr, rows_hr, cols_hr, hr_trans, srs, 0) # 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) # ???? empty = pcr.ifthen(ones == 0, pcr.scalar(0)) # TODO: check if extents are correct this way # TODO: check what the role of missing values is in zeros and ones (l. 123 # in old code) # first add a missing value to dem_in ds = gdal.Open(dem_in, gdal.GA_Update) RasterBand = ds.GetRasterBand(1) fill_val = RasterBand.GetNoDataValue() if fill_val is None: RasterBand.SetNoDataValue(-9999) ds = None # reproject to clone map: see http://stackoverflow.com/questions/10454316/how-to-project-and-resample-a-grid-to-match-another-grid-with-gdal-python # resample DEM logger.info("Resampling dem from {:s} to {:s}".format( os.path.abspath(dem_in), os.path.join(destination, dem_map))) wt.gdal_warp( dem_in, clone_map, os.path.join(destination, dem_map), format="PCRaster", gdal_interp=gdalconst.GRA_Average, ) # retrieve amount of rows and columns from clone # TODO: make windowstats applicable to source/target with different projections. This does not work yet. # retrieve srs from DEM try: srs_dem = wt.get_projection(dem_in) except: logger.warning( "No projection found in DEM, assuming WGS 1984 lat long") srs_dem = osr.SpatialReference() srs_dem.ImportFromEPSG(4326) clone2dem_transform = osr.CoordinateTransformation(srs, srs_dem) # if srs.ExportToProj4() == srs_dem.ExportToProj4(): wt.windowstats( dem_in, len(yax), len(xax), trans, srs, destination, percentiles, transform=clone2dem_transform, logger=logger, ) ## read catchment shape-file to create catchment map src = rasterio.open(clone_map) shapefile = fiona.open(catchshp, "r") catchment_shapes = [feature["geometry"] for feature in shapefile] image = features.rasterize(catchment_shapes, out_shape=src.shape, all_touched=True, transform=src.transform) catchment_domain = pcr.numpy2pcr(pcr.Ordinal, image.copy(), 0) ## read river shape-file and create burn layer shapefile = fiona.open(rivshp, "r") river_shapes = [feature["geometry"] for feature in shapefile] image = features.rasterize(river_shapes, out_shape=src.shape, all_touched=False, transform=src.transform) rivers = pcr.numpy2pcr(pcr.Nominal, image.copy(), 0) riverdem = pcr.scalar(rivers) * pcr.readmap( os.path.join(destination, dem_map)) pcr.setglobaloption("lddin") riverldd = pcr.lddcreate(riverdem, 1e35, 1e35, 1e35, 1e35) riveroutlet = pcr.cover( pcr.ifthen(pcr.scalar(riverldd) == 5, pcr.scalar(1000)), 0) burn_layer = pcr.cover( (pcr.scalar( pcr.ifthen( pcr.streamorder(riverldd) > 1, pcr.streamorder(riverldd))) - 1) * 1000 + riveroutlet, 0, ) outlets_x, outlets_y = outlets n_outlets = len(outlets_x) logger.info("Number of outlets: {}".format(n_outlets)) if n_outlets >= 1: outlets_map_numbered = tr.points_to_map(pcr.scalar(0), outlets_x, outlets_y, 0.5) outlets_map = pcr.boolean(outlets_map_numbered) # snap outlets to closest river (max 1 cell closer to river) outlets_map = pcr.boolean( pcr.cover(tr.snaptomap(pcr.ordinal(outlets_map), rivers), 0)) ## create ldd per catchment logger.info("Calculating ldd") ldddem = pcr.scalar(clone_map) # per subcatchment, burn dem, then create modified dem that fits the ldd of the subcatchment # this ldd dem is merged over catchments, to create a global ldd that abides to the subcatchment boundaries for idx, shape in enumerate(catchment_shapes): logger.info("Computing ldd for catchment " + str(idx + 1) + "/" + str(len(catchment_shapes))) image = features.rasterize([shape], out_shape=src.shape, all_touched=True, transform=src.transform) catchment = pcr.numpy2pcr(pcr.Scalar, image.copy(), 0) dem_burned_catchment = ( pcr.readmap(os.path.join(destination, dem_map)) * pcr.scalar(catchment_domain) * catchment) - burn_layer # ldddem_catchment = pcr.lddcreatedem( # dem_burned_catchment, 1e35, 1e35, 1e35, 1e35) ldddem = pcr.cover(ldddem, dem_burned_catchment) pcr.report(ldddem, os.path.join(destination, "ldddem.map")) wflow_ldd = pcr.lddcreate(ldddem, 1e35, 1e35, 1e35, 1e35) if n_outlets >= 1: # set outlets to pit wflow_ldd = pcr.ifthenelse(outlets_map, pcr.ldd(5), wflow_ldd) wflow_ldd = pcr.lddrepair(wflow_ldd) pcr.report(wflow_ldd, os.path.join(destination, "wflow_ldd.map")) # compute stream order, identify river cells streamorder = pcr.ordinal(pcr.streamorder(wflow_ldd)) river = pcr.ifthen(streamorder >= pcr.ordinal(minorder), pcr.boolean(1)) # find the minimum value in the DEM and cover missing values with a river with this value. Effect is none!! so now left out! # mindem = int(np.min(pcr.pcr2numpy(pcr.ordinal(os.path.join(destination, dem_map)),9999999))) # dem_resample_map = pcr.cover(os.path.join(destination, dem_map), pcr.scalar(river)*0+mindem) # pcr.report(dem_resample_map, os.path.join(destination, dem_map)) pcr.report(streamorder, os.path.join(destination, streamorder_map)) pcr.report(river, os.path.join(destination, river_map)) # deal with your catchments if gaugeshp == None: logger.info("No gauges defined, using outlets instead") gauges = pcr.ordinal( pcr.uniqueid( pcr.boolean( pcr.ifthen(pcr.scalar(wflow_ldd) == 5, pcr.boolean(1))))) pcr.report(gauges, os.path.join(destination, gauges_map)) # TODO: Add the gauge shape code from StaticMaps.py (line 454-489) # TODO: add river length map (see SticMaps.py, line 492-499) # since the products here (river length fraction) are not yet used # this is disabled for now, as it also takes a lot of computation time if False: # report river length # make a high resolution empty map dem_hr_file = os.path.join(destination, "dem_highres.tif") burn_hr_file = os.path.join(destination, "burn_highres.tif") demburn_hr_file = os.path.join(destination, "demburn_highres.map") riv_hr_file = os.path.join(destination, "riv_highres.map") wt.gdal_warp(dem_in, clone_hr, dem_hr_file) # wt.CreateTif(riv_hr, rows_hr, cols_hr, hr_trans, srs, 0) # open the shape layer ds = ogr.Open(rivshp) lyr = ds.GetLayer(0) wt.ogr_burn( lyr, clone_hr, -100, file_out=burn_hr_file, format="GTiff", gdal_type=gdal.GDT_Float32, fill_value=0, ) # read dem and burn values and add xax_hr, yax_hr, burn_hr, fill = wt.gdal_readmap(burn_hr_file, "GTiff") burn_hr[burn_hr == fill] = 0 xax_hr, yax_hr, dem_hr, fill = wt.gdal_readmap(dem_hr_file, "GTiff") dem_hr[dem_hr == fill] = np.nan demburn_hr = dem_hr + burn_hr demburn_hr[np.isnan(demburn_hr)] = -9999 wt.gdal_writemap(demburn_hr_file, "PCRaster", xax_hr, yax_hr, demburn_hr, -9999.) pcr.setclone(demburn_hr_file) demburn_hr = pcr.readmap(demburn_hr_file) logger.info("Calculating ldd to determine river length") ldd_hr = pcr.lddcreate(demburn_hr, 1e35, 1e35, 1e35, 1e35) pcr.report(ldd_hr, os.path.join(destination, "ldd_hr.map")) pcr.setglobaloption("unitcell") riv_hr = pcr.scalar( pcr.streamorder(ldd_hr) >= minorder) * pcr.downstreamdist(ldd_hr) pcr.report(riv_hr, riv_hr_file) pcr.setglobaloption("unittrue") pcr.setclone(clone_map) logger.info("Computing river length") wt.windowstats( riv_hr_file, len(yax), len(xax), trans, srs, destination, stat="fact", transform=False, logger=logger, ) # TODO: nothing happens with the river lengths yet. Need to decide how to use these # report outlet map pcr.report( pcr.ifthen(pcr.ordinal(wflow_ldd) == 5, pcr.ordinal(1)), os.path.join(destination, outlet_map), ) # report subcatchment map subcatchment = pcr.subcatchment(wflow_ldd, gauges) pcr.report(pcr.ordinal(subcatchment), os.path.join(destination, subcatch_map)) # Report land use map if landuse == None: logger.info( "No land use map used. Preparing {:s} with only ones.".format( os.path.join(destination, landuse_map))) pcr.report(pcr.nominal(ones), os.path.join(destination, landuse_map)) else: logger.info("Resampling land use from {:s} to {:s}".format( os.path.abspath(landuse), os.path.join(destination, os.path.abspath(landuse_map)), )) wt.gdal_warp( landuse, clone_map, os.path.join(destination, landuse_map), format="PCRaster", gdal_interp=gdalconst.GRA_Mode, gdal_type=gdalconst.GDT_Int32, ) # report soil map if soil == None: logger.info("No soil map used. Preparing {:s} with only ones.".format( os.path.join(destination, soil_map))) pcr.report(pcr.nominal(ones), os.path.join(destination, soil_map)) else: logger.info("Resampling soil from {:s} to {:s}".format( os.path.abspath(soil), os.path.join(destination, os.path.abspath(soil_map)), )) wt.gdal_warp( soil, clone_map, os.path.join(destination, soil_map), format="PCRaster", gdal_interp=gdalconst.GRA_Mode, gdal_type=gdalconst.GDT_Int32, ) if lai == None: logger.info( "No vegetation LAI maps used. Preparing default maps {:s} with only ones." .format(os.path.join(destination, soil_map))) pcr.report(pcr.nominal(ones), os.path.join(destination, soil_map)) else: dest_lai = os.path.join(destination, "clim") os.makedirs(dest_lai) for month in range(12): lai_in = os.path.join(lai, "LAI00000.{:03d}".format(month + 1)) lai_out = os.path.join(dest_lai, "LAI00000.{:03d}".format(month + 1)) logger.info("Resampling vegetation LAI from {:s} to {:s}".format( os.path.abspath(lai_in), os.path.abspath(lai_out))) wt.gdal_warp( lai_in, clone_map, lai_out, format="PCRaster", gdal_interp=gdalconst.GRA_Bilinear, gdal_type=gdalconst.GDT_Float32, ) # report soil map if other_maps == None: logger.info("No other maps used. Skipping other maps.") else: logger.info("Resampling list of other maps...") for map_file in other_maps: map_name = os.path.split(map_file)[1] logger.info("Resampling a map from {:s} to {:s}".format( os.path.abspath(map_file), os.path.join( destination, os.path.splitext(os.path.basename(map_file))[0] + ".map", ), )) wt.gdal_warp( map_file, clone_map, os.path.join( destination, os.path.splitext(os.path.basename(map_file))[0] + ".map", ), format="PCRaster", gdal_interp=gdalconst.GRA_Mode, gdal_type=gdalconst.GDT_Float32, ) if clean: wt.DeleteList(glob.glob(os.path.join(destination, "*.xml")), logger=logger) wt.DeleteList(glob.glob(os.path.join(destination, "clim", "*.xml")), logger=logger) wt.DeleteList(glob.glob(os.path.join(destination, "*highres*")), logger=logger)
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( "-t", "--time", dest="time", default="", help="time in YYYYMMDDHHMMSS, overrides time in NetCDF input if set", ) # parser.add_option('-s', '--hand_strahler', # dest='hand_strahler', default=7, type='int', # help='Strahler order threshold >= selected as riverine') parser.add_option( "-m", "--max_strahler", dest="max_strahler", default=1000, type="int", help="Maximum Strahler order to loop over", ) parser.add_option( "-d", "--destination", dest="dest_path", default="inun", help="Destination path" ) parser.add_option( "-H", "--hand_file_prefix", dest="hand_file_prefix", default="", help="optional HAND file prefix of already generated HAND files", ) parser.add_option( "-n", "--neg_HAND", dest="neg_HAND", default=0, type="int", help="if set to 1, allow for negative HAND values in HAND maps", ) (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) case_name = "inun_{:s}_catch_{:02d}".format(flood_name, 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, "HighResMaps", "dem_file", True) options.ldd_file = inun_lib.configget(config, "HighResMaps", "ldd_file", True) options.stream_file = inun_lib.configget(config, "HighResMaps", "stream_file", True) options.riv_length_fact_file = inun_lib.configget( config, "wflowResMaps", "riv_length_fact_file", True ) options.ldd_wflow = inun_lib.configget(config, "wflowResMaps", "ldd_wflow", True) options.riv_width_file = inun_lib.configget( config, "wflowResMaps", "riv_width_file", True ) options.file_format = inun_lib.configget( config, "file_settings", "file_format", 0, datatype="int" ) options.out_format = inun_lib.configget( config, "file_settings", "out_format", 0, datatype="int" ) options.latlon = inun_lib.configget( config, "file_settings", "latlon", 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.flood_volume_type = inun_lib.configget( config, "inundation", "flood_volume_type", 0, datatype="int" ) # 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("streamfile: {:s}".format(options.stream_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"] = "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 for each strahler order max_s = inun_lib.define_max_strahler(options.stream_file, logging=logger) stream_max = np.minimum(max_s, options.max_strahler) for hand_strahler in range(options.catchment_strahler, stream_max + 1, 1): dem_name = os.path.split(options.dem_file)[1].split(".")[0] if os.path.isfile( "{:s}_{:02d}.tif".format(options.hand_file_prefix, hand_strahler) ): hand_file = "{:s}_{:02d}.tif".format( options.hand_file_prefix, hand_strahler ) else: logger.info( "No HAND files with HAND prefix were found, checking {:s}_hand_strahler_{:02d}.tif".format( dem_name, hand_strahler ) ) hand_file = os.path.join( options.dest_path, "{:s}_hand_strahler_{:02d}.tif".format(dem_name, hand_strahler), ) if not (os.path.isfile(hand_file)): # hand file does not exist yet! Generate it, otherwise skip! logger.info( "HAND file {:s} not found, start 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, hand_strahler), ) ds_hand, band_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 # check if the highest stream order of the tile is below the hand_strahler # if the highest stream order of the tile is smaller than hand_strahler, than DEM values are taken instead of HAND values. max_stream_tile = inun_lib.define_max_strahler( stream_temp_file, logging=logger ) if max_stream_tile < hand_strahler: hand_pcr = terrain_pcr logger.info( "For this tile, DEM values are used instead of HAND because there is no stream order larger than {:02d}".format( hand_strahler ) ) else: # compute streams stream_ge, subcatch = inun_lib.subcatch_stream( drainage_pcr, hand_strahler, stream=stream_pcr ) # generate streams # compute basins stream_ge_dummy, subcatch = inun_lib.subcatch_stream( drainage_pcr, options.catchment_strahler, stream=stream_pcr ) # 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, neg_HAND=options.neg_HAND, ) # 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) os.unlink(stream_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 # ##################################################################################### # set the clone pcr.setclone(options.ldd_wflow) # read wflow ldd as pcraster object ldd_pcr = pcr.readmap(options.ldd_wflow) xax, yax, riv_width, fill_value = inun_lib.gdal_readmap( options.riv_width_file, "GTiff", logging=logger ) # determine cell length in meters using ldd_pcr as clone (if latlon=True, values are converted to m2 x_res, y_res, reallength_wflow = pcrut.detRealCellLength( pcr.scalar(ldd_pcr), not (bool(options.latlon)) ) cell_surface_wflow = pcr.pcr2numpy(x_res * y_res, 0) if options.flood_volume_type == 0: # load the staticmaps needed to estimate volumes across all # xax, yax, riv_length, fill_value = inun_lib.gdal_readmap(options.riv_length_file, 'GTiff', logging=logger) # 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", logging=logger ) riv_width[riv_width == fill_value] = 0 # read river length factor file (multiplier) xax, yax, riv_length_fact, fill_value = inun_lib.gdal_readmap( options.riv_length_fact_file, "GTiff", logging=logger ) riv_length_fact = np.ma.masked_where( riv_length_fact == fill_value, riv_length_fact ) drain_length = wflow_lib.detdrainlength(ldd_pcr, x_res, y_res) # compute river length in each cell riv_length = pcr.pcr2numpy(drain_length, 0) * riv_length_fact # riv_length_pcr = pcr.numpy2pcr(pcr.Scalar, riv_length, 0) 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) if options.out_format == 0: 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)) else: inun_file_tmp = os.path.join(flood_folder, "{:s}.nc.tmp".format(case_name)) inun_file = os.path.join(flood_folder, "{:s}.nc".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 logger.info("Reading flood from {:s} NetCDF file".format(options.flood_map)) a = nc.Dataset(options.flood_map, "r") if options.latlon == 0: xax = a.variables["x"][:] yax = a.variables["y"][:] else: try: xax = a.variables["lon"][:] yax = a.variables["lat"][:] except: xax = a.variables["x"][:] yax = a.variables["y"][:] if options.time == "": time_list = nc.num2date( a.variables["time"][:], units=a.variables["time"].units, calendar=a.variables["time"].calendar, ) time = [time_list[len(time_list) / 2]] else: time = [dt.datetime.strptime(options.time, "%Y%m%d%H%M%S")] 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: logger.info("Reading flood from {:s} PCRaster file".format(options.flood_map)) xax, yax, flood, flood_fill_value = inun_lib.gdal_readmap( options.flood_map, "PCRaster", logging=logger ) flood = np.ma.masked_equal(flood, flood_fill_value) if options.time == "": options.time = "20000101000000" time = [dt.datetime.strptime(options.time, "%Y%m%d%H%M%S")] flood[flood == flood_fill_value] = 0. # load the bankfull depths if options.bankfull_map == "": bankfull = np.zeros(flood.shape) else: if options.file_format == 0: logger.info( "Reading bankfull from {:s} NetCDF file".format(options.bankfull_map) ) a = nc.Dataset(options.bankfull_map, "r") xax = a.variables["x"][:] yax = a.variables["y"][:] # xax = a.variables['lon'][:] # yax = a.variables['lat'][:] bankfull_series = a.variables[options.flood_variable][:] bankfull_data = bankfull_series.max(axis=0) if np.ma.is_masked(bankfull_data): bankfull = bankfull_data.data bankfull[bankfull_data.mask] = 0 if yax[-1] > yax[0]: yax = np.flipud(yax) bankfull = np.flipud(bankfull) a.close() elif options.file_format == 1: logger.info( "Reading bankfull from {:s} PCRaster file".format(options.bankfull_map) ) xax, yax, bankfull, bankfull_fill_value = inun_lib.gdal_readmap( options.bankfull_map, "PCRaster", logging=logger ) bankfull = np.ma.masked_equal(bankfull, bankfull_fill_value) # 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) if options.flood_volume_type == 0: flood_vol_m = ( riv_length * riv_width * flood_vol / cell_surface_wflow ) # volume expressed in meters water disc flood_vol_m_pcr = pcr.numpy2pcr(pcr.Scalar, flood_vol_m, 0) else: flood_vol_m = flood_vol / cell_surface_wflow flood_vol_m_data = flood_vol_m.data flood_vol_m_data[flood_vol_m.mask] = -999. logger.info("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., logging=logger, ) # this is placed later in the hand loop # 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)) if options.out_format == 0: ds_inun, band_inun = inun_lib.prepare_gdal( inun_file_tmp, x, y, logging=logger, srs=srs ) # band_inun = ds_inun.GetRasterBand(1) else: ds_inun, band_inun = inun_lib.prepare_nc( inun_file_tmp, time, x, np.flipud(y), metadata=metadata_global, metadata_var=metadata_var, logging=logger, ) # 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 ) ) 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), ) # stream_max = np.minimum(stream.max(), options.max_strahler) 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(stream_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 # warp of flood volume to inundation resolution inun_lib.gdal_warp( flood_vol_map, stream_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", logging=logger ) # make sure that the option unittrue is on !! (if unitcell was is used in another function) x_res_tile, y_res_tile, reallength = pcrut.detRealCellLength( pcr.scalar(stream_pcr), not (bool(options.latlon)) ) cell_surface_tile = pcr.pcr2numpy(x_res_tile * y_res_tile, 0) # convert meter depth to volume [m3] flood_vol = pcr.numpy2pcr( pcr.Scalar, flood_meter * cell_surface_tile, fill_value ) # first prepare a basin map, belonging to the lowest order we are looking at inundation_pcr = pcr.scalar(stream_pcr) * 0 for hand_strahler in range(options.catchment_strahler, stream_max + 1, 1): # hand_temp_file = os.path.join(flood_folder, 'hand_temp.map') if os.path.isfile( os.path.join( options.dest_path, "{:s}_hand_strahler_{:02d}.tif".format(dem_name, hand_strahler), ) ): hand_file = os.path.join( options.dest_path, "{:s}_hand_strahler_{:02d}.tif".format(dem_name, hand_strahler), ) else: hand_file = "{:s}_{:02d}.tif".format( options.hand_file_prefix, hand_strahler ) ds_hand, rasterband_hand = inun_lib.get_gdal_rasterband(hand_file) 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), ) 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, ) hand_pcr = pcr.readmap(hand_temp_file) stream_ge_hand, subcatch_hand = inun_lib.subcatch_stream( drainage_pcr, options.catchment_strahler, stream=stream_pcr ) # stream_ge_hand, subcatch_hand = inun_lib.subcatch_stream(drainage_pcr, hand_strahler, stream=stream_pcr) stream_ge, subcatch = inun_lib.subcatch_stream( drainage_pcr, options.catchment_strahler, stream=stream_pcr, basin=pcr.boolean(pcr.cover(subcatch_hand, 0)), assign_existing=True, min_strahler=hand_strahler, max_strahler=hand_strahler, ) # generate subcatchments, only within basin for HAND flood_vol_strahler = pcr.ifthenelse( pcr.boolean(pcr.cover(subcatch, 0)), flood_vol, 0 ) # mask the flood volume map with the created subcatch map for strahler order = hand_strahler inundation_pcr_step = inun_lib.volume_spread( drainage_pcr, hand_pcr, pcr.subcatchment( drainage_pcr, subcatch ), # to make sure backwater effects can occur from higher order rivers to lower order rivers flood_vol_strahler, volume_thres=0., iterations=options.iterations, cell_surface=pcr.numpy2pcr(pcr.Scalar, cell_surface_tile, -9999), logging=logger, order=hand_strahler, neg_HAND=options.neg_HAND, ) # 1166400000. # use maximum value of inundation_pcr_step and new inundation for higher strahler order inundation_pcr = pcr.max(inundation_pcr, inundation_pcr_step) 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 if options.out_format == 0: band_inun.WriteArray(inundation_cut, x_start, y_start) band_inun.FlushCache() else: # with netCDF, data is up-side-down. inun_lib.write_tile_nc(band_inun, inundation_cut, x_start, y_start) # clean up os.unlink(flood_vol_temp_file) os.unlink(drainage_temp_file) os.unlink(hand_temp_file) os.unlink( stream_temp_file ) # also remove temp stream file from output folder # 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) if options.out_format == 0: ds_inun = None ds_hand = None else: ds_inun.close() 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)
#-maps: clone map and cell area clone= pcr.readmap(os.path.join(mapsDir,'cloneAfrica.map')) #-set sample domain xMin= -25.5 xMax= 57.5 yMin= -35.0 yMax= 37.5 sampleResolution= 0.5 resampleRatio= 1. #-class to clip map during read clippedRead= pcrPartialRead(xMin,xMax,yMin,yMax,sampleResolution,resampleRatio,clone) cellAreaMap= os.path.join(mapsDir,'cellarea30.map') cellArea= clippedRead.get(cellAreaMap,'scalar') #-channel and floodplain characteristics LDDMap= os.path.join(mapsDir,'lddsound_30min.map') LDD= pcr.lddrepair(clippedRead.get(LDDMap,'ldd')) channelGradient= clippedRead.get(os.path.join(mapsDir,'globalgradchannel.map')) channelWidth= clippedRead.get(os.path.join(mapsDir,'channel_width.map')) channelLength= clippedRead.get(os.path.join(mapsDir,'channel_length.map')) channelDepth= clippedRead.get(os.path.join(mapsDir,'channel_depth.map')) floodplainMask= pcr.spatial(pcr.boolean(1)) # NOTE: set to zero for static, to one for dynamic floodplains channelManN= 0.04 floodplainManN= 0.10 #-flood plain parameterization #-root of file name with maps of relative elvation above floodplain # and associated fractions relZFileName= 'elev%04d.map' areaFractions=[0.0,0.01,0.05,0.10,0.20,0.30,0.40,\ 0.50,0.60,0.70,0.80,0.90,1.00] # reduction parameter of smoothing interval and error threshold reductionKK= 0.5
print("") print(cmd) os.system(cmd) print("") input_files['averageClimatologyDischargeMonthAvg'] = out_file # set the pcraster clone, ldd, landmask, and cell area map msg = "Setting the clone, ldd, landmask, and cell area maps" + ":" logger.info(msg) # - clone clone_map_file = input_files['clone_map_05min'] pcr.setclone(clone_map_file) # - ldd ldd = vos.readPCRmapClone(input_files['ldd_map_05min'], clone_map_file, output_files['tmp_folder'], None, True) ldd = pcr.lddrepair(pcr.ldd(ldd)) ldd = pcr.lddrepair(ldd) # - landmask landmask = pcr.ifthen(pcr.defined(ldd), pcr.boolean(1.0)) # - cell area cell_area = vos.readPCRmapClone(input_files['cell_area_05min'], clone_map_file, output_files['tmp_folder']) # set the basin map msg = "Setting the basin map" + ":" logger.info(msg) basin_map = pcr.nominal(\ vos.readPCRmapClone(input_files['basin_map_05min'], input_files['clone_map_05min'], output_files['tmp_folder'], None, False, None, True))
pitsDict = {13 : [13,3153], 28 : [28,3515]} lddOld = pcr.readmap('/home/straa005/LDD/lddOutput/ldd_HydroSHEDS_Hydro1k_5min.map') lddDiff = pcr.scalar(ldd) - pcr.scalar(lddOld) pcr.report(pcr.boolean(lddDiff), 'lddDiff.map') p ############################### main ################################### ldd = pcr.nominal(ldd) ldd = fillMVBoundingBox(ldd, 1, 57, 76, 26, 47) ldd = fillMVBoundingBox(ldd, 1, 58, 62, 51, 60) ldd = fillMVBoundingBox(ldd, 1, -108, -101, 31, 40) ldd = pcr.lddrepair(pcr.ldd(ldd)) pits = pcr.pit(ldd) pcr.setglobaloption('unitcell') continentMasks = pcr.cover(mask48, pcr.windowmajority(mask48,5)) #- adjust area masks with 5 min ldd continentMasksNew = pcr.ifthen(pcr.boolean(pcr.readmap(cloneMap)) == 0, pcr.scalar(1)) for i in areas[0:]: print 'area mask = ', i mask = pcr.ifthen(continentMasks == i, pcr.boolean(1)) pitsContinent = pcr.pcrand(mask, pcr.boolean(pits)) pitsContinent = pcr.nominal(pcr.uniqueid(pcr.ifthen(pitsContinent == 1, pcr.boolean(1)))) catchments = pcr.catchment(ldd, pitsContinent) newMask = pcr.ifthen(pcr.boolean(catchments) == 1, pcr.scalar(i))
msg = "Set the landmask to : " + str(landmask_map_file) logger.info(msg) landmask = pcr.readmap(landmask_map_file) # resampling low resolution ldd map msg = "Resample the low resolution ldd map." logger.info(msg) ldd_map_low_resolution_file_name = "/projects/0/dfguu/data/hydroworld/PCRGLOBWB20/input5min/routing/lddsound_05min.map" ldd_map_low_resolution = vos.readPCRmapClone(ldd_map_low_resolution_file_name, \ clone_map_file, \ tmp_folder, \ None, True, None, False) ldd_map_low_resolution = pcr.ifthen( landmask, ldd_map_low_resolution) # NOTE THAT YOU MAY NOT HAVE TO MASK-OUT THE LDD. ldd_map_low_resolution = pcr.lddrepair(pcr.ldd(ldd_map_low_resolution)) ldd_map_low_resolution = pcr.lddrepair(ldd_map_low_resolution) pcr.report(ldd_map_low_resolution, "resampled_low_resolution_ldd.map") # permanent water bodies files (at 5 arc-minutes resolution) reservoir_capacity_file = "/projects/0/dfguu/data/hydroworld/PCRGLOBWB20/input5min/routing/reservoirs/waterBodiesFinal_version15Sept2013/maps/reservoircapacity_2010.map" fracwat_file = "/projects/0/dfguu/data/hydroworld/PCRGLOBWB20/input5min/routing/reservoirs/waterBodiesFinal_version15Sept2013/maps/fracwat_2010.map" water_body_id_file = "/projects/0/dfguu/data/hydroworld/PCRGLOBWB20/input5min/routing/reservoirs/waterBodiesFinal_version15Sept2013/maps/waterbodyid_2010.map" # cell_area_file cell_area_file = "/projects/0/dfguu/data/hydroworld/PCRGLOBWB20/input5min/routing/cellsize05min.correct.map" # read all extreme value maps (low resolution maps), resample them, and save them to the output folder msg = "Resampling extreme value maps." logger.info(msg) file_names = [
def evaluateAllBaseflowResults(self,globalCloneMapFileName,\ catchmentClassFileName,\ lddMapFileName,\ cellAreaMapFileName,\ pcrglobwb_output,\ analysisOutputDir="",\ tmpDir = None): # temporary directory if tmpDir == None: tmpDir = self.tmpDir+"/edwin_iwmi_" # output directory for all analyses for all stations analysisOutputDir = str(analysisOutputDir) self.chartOutputDir = analysisOutputDir+"/chart/" self.tableOutputDir = analysisOutputDir+"/table/" # if analysisOutputDir == "": self.chartOutputDir = "chart/" if analysisOutputDir == "": self.tableOutputDir = "table/" # # make the chart and table directories: os.system('rm -r '+self.chartOutputDir+"*") os.system('rm -r '+self.tableOutputDir+"*") os.makedirs(self.chartOutputDir) os.makedirs(self.tableOutputDir) # cloneMap for all pcraster operations pcr.setclone(globalCloneMapFileName) cloneMap = pcr.boolean(1) lddMap = pcr.lddrepair(pcr.readmap(lddMapFileName)) cellArea = pcr.scalar(pcr.readmap(cellAreaMapFileName)) # The landMaskClass map contains the nominal classes for all landmask regions. landMaskClass = pcr.nominal(cloneMap) # default: if catchmentClassFileName is not given if catchmentClassFileName != None: landMaskClass = pcr.nominal(pcr.readmap(catchmentClassFileName)) for id in self.list_of_grdc_ids: logger.info("Evaluating simulated annual baseflow time series to IWMI baseflow time series at "+str(self.attributeGRDC["id_from_grdc"][str(id)])+".") # evaluate model results to GRDC data self.evaluateBaseflowResult(str(id),pcrglobwb_output,catchmentClassFileName,tmpDir) # write the summary to a table summary_file = analysisOutputDir+"baseflow_summary.txt" # logger.info("Writing the summary for all stations to the file: "+str(summary_file)+".") # # prepare the file: summary_file_handle = open(summary_file,"w") # # write the header summary_file_handle.write( ";".join(self.grdc_dict_keys)+"\n") # # write the content for id in self.list_of_grdc_ids: rowLine = "" for key in self.grdc_dict_keys: rowLine += str(self.attributeGRDC[key][str(id)]) + ";" rowLine = rowLine[0:-1] + "\n" summary_file_handle.write(rowLine) summary_file_handle.close()
def initial(self): """ initial part of the routing module """ maskinfo = MaskInfo.instance() self.var.avgdis = maskinfo.in_zero() self.var.Beta = loadmap('beta') self.var.InvBeta = 1 / self.var.Beta # Inverse of beta for kinematic wave self.var.ChanLength = loadmap('ChanLength').astype(float) self.var.InvChanLength = 1 / self.var.ChanLength # Inverse of channel length [1/m] self.var.NoRoutSteps = int( np.maximum(1, round(self.var.DtSec / self.var.DtSecChannel, 0))) # Number of sub-steps based on value of DtSecChannel, # or 1 if DtSec is smaller than DtSecChannel settings = LisSettings.instance() option = settings.options if option['InitLisflood']: self.var.NoRoutSteps = 1 # InitLisflood is used! # so channel routing step is the same as the general time step self.var.DtRouting = self.var.DtSec / self.var.NoRoutSteps # Corresponding sub-timestep (seconds) self.var.InvDtRouting = 1 / self.var.DtRouting self.var.InvNoRoutSteps = 1 / float(self.var.NoRoutSteps) # inverse for faster calculation inside the dynamic section # -------------------------- LDD self.var.Ldd = lddmask(loadmap('Ldd', pcr=True, lddflag=True), self.var.MaskMap) # Cut ldd to size of MaskMap (NEW, 29/9/2004) # Prevents 'unsound' ldd if MaskMap covers sub-area of ldd # Count (inverse of) upstream area for each pixel # Needed if we want to calculate average values of variables # upstream of gauge locations self.var.UpArea = accuflux(self.var.Ldd, self.var.PixelAreaPcr) # Upstream contributing area for each pixel # Note that you might expext that values of UpArea would be identical to # those of variable CatchArea (see below) at the outflow points. # This is NOT actually the case, because outflow points are shifted 1 # cell in upstream direction in the calculation of CatchArea! self.var.InvUpArea = 1 / self.var.UpArea # Calculate inverse, so we can multiply in dynamic (faster than divide) self.var.IsChannelPcr = boolean(loadmap('Channels', pcr=True)) self.var.IsChannel = np.bool8(compressArray(self.var.IsChannelPcr)) # Identify channel pixels self.var.IsChannelKinematic = self.var.IsChannel.copy() # Identify kinematic wave channel pixels # (identical to IsChannel, unless dynamic wave is used, see below) #self.var.IsStructureKinematic = pcraster.boolean(0) self.var.IsStructureKinematic = np.bool8(maskinfo.in_zero()) # Map that identifies special inflow/outflow structures (reservoirs, lakes) within the # kinematic wave channel routing. Set to (dummy) value of zero modified in reservoir and lake # routines (if those are used) LddChan = lddmask(self.var.Ldd, self.var.IsChannelPcr) # ldd for Channel network self.var.MaskMap = boolean(self.var.Ldd) # Use boolean version of Ldd as calculation mask # (important for correct mass balance check # any water generated outside of Ldd won't reach # channel anyway) self.var.LddToChan = lddrepair( ifthenelse(self.var.IsChannelPcr, 5, self.var.Ldd)) # Routing of runoff (incl. ground water)en AtOutflow = boolean(pit(self.var.Ldd)) # find outlet points... if option['dynamicWave']: IsChannelDynamic = boolean(loadmap('ChannelsDynamic', pcr=True)) # Identify channel pixels where dynamic wave is used self.var.IsChannelKinematic = (self.var.IsChannelPcr == 1) & (IsChannelDynamic == 0) # Identify (update) channel pixels where kinematic wave is used self.var.LddKinematic = lddmask(self.var.Ldd, self.var.IsChannelKinematic) # Ldd for kinematic wave: ends (pit) just before dynamic stretch LddDynamic = lddmask(self.var.Ldd, IsChannelDynamic) # Ldd for dynamic wave # Following statements produce an ldd network that connects the pits in # LddKinematic to the nearest downstream dynamic wave pixel LddToDyn = lddrepair(ifthenelse(IsChannelDynamic, 5, self.var.Ldd)) # Temporary ldd: flow paths end in dynamic pixels PitsKinematic = cover(boolean(pit(self.var.LddKinematic)), 0) # Define start of each flow path at pit on LddKinematic PathKinToDyn = path(LddToDyn, PitsKinematic) # Identify paths that connect pits in LddKinematic to dynamic wave # pixels LddKinToDyn = lddmask(LddToDyn, PathKinToDyn) # Create ldd DynWaveBoundaryCondition = boolean(pit(LddDynamic)) # NEW 12-7-2005 (experimental) # Location of boundary condition dynamic wave self.var.AtLastPoint = (downstream( self.var.Ldd, AtOutflow) == 1) & (AtOutflow != 1) & self.var.IsChannelPcr # NEW 23-6-2005 # Dynamic wave routine gives no outflow out of pits, so we calculate this # one cell upstream (WvD) # (implies that most downstream cell is not taken into account in mass balance # calculations, even if dyn wave is not used) # Only include points that are on a channel (otherwise some small 'micro-catchments' # are included, for which the mass balance cannot be calculated # properly) else: self.var.LddKinematic = LddChan # No dynamic wave, so kinematic ldd equals channel ldd self.var.AtLastPoint = AtOutflow self.var.AtLastPointC = np.bool8( compressArray(self.var.AtLastPoint)) # assign unique identifier to each of them maskinfo = MaskInfo.instance() lddC = compressArray(self.var.LddKinematic) inAr = decompress(np.arange(maskinfo.info.mapC[0], dtype="int32")) # giving a number to each non missing pixel as id self.var.downstruct = (compressArray( downstream(self.var.LddKinematic, inAr))).astype("int32") # each upstream pixel gets the id of the downstream pixel self.var.downstruct[lddC == 5] = maskinfo.info.mapC[0] # all pits gets a high number #d3=np.bincount(self.var.down, weights=loadmap('AvgDis'))[:-1] # upstream function in numpy OutflowPoints = nominal(uniqueid(self.var.AtLastPoint)) # and assign unique identifier to each of them self.var.Catchments = (compressArray( catchment(self.var.Ldd, OutflowPoints))).astype(np.int32) CatchArea = np.bincount( self.var.Catchments, weights=self.var.PixelArea)[self.var.Catchments] #CatchArea = CatchArea[self.var.Catchments] # define catchment for each outflow point #CatchArea = areatotal(self.var.PixelArea, self.var.Catchments) # Compute area of each catchment [m2] # Note: in earlier versions this was calculated using the "areaarea" function, # changed to "areatotal" in order to enable handling of grids with spatially # variable cell areas (e.g. lat/lon grids) self.var.InvCatchArea = 1 / CatchArea # inverse of catchment area [1/m2] # ************************************************************ # ***** CHANNEL GEOMETRY ************************************ # ************************************************************ self.var.ChanGrad = np.maximum(loadmap('ChanGrad'), loadmap('ChanGradMin')) # avoid calculation of Alpha using ChanGrad=0: this creates MV! self.var.CalChanMan = loadmap('CalChanMan') self.var.ChanMan = self.var.CalChanMan * loadmap('ChanMan') # Manning's n is multiplied by ChanManCal # enables calibration for peak timing self.var.ChanBottomWidth = loadmap('ChanBottomWidth') ChanDepthThreshold = loadmap('ChanDepthThreshold') ChanSdXdY = loadmap('ChanSdXdY') self.var.ChanUpperWidth = self.var.ChanBottomWidth + 2 * ChanSdXdY * ChanDepthThreshold # Channel upper width [m] self.var.TotalCrossSectionAreaBankFull = 0.5 * \ ChanDepthThreshold * (self.var.ChanUpperWidth + self.var.ChanBottomWidth) # Area (sq m) of bank full discharge cross section [m2] # (trapezoid area equation) TotalCrossSectionAreaHalfBankFull = 0.5 * self.var.TotalCrossSectionAreaBankFull # Cross-sectional area at half bankfull [m2] # This can be used to initialise channel flow (see below) TotalCrossSectionAreaInitValue = loadmap( 'TotalCrossSectionAreaInitValue') self.var.TotalCrossSectionArea = np.where( TotalCrossSectionAreaInitValue == -9999, TotalCrossSectionAreaHalfBankFull, TotalCrossSectionAreaInitValue) # Total cross-sectional area [m2]: if initial value in binding equals -9999 the value at half bankfull is used, # otherwise TotalCrossSectionAreaInitValue (typically end map from previous simulation) if option['SplitRouting']: # in_zero = maskinfo.in_zero() CrossSection2AreaInitValue = loadmap('CrossSection2AreaInitValue') self.var.CrossSection2Area = np.where( CrossSection2AreaInitValue == -9999, maskinfo.in_zero(), CrossSection2AreaInitValue) # cross-sectional area [m2] for 2nd line of routing: if initial value in binding equals -9999 the value is set to 0 # otherwise CrossSection2AreaInitValue (typically end map from previous simulation) PrevSideflowInitValue = loadmap('PrevSideflowInitValue') self.var.Sideflow1Chan = np.where(PrevSideflowInitValue == -9999, maskinfo.in_zero(), PrevSideflowInitValue) # sideflow from previous run for 1st line of routing: if initial value in binding equals -9999 the value is set to 0 # otherwise PrevSideflowInitValue (typically end map from previous simulation) # ************************************************************ # ***** CHANNEL ALPHA (KIN. WAVE)***************************** # ************************************************************ # Following calculations are needed to calculate Alpha parameter in kinematic # wave. Alpha currently fixed at half of bankful depth (this may change in # future versions!) ChanWaterDepthAlpha = np.where(self.var.IsChannel, 0.5 * ChanDepthThreshold, 0.0) # Reference water depth for calculation of Alpha: half of bankfull self.var.ChanWettedPerimeterAlpha = self.var.ChanBottomWidth + 2 * \ np.sqrt(np.square(ChanWaterDepthAlpha) + np.square(ChanWaterDepthAlpha * ChanSdXdY)) # Channel wetted perimeter [m](Pythagoras) AlpTermChan = (self.var.ChanMan / (np.sqrt(self.var.ChanGrad)))**self.var.Beta self.var.AlpPow = 2.0 / 3.0 * self.var.Beta self.var.ChannelAlpha = ( AlpTermChan * (self.var.ChanWettedPerimeterAlpha**self.var.AlpPow)).astype(float) self.var.InvChannelAlpha = 1 / self.var.ChannelAlpha # ChannelAlpha for kinematic wave # ************************************************************ # ***** CHANNEL INITIAL DISCHARGE **************************** # ************************************************************ self.var.ChanM3 = self.var.TotalCrossSectionArea * self.var.ChanLength # channel water volume [m3] self.var.ChanIniM3 = self.var.ChanM3.copy() self.var.ChanM3Kin = self.var.ChanIniM3.copy().astype(float) # Initialise water volume in kinematic wave channels [m3] self.var.ChanQKin = np.where(self.var.ChannelAlpha > 0, (self.var.TotalCrossSectionArea / self.var.ChannelAlpha)**self.var.InvBeta, 0).astype(float) # Initialise discharge at kinematic wave pixels (note that InvBeta is # simply 1/beta, computational efficiency!) self.var.CumQ = maskinfo.in_zero() # ininialise sum of discharge to calculate average # ************************************************************ # ***** CHANNEL INITIAL DYNAMIC WAVE ************************* # ************************************************************ if option['dynamicWave']: pass # TODO !!!!!!!!!!!!!!!!!!!! # lookchan = lookupstate(TabCrossSections, ChanCrossSections, ChanBottomLevel, self.var.ChanLength, # DynWaveConstantHeadBoundary + ChanBottomLevel) # ChanIniM3 = ifthenelse(AtOutflow, lookchan, ChanIniM3) # Correct ChanIniM3 for constant head boundary in pit (only if # dynamic wave is used) # ChanM3Dyn = ChanIniM3 # Set volume of water in dynamic wave channel to initial value # (note that initial condition is expressed as a state in [m3] for the dynamic wave, # and as a rate [m3/s] for the kinematic wave (a bit confusing) # Estimate number of iterations needed in first time step (based on Courant criterium) # TO DO !!!!!!!!!!!!!!!!!!!! # Potential = lookuppotential( # TabCrossSections, ChanCrossSections, ChanBottomLevel, self.var.ChanLength, ChanM3Dyn) # Potential # WaterLevelDyn = Potential - ChanBottomLevel # Water level [m above bottom level) # WaveCelerityDyn = pcraster.sqrt(9.81 * WaterLevelDyn) # Dynamic wave celerity [m/s] # CourantDynamic = self.var.DtSec * \ # (WaveCelerityDyn + 2) / self.var.ChanLength # Courant number for dynamic wave # We don't know the water velocity at this time so # we just guess it's 2 m/s (Odra tests show that flow velocity # is typically much lower than wave celerity, and 2 m/s is quite # high already so this gives a pretty conservative/safe estimate # for DynWaveIterations) # DynWaveIterationsTemp = max( # 1, roundup(CourantDynamic / CourantDynamicCrit)) # DynWaveIterations = ordinal(mapmaximum(DynWaveIterationsTemp)) # Number of sub-steps needed for required numerical # accuracy. Always greater than or equal to 1 # (otherwise division by zero!) # TEST # If polder option is used, we need an estimate of the initial channel discharge, but we don't know this # for the dynamic wave pixels (since only initial state is known)! Try if this works (dyn wave flux based on zero inflow 1 iteration) # Note that resulting ChanQ is ONLY used in the polder routine!!! # Since we need instantaneous estimate at start of time step, a # ChanQM3Dyn is calculated for one single one-second time step!!! # ChanQDyn = dynwaveflux(TabCrossSections, # ChanCrossSections, # LddDynamic, # ChanIniM3, # 0.0, # ChanBottomLevel, # self.var.ChanMan, # self.var.ChanLength, # 1, # 1, # DynWaveBoundaryCondition) # Compute volume and discharge in channel after dynamic wave # ChanM3Dyn in [cu m] # ChanQDyn in [cu m / s] # self.var.ChanQ = ifthenelse( # IsChannelDynamic, ChanQDyn, self.var.ChanQKin) # Channel discharge: combine results of kinematic and dynamic wave else: # ***** NO DYNAMIC WAVE ************************* # Dummy code if dynamic wave is not used, in which case ChanQ equals ChanQKin # (needed only for polder routine) PrevDischarge = loadmap('PrevDischarge') self.var.ChanQ = np.where(PrevDischarge == -9999, self.var.ChanQKin, PrevDischarge) # initialise channel discharge: cold start: equal to ChanQKin # [m3/s] # Initialising cumulative output variables # These are all needed to compute the cumulative mass balance error self.var.DischargeM3Out = maskinfo.in_zero() # cumulative discharge at outlet [m3] self.var.TotalQInM3 = maskinfo.in_zero() # cumulative inflow from inflow hydrographs [m3] #self.var.sumDis = maskinfo.in_zero() self.var.sumDis = maskinfo.in_zero() self.var.sumIn = maskinfo.in_zero()
def __init__(self, modelTime, input_file, output_file, variable_name, variable_unit): DynamicModel.__init__(self) self.modelTime = modelTime # netcdf input file - based on PCR-GLOBWB output self.input_file = "/projects/0/dfguu/users/edwin/pcr-globwb-aqueduct/historical/1951-2005/gfdl-esm2m/temperature_annuaAvg_output_%s-12-31_to_%s-12-31.nc" self.input_file = input_file # output file - in netcdf format self.output_file = output_folder + "/mekong/basin_temperature_annuaAvg_output.nc" self.output_file = output_file # output variable name and unit self.variable_name = variable_name self.variable_unit = variable_unit # preparing temporary directory self.temporary_directory = output_folder + "/tmp/" os.makedirs(self.temporary_directory) # clone and landmask maps logger.info("Set the clone and landmask maps.") self.clonemap_file_name = "/projects/0/dfguu/users/edwinhs/data/mekong_etc_clone/version_2018-10-22/final/clone_mekong.map" pcr.setclone(self.clonemap_file_name) landmask_file_name = "/projects/0/dfguu/users/edwinhs/data/mekong_etc_clone/version_2018-10-22/final/mask_mekong.map" self.landmask = vos.readPCRmapClone(landmask_file_name, \ self.clonemap_file_name, \ self.temporary_directory, \ None, False, None, True) # pcraster input files # - river network map and sub-catchment map ldd_file_name = "/projects/0/dfguu/data/hydroworld/PCRGLOBWB20/input5min/routing/lddsound_05min.map" # - cell area (unit: m2) cell_area_file_name = "/projects/0/dfguu/data/hydroworld/PCRGLOBWB20/input5min/routing/cellsize05min.correct.map" # loading pcraster input maps self.ldd_network = vos.readPCRmapClone(ldd_file_name, \ self.clonemap_file_name, \ self.temporary_directory, \ None, \ True) self.ldd_network = pcr.lddrepair(pcr.ldd(self.ldd_network)) self.ldd_network = pcr.lddrepair(self.ldd_network) self.cell_area = vos.readPCRmapClone(cell_area_file_name, \ self.clonemap_file_name, \ self.temporary_directory, \ None) # set/limit all input maps to the defined landmask self.ldd_network = pcr.ifthen(self.landmask, self.ldd_network) self.cell_area = pcr.ifthen(self.landmask, self.cell_area) # calculate basin/catchment area self.basin_area = pcr.catchmenttotal(self.cell_area, self.ldd_network) self.basin_area = pcr.ifthen(self.landmask, self.basin_area) # preparing an object for reporting netcdf files: self.netcdf_report = netcdf_writer.PCR2netCDF(self.clonemap_file_name) # preparing netcdf output files: self.netcdf_report.createNetCDF(self.output_file, \ self.variable_name, \ self.variable_unit)
def initial(self): """ initial part of the water abstraction module """ # self.testmap=windowaverage(self.var.Elevation,5) # self.report(self.testmap,"test.map") # ************************************************************ # ***** WATER USE # ************************************************************ settings = LisSettings.instance() option = settings.options binding = settings.binding maskinfo = MaskInfo.instance() if option['wateruse']: self.var.WUsePercRemain = loadmap('WUsePercRemain') self.var.NoWaterUseSteps = int(loadmap('maxNoWateruse')) self.var.GroundwaterBodies = loadmap('GroundwaterBodies') self.var.FractionGroundwaterUsed = np.minimum( np.maximum(loadmap('FractionGroundwaterUsed'), maskinfo.in_zero()), 1.0) self.var.FractionNonConventionalWaterUsed = loadmap( 'FractionNonConventionalWaterUsed') self.var.FractionLakeReservoirWaterUsed = loadmap( 'FractionLakeReservoirWaterUsed') self.var.EFlowThreshold = loadmap('EFlowThreshold') # EFlowThreshold is map with m3/s discharge, e.g. the 10th percentile discharge of the baseline run self.var.WUseRegionC = loadmap('WUseRegion').astype(int) self.var.IrrigationMult = loadmap('IrrigationMult') # ************************************************************ # ***** water use constant maps ****************************** # ************************************************************ self.var.IndustryConsumptiveUseFraction = loadmap( 'IndustryConsumptiveUseFraction') # fraction (0-1) self.var.WaterReUseFraction = loadmap('WaterReUseFraction') # fraction of water re-used (0-1) self.var.EnergyConsumptiveUseFraction = loadmap( 'EnergyConsumptiveUseFraction') # fraction (0-1), value depends on cooling technology of power plants self.var.LivestockConsumptiveUseFraction = loadmap( 'LivestockConsumptiveUseFraction') # fraction (0-1) self.var.LeakageFraction = np.minimum( np.maximum( loadmap('LeakageFraction') * (1 - loadmap('LeakageReductionFraction')), maskinfo.in_zero()), 1.0) self.var.DomesticLeakageConstant = np.minimum( np.maximum(1 / (1 - self.var.LeakageFraction), maskinfo.in_zero()), 1.0) # Domestic Water Abstraction becomes larger in case of leakage # LeakageFraction is LeakageFraction (0-1) multiplied by reduction scenario (10% reduction is 0.1 in map) # 0.65 leakage and 0.1 reduction leads to 0.585 effective leakage, resulting in 2.41 times more water abstraction self.var.DomesticWaterSavingConstant = np.minimum( np.maximum(1 - loadmap('WaterSavingFraction'), maskinfo.in_zero()), 1.0) # Domestic water saving if in place, changes this value from 1 to a value between 0 and 1, and will reduce demand and abstraction # so value = 0.9 if WaterSavingFraction equals 0.1 (10%) self.var.DomesticConsumptiveUseFraction = loadmap( 'DomesticConsumptiveUseFraction') # fraction (0-1), typically rather low ~ 0.10 self.var.LeakageWaterLossFraction = loadmap('LeakageWaterLoss') # fraction (0-1), 0=no leakage # Initialize water demand. Read from a static map either value or pcraster map or netcdf (single or stack). # If reading from NetCDF stack, get time step corresponding to model step. # Added management for sub-daily modelling time steps # Added possibility to use one single average year to be repeated during the simulation if option['useWaterDemandAveYear']: # CM: using one water demand average year throughout the model simulation self.var.DomesticDemandMM = loadmap( 'DomesticDemandMaps', timestampflag='closest', averageyearflag=True) * self.var.DtDay self.var.IndustrialDemandMM = loadmap( 'IndustrialDemandMaps', timestampflag='closest', averageyearflag=True) * self.var.DtDay self.var.LivestockDemandMM = loadmap( 'LivestockDemandMaps', timestampflag='closest', averageyearflag=True) * self.var.DtDay self.var.EnergyDemandMM = loadmap( 'EnergyDemandMaps', timestampflag='closest', averageyearflag=True) * self.var.DtDay else: # CM: using information on water demand from NetCDF files self.var.DomesticDemandMM = loadmap( 'DomesticDemandMaps', timestampflag='closest') * self.var.DtDay self.var.IndustrialDemandMM = loadmap( 'IndustrialDemandMaps', timestampflag='closest') * self.var.DtDay self.var.LivestockDemandMM = loadmap( 'LivestockDemandMaps', timestampflag='closest') * self.var.DtDay self.var.EnergyDemandMM = loadmap( 'EnergyDemandMaps', timestampflag='closest') * self.var.DtDay # Check consistency with the reference calendar that is read from the precipitation forcing file (global_modules.zusatz.optionBinding) if option['TransientWaterDemandChange'] and option[ 'readNetcdfStack']: for k in ('DomesticDemandMaps', 'IndustrialDemandMaps', 'LivestockDemandMaps', 'EnergyDemandMaps'): with Dataset(binding[k] + '.nc') as nc: cal_type = get_calendar_type(nc) if cal_type != binding['calendar_type']: warnings.warn( calendar_inconsistency_warning( binding[k], cal_type, binding['calendar_type'])) if option['groundwaterSmooth']: self.var.GroundwaterBodiesPcr = decompress( self.var.GroundwaterBodies) self.var.groundwaterCatch = boolean( decompress((self.var.GroundwaterBodies * self.var.Catchments).astype(int))) # nominal(scalar(GroundwaterBodies)*scalar(self.var.Catchments)); # smoothing for groundwater to correct error by using windowtotal, based on groundwater bodies and catchments self.var.LZSmoothRange = loadmap('LZSmoothRange') if option['wateruseRegion']: WUseRegion = nominal(loadmap('WUseRegion', pcr=True)) pitWuse1 = ifthen(self.var.AtLastPoint != 0, boolean(1)) pitWuse1b = ifthen(defined(pitWuse1), WUseRegion) # use every existing pit in the Ldd and number them by the water regions # coastal water regions can have more than one pit per water region pitWuseMax = areamaximum(self.var.UpArea, WUseRegion) pitWuse2 = ifthen(pitWuseMax == self.var.UpArea, WUseRegion) # search outlets in the inland water regions by using the maximum upstream area as criterium pitWuse3 = downstream(self.var.LddStructuresKinematic, WUseRegion) pitWuse3b = ifthen(pitWuse3 != WUseRegion, WUseRegion) # search point where ldd leaves a water region pitWuse = cover(pitWuse1b, pitWuse2, pitWuse3b, nominal(0)) # join all sources of pits LddWaterRegion = lddrepair( ifthenelse(pitWuse == 0, self.var.LddStructuresKinematic, 5)) # create a Ldd with pits at every water region outlet # this results in a interrupted ldd, so water cannot be transfered to the next water region lddC = compressArray(LddWaterRegion) inAr = decompress( np.arange(maskinfo.info.mapC[0], dtype="int32")) # giving a number to each non missing pixel as id self.var.downWRegion = (compressArray( downstream(LddWaterRegion, inAr))).astype(np.int32) # each upstream pixel gets the id of the downstream pixel self.var.downWRegion[lddC == 5] = maskinfo.info.mapC[0] # all pits gets a high number # ************************************************************ # ***** OUTFLOW AND INFLOW POINTS FOR WATER REGIONS ********** # ************************************************************ self.var.WaterRegionOutflowPoints = ifthen( pitWuse != 0, boolean(1)) # outflowpoints to calculate upstream inflow for balances and Water Exploitation Index # both inland outflowpoints to downstream subbasin, and coastal outlets WaterRegionInflow1 = boolean( upstream( self.var.LddStructuresKinematic, cover(scalar(self.var.WaterRegionOutflowPoints), 0))) self.var.WaterRegionInflowPoints = ifthen( WaterRegionInflow1, boolean(1)) # inflowpoints to calculate upstream inflow for balances and Water Exploitation Index else: self.var.downWRegion = self.var.downstruct.copy() self.var.downWRegion = self.var.downWRegion.astype(np.int32) # ************************************************************ # ***** Initialising cumulative output variables ************* # ************************************************************ # These are all needed to compute the cumulative mass balance error self.var.wateruseCum = maskinfo.in_zero() # water use cumulated amount self.var.WUseAddM3Dt = maskinfo.in_zero() self.var.WUseAddM3 = maskinfo.in_zero() self.var.IrriLossCUM = maskinfo.in_zero() # Cumulative irrigation loss [mm] # Cumulative abstraction from surface water [mm] self.var.TotalAbstractionFromSurfaceWaterM3 = maskinfo.in_zero() self.var.TotalAbstractionFromGroundwaterM3 = maskinfo.in_zero() self.var.TotalIrrigationAbstractionM3 = maskinfo.in_zero() self.var.TotalPaddyRiceIrrigationAbstractionM3 = maskinfo.in_zero() self.var.TotalLivestockAbstractionM3 = maskinfo.in_zero() self.var.IrrigationType = loadmap('IrrigationType') self.var.IrrigationEfficiency = loadmap('IrrigationEfficiency') self.var.ConveyanceEfficiency = loadmap('ConveyanceEfficiency') self.var.GroundwaterRegionPixels = np.take( np.bincount(self.var.WUseRegionC, weights=self.var.GroundwaterBodies), self.var.WUseRegionC) self.var.AllRegionPixels = np.take( np.bincount(self.var.WUseRegionC, weights=self.var.GroundwaterBodies * 0.0 + 1.0), self.var.WUseRegionC) self.var.RatioGroundWaterUse = self.var.AllRegionPixels / ( self.var.GroundwaterRegionPixels + 0.01) self.var.FractionGroundwaterUsed = np.minimum( self.var.FractionGroundwaterUsed * self.var.RatioGroundWaterUse, 1 - self.var.FractionNonConventionalWaterUsed) # FractionGroundwaterUsed is a percentage given at national scale # since the water needs to come from the GroundwaterBodies pixels, # the fraction needs correction for the non-Groundwaterbodies; this is done here self.var.EFlowIndicator = maskinfo.in_zero() self.var.ReservoirAbstractionM3 = maskinfo.in_zero() self.var.PotentialSurfaceWaterAvailabilityForIrrigationM3 = maskinfo.in_zero( ) self.var.LakeAbstractionM3 = maskinfo.in_zero() self.var.FractionAbstractedFromChannels = maskinfo.in_zero() self.var.AreatotalIrrigationUseM3 = maskinfo.in_zero() self.var.totalAddM3 = maskinfo.in_zero() self.var.TotalDemandM3 = maskinfo.in_zero()
logger.info(msg) # set the pcraster clone, ldd, landmask, and cell area map msg = "Setting the clone, ldd, landmask, and cell area maps" + ":" logger.info(msg) # - clone clone_map_file = input_files['clone_map_05min'] pcr.setclone(clone_map_file) # - ldd ldd = vos.readPCRmapClone(input_files['ldd_map_05min'], clone_map_file, output_files['tmp_folder'], None, True) ldd = pcr.lddrepair(pcr.ldd(ldd)) ldd = pcr.lddrepair(ldd) # - landmask landmask = pcr.ifthen(pcr.defined(ldd), pcr.boolean(1.0)) # - cell area cell_area = vos.readPCRmapClone(input_files['cell_area_05min'], clone_map_file, output_files['tmp_folder']) # read the hydrological year msg = "Reading the hydrological year types" + ":" logger.info(msg) hydro_year_type = pcr.nominal(\ vos.readPCRmapClone(input_files['hydro_year_05min'], input_files['clone_map_05min'],
def __init__(self, iniItems, landmask, Dir, cloneMap, tmpDir): object.__init__(self) # clone map file names, temporary directory and global/absolute path of input directory self.cloneMap = cloneMap # iniItems.cloneMap self.tmpDir = tmpDir # iniItems.tmpDir self.inputDir = Dir # iniItems.globalOptions['inputDir'] self.landmask = landmask # local drainage direction: self.lddMap = vos.readPCRmapClone( iniItems.get("routingOptions", "lddMap"), self.cloneMap, self.tmpDir, self.inputDir, True, ) self.lddMap = pcr.lddrepair(pcr.ldd(self.lddMap)) self.lddMap = pcr.lddrepair(self.lddMap) # option to activate water balance check self.debugWaterBalance = True if ( configget(iniItems, "routingOptions", "debugWaterBalance", "True") == "False" ): self.debugWaterBalance = False # option to perform a run with only natural lakes (without reservoirs) self.onlyNaturalWaterBodies = False if ( "onlyNaturalWaterBodies" in iniItems._sections["routingOptions"] and configget(iniItems, "routingOptions", "onlyNaturalWaterBodies", "False") == "True" ): logger.info( "Using only natural water bodies identified in the year 1900. All reservoirs in 1900 are assumed as lakes." ) self.onlyNaturalWaterBodies = True self.dateForNaturalCondition = ( "1900-01-01" ) # The run for a natural condition should access only this date. # names of files containing water bodies parameters if configget(iniItems, "routingOptions", "waterBodyInputNC", "None") == str( None ): self.useNetCDF = False self.fracWaterInp = iniItems.get("routingOptions", "fracWaterInp") self.waterBodyIdsInp = iniItems.get("routingOptions", "waterBodyIds") self.waterBodyTypInp = iniItems.get("routingOptions", "waterBodyTyp") self.resMaxCapInp = iniItems.get("routingOptions", "resMaxCapInp") self.resSfAreaInp = iniItems.get("routingOptions", "resSfAreaInp") else: self.useNetCDF = True self.ncFileInp = vos.getFullPath( iniItems.get("routingOptions", "waterBodyInputNC"), self.inputDir ) # minimum width (m) used in the weir formula # TODO: define minWeirWidth based on the GLWD, GRanD database and/or bankfull discharge formula self.minWeirWidth = 10.0 # lower and upper limits at which reservoir release is terminated and # at which reservoir release is equal to long-term average outflow self.minResvrFrac = 0.10 self.maxResvrFrac = 0.75
def evaluateAllModelResults(self,globalCloneMapFileName,\ catchmentClassFileName,\ lddMapFileName,\ cellAreaMapFileName,\ pcrglobwb_output,\ analysisOutputDir="",\ tmpDir = None): # temporary directory if tmpDir == None: tmpDir = self.tmpDir+"/edwin_grdc_" # output directory for all analyses for all stations analysisOutputDir = str(analysisOutputDir) self.chartOutputDir = analysisOutputDir+"/chart/" self.tableOutputDir = analysisOutputDir+"/table/" # if analysisOutputDir == "": self.chartOutputDir = "chart/" if analysisOutputDir == "": self.tableOutputDir = "table/" # # make the chart and table directories: os.system('rm -r '+self.chartOutputDir+"*") os.system('rm -r '+self.tableOutputDir+"*") os.makedirs(self.chartOutputDir) os.makedirs(self.tableOutputDir) # cloneMap for all pcraster operations pcr.setclone(globalCloneMapFileName) cloneMap = pcr.boolean(1) self.cell_size_in_arc_degree = vos.getMapAttributesALL(globalCloneMapFileName)['cellsize'] lddMap = pcr.lddrepair(pcr.readmap(lddMapFileName)) cellArea = pcr.scalar(pcr.readmap(cellAreaMapFileName)) # The landMaskClass map contains the nominal classes for all landmask regions. landMaskClass = pcr.nominal(cloneMap) # default: if catchmentClassFileName is not given if catchmentClassFileName != None: landMaskClass = pcr.nominal(pcr.readmap(catchmentClassFileName)) # model catchment areas and cordinates catchmentAreaAll = pcr.catchmenttotal(cellArea, lddMap) / (1000*1000) # unit: km2 xCoordinate = pcr.xcoordinate(cloneMap) yCoordinate = pcr.ycoordinate(cloneMap) for id in self.list_of_grdc_ids: logger.info("Evaluating simulated discharge to the grdc observation at "+str(self.attributeGRDC["id_from_grdc"][str(id)])+".") # identify model pixel self.identifyModelPixel(tmpDir,catchmentAreaAll,landMaskClass,xCoordinate,yCoordinate,str(id)) # evaluate model results to GRDC data self.evaluateModelResultsToGRDC(str(id),pcrglobwb_output,catchmentClassFileName,tmpDir) # write the summary to a table summary_file = analysisOutputDir+"summary.txt" # logger.info("Writing the summary for all stations to the file: "+str(summary_file)+".") # # prepare the file: summary_file_handle = open(summary_file,"w") # # write the header summary_file_handle.write( ";".join(self.grdc_dict_keys)+"\n") # # write the content for id in self.list_of_grdc_ids: rowLine = "" for key in self.grdc_dict_keys: rowLine += str(self.attributeGRDC[key][str(id)]) + ";" rowLine = rowLine[0:-1] + "\n" summary_file_handle.write(rowLine) summary_file_handle.close()
def main(): try: opts, args = getopt.getopt(sys.argv[1:], "fhC:N:I:s:M:", ['version']) except getopt.error as msg: usage(msg) factor = 1 Verbose = 1 inmaps = True force = False caseName = "thecase" caseNameNew = "thecase_resamp" maxcpu = 4 for o, a in opts: if o == "-C": caseName = a if o == "-N": caseNameNew = a if o == "-s": subcatch = int(a) if o == "-I": inmaps = False if o == "-h": usage() if o == "-f": force = True if o == "-M": maxcpu = int(a) if o == "--version": import wflow print("wflow version: ", wflow.__version__) sys.exit(0) dirs = [ "/intbl/", "/staticmaps/", "/intss/", "/instate/", "/outstate/", "/inmaps/", "/inmaps/clim/", "/intbl/clim/", ] ext_to_copy = ["*.tss", "*.tbl", "*.col", "*.xml"] if os.path.isdir(caseNameNew) and not force: print("Refusing to write into an existing directory:" + caseNameNew) exit() # ddir = [] dirs = [] for (path, thedirs, files) in os.walk(caseName): print(path) dirs.append(path) if not os.path.isdir(caseNameNew): for ddir in dirs: os.makedirs(ddir.replace(caseName, caseNameNew)) for inifile in glob.glob(caseName + "/*.ini"): shutil.copy(inifile, inifile.replace(caseName, caseNameNew)) # read subcatchment map x, y, subcatchmap, FillVal = readMap( os.path.join(caseName, "staticmaps", "wflow_subcatch.map"), "PCRaster") for ddir in dirs: print(ddir) allcmd = [] for mfile in glob.glob(ddir + "/*.map"): if not os.path.exists(mfile.replace(caseName, caseNameNew)): x, y, data, FillVal = readMap(mfile, "PCRaster") try: good = 1 xn, yn, datan = cutMapById(data, subcatchmap, subcatch, x, y, FillVal) except Exception as e: good = 0 print("Skipping: " + mfile + " exception: " + str(e)) if xn.size == 0: good = 0 print("Skipping: " + mfile + " size does not match...") if good: ofile = mfile.replace(caseName, caseNameNew) if data.dtype == np.int32 or data.dtype == np.uint8: writeMap(ofile, "PCRaster", xn, yn, datan.astype(np.int32), FillVal) else: writeMap(ofile, "PCRaster", xn, yn, datan, FillVal) # Assume ldd and repair if (data.dtype == np.uint8 and 'wflow_ldd.map' in mfile): myldd = pcr.ldd(pcr.readmap(ofile)) myldd = pcr.lddrepair(myldd) pcr.report(myldd, ofile) for mfile in glob.glob(ddir + "/*.[0-9][0-9][0-9]"): if not os.path.exists(mfile.replace(caseName, caseNameNew)): x, y, data, FillVal = readMap(mfile, "PCRaster") try: good = 1 xn, yn, datan = cutMapById(data, subcatchmap, subcatch, x, y, FillVal) except Exception as e: good = 0 print("Skipping: " + mfile + " exception: " + str(e)) if xn.size == 0: good = 0 print("Skipping: " + mfile + " size does not match...") if good: ofile = mfile.replace(caseName, caseNameNew) if data.dtype == np.int32 or data.dtype == np.uint8: writeMap(ofile, "PCRaster", xn, yn, datan.astype(np.int32), FillVal) else: writeMap(ofile, "PCRaster", xn, yn, datan, FillVal) for ext in ext_to_copy: for mfile in glob.glob(os.path.join(ddir, ext)): shutil.copy(mfile, mfile.replace(caseName, caseNameNew)) # Copy ini files for mfile in glob.glob(os.path.join(caseName, "*.ini")): shutil.copy(mfile, mfile.replace(caseName, caseNameNew))