sys.exit("Unable to read rule directory %s" % (ruleDir,) ) ruleDir = os.path.abspath(args.ruleDir) if ruleDir: sys.stdout.write(textwrap.fill("Importing landcover reclass rules from %s ..." % (ruleDir,) ) ) sys.stdout.flush() # Copy rules into project directory roadRulePath = os.path.join(ruleDir, RHESSysMetadata.LC_RULE_ROAD) shutil.copy(roadRulePath, projectDirRuleDir) imperviousRulePath = os.path.join(ruleDir, RHESSysMetadata.LC_RULE_IMPERVIOUS) shutil.copy(imperviousRulePath, projectDirRuleDir) landuseRulePath = os.path.join(ruleDir, RHESSysMetadata.LC_RULE_LANDUSE) shutil.copy(landuseRulePath, projectDirRuleDir) stratumRulePath = os.path.join(ruleDir, RHESSysMetadata.LC_RULE_STRATUM) shutil.copy(stratumRulePath, projectDirRuleDir) if args.includeLaiRules: laiRulePath = os.path.join(ruleDir, RHESSysMetadata.LC_RULE_LAI) shutil.copy(laiRulePath, projectDirRuleDir) sys.stdout.write('done\n') # Write metadata RHESSysMetadata.writeRHESSysEntry(context, 'landcover_stratum_rule', os.path.join(RHESSysMetadata.RULES_DIR, os.path.basename(stratumRulePath)) ) RHESSysMetadata.writeRHESSysEntry(context, 'landcover_landuse_rule', os.path.join(RHESSysMetadata.RULES_DIR, os.path.basename(landuseRulePath)) ) RHESSysMetadata.writeRHESSysEntry(context, 'landcover_impervious_rule', os.path.join(RHESSysMetadata.RULES_DIR, os.path.basename(imperviousRulePath)) ) RHESSysMetadata.writeRHESSysEntry(context, 'landcover_road_rule', os.path.join(RHESSysMetadata.RULES_DIR, os.path.basename(roadRulePath)) ) if args.includeLaiRules: RHESSysMetadata.writeRHESSysEntry(context, 'landcover_lai_rule', os.path.join(RHESSysMetadata.RULES_DIR, os.path.basename(laiRulePath)) ) # Write processing history RHESSysMetadata.appendProcessingHistoryItem(context, cmdline)
if RHESSysMetadata.LC_RULE_LAI_COMPAT == os.path.basename( metadata['landcover_lai_rule']): # Compatibility mode, use r.reclass result = grassLib.script.read_command('r.reclass', input=landcoverRast, output='lai', rules=laiRulePath, overwrite=args.overwrite) if None == result: sys.exit("r.reclass failed to create LAI map, returning %s" % (result, )) else: # use r.reclass result = grassLib.script.read_command('r.recode', input=landcoverRast, output='lai', rules=laiRulePath, overwrite=args.overwrite) if None == result: sys.exit("r.reclass failed to create LAI map, returning %s" % (result, )) RHESSysMetadata.writeGRASSEntry(context, 'lai_rast', 'lai') # Write metadata RHESSysMetadata.writeRHESSysEntry(context, 'stratum_defs', True) RHESSysMetadata.writeRHESSysEntry(context, 'landuse_defs', True) # Write processing history RHESSysMetadata.appendProcessingHistoryItem(context, cmdline)
def run(self, *args, **kwargs): """ Run lairead for multiple worldfiles Arguments: topmodel -- boolean Whether to run RHESSys in TOPMODEL model. Default: False. verbose -- boolean Produce verbose output. Default: False. """ verbose = kwargs.get('verbose', False) topmodel = kwargs.get('topmodel', False) self.checkMetadata(topmodel=topmodel) rhessysDir = self.metadata['rhessys_dir'] self.paths = RHESSysPaths(self.context.projectDir, rhessysDir) rhessysBinPath = os.path.join(self.context.projectDir, self.metadata['rhessys_bin']) # Make sure region is properly set demRast = self.grassMetadata['dem_rast'] result = self.grassLib.script.run_command('g.region', rast=demRast) if result != 0: raise RunException("g.region failed to set region to DEM, returning {0}".format(result)) # Run lairead for each worldfile lairead_tecfiles = [] final_worldfiles = [] worldfiles = self.metadata['worldfiles_init'].split(RHESSysMetadata.VALUE_DELIM) masks = self.metadata['subbasin_masks'].split(RHESSysMetadata.VALUE_DELIM) surfaceFlowtables = subsurfaceFlowtables = None if not topmodel: surfaceFlowtables = self.metadata['surface_flowtables'].split(RHESSysMetadata.VALUE_DELIM) subsurfaceFlowtables = self.metadata['subsurface_flowtables'].split(RHESSysMetadata.VALUE_DELIM) for (i, worldfile) in enumerate(worldfiles): worldfilePath = os.path.join(self.context.projectDir, worldfile) worldfileDir = os.path.dirname(worldfilePath) surfaceFlowtable = subsurfaceFlowtable = None if not topmodel: surfaceFlowtable = surfaceFlowtables[i] # Assumption: worldfiles and flowtables lists are in the same order subsurfaceFlowtable = subsurfaceFlowtables[i] # Assumption: worldfiles and flowtables lists are in the same order # Mask to correct mask mask = masks[i] # Assumption: worldfiles and masks lists are in the same order result = self.grassLib.script.run_command('r.mask', flags='o', input=mask, maskcats='1', quiet=True) if result != 0: raise RunException("r.mask failed to set mask to sub-basin {0}, returning {1}".format(mask, result)) ## 1. Determine legal simulation start and date from climate data # Read first climate station from worldfile header = "{0}.hdr".format(worldfile) headerPath = os.path.join(self.context.projectDir, header) stations = getClimateBaseStationFilenames(headerPath) if not len(stations) > 0: raise RunException("No climate stations found in worldfile header {0}".format(headerPath)) firstStationPath = os.path.normpath( os.path.join(self.paths.RHESSYS_DIR, stations[0]) ) if verbose: self.outfp.write("First climate station in worldfile: %s\n" % (firstStationPath,) ) # Read climate timeseries for start and end date, write to metadata (startDate, endDate) = getStartAndEndDateForClimateStation(firstStationPath, self.paths) if verbose: self.outfp.write("start date: %s, end date: %s\n" % ( str(startDate), str(endDate) ) ) fourDays = datetime.timedelta(days=4) if endDate - startDate < fourDays: raise RunException("Climate time-series defined by station %s is too short to run lairead (less than four-days long)" % (firstStationPath,) ) ## 2. Run LAI read to generate redefine worldfile tecDurRedef = datetime.timedelta(days=1) tecRedef = startDate + tecDurRedef laireadPath = os.path.join(self.context.projectDir, self.metadata['lairead_bin']) oldWorldPath = os.path.join(self.context.projectDir, worldfile) redefWorldName = "%s.Y%dM%dD%dH%d" % \ (worldfile, tecRedef.year, tecRedef.month, tecRedef.day, tecRedef.hour) redefWorldPath = os.path.join(self.context.projectDir, redefWorldName) allomPath = os.path.join(self.context.projectDir, self.metadata['allometric_table']) if verbose: self.outfp.write("\nRunning lairead for subbasin {0}...".format(mask)) p = self.grassLib.script.pipe_command(laireadPath, old=oldWorldPath, redef=redefWorldPath, allom=allomPath, lai=self.grassMetadata['lai_rast'], vegid=self.grassMetadata['stratum_rast'], zone=self.grassMetadata['zone_rast'], hill=self.grassMetadata['hillslope_rast'], patch=self.grassMetadata['patch_rast'], mask=mask) (stdoutStr, stderrStr) = p.communicate() result = p.returncode if result != 0: self.outfp.write(stdoutStr) raise RunException("\nlairead failed, returning %s" % (result,)) if verbose: self.outfp.write('done\n') ## 3. Write TEC file for redefining the initial flow table ## Redefine on the second day of the simulation, write output ## on the third day tecName = "tec.lairead_{0}".format(mask) tecPath = os.path.join(self.paths.RHESSYS_TEC, tecName) tecDurOutput = datetime.timedelta(days=2) tecOutput = startDate + tecDurOutput f = open(tecPath, 'w') f.write("%s redefine_world%s" % (datetimeToString(tecRedef), os.linesep) ) f.write("%s output_current_state%s" % (datetimeToString(tecOutput), os.linesep) ) f.close() lairead_tecfiles.append(tecPath) ## 4. Run RHESSys for the first 4 legal days with redefine TEC rhessysStart = startDate rhessysDur = datetime.timedelta(days=3) rhessysEnd = startDate + rhessysDur surfaceFlowtablePath = subSurfaceFlowtablePath = None if not topmodel: surfaceFlowtablePath = os.path.join(self.context.projectDir, surfaceFlowtable) subsurfaceFlowtablePath = os.path.join(self.context.projectDir, subsurfaceFlowtable) rhessysCmd = generateCommandString(rhessysBinPath, None, rhessysStart, rhessysEnd, tecPath, oldWorldPath, surfaceFlowtablePath, subsurfaceFlowtablePath) if verbose: self.outfp.write('\nRunning RHESSys to redefine worldfile with vegetation carbon stores...\n') self.outfp.write(rhessysCmd) self.outfp.write('\n') cmdArgs = rhessysCmd.split() process = Popen(cmdArgs, cwd=self.paths.RHESSYS_DIR, stdout=PIPE, stderr=PIPE) (process_stdout, process_stderr) = process.communicate() if verbose: self.outfp.write(process_stdout) self.outfp.write(process_stderr) if process.returncode != 0: raise RunException("\n\nRHESSys failed, returning %s" % (process.returncode,) ) if verbose: sys.stdout.write('done\n') ## 5. Rename redefine worldfile, write to metadata outputWorldName = "%s.Y%dM%dD%dH%d.state" % \ (worldfile, tecOutput.year, tecOutput.month, tecOutput.day, tecOutput.hour) outputWorldPath = os.path.join(self.context.projectDir, outputWorldName) if not os.access(outputWorldPath, os.W_OK): raise RunException("Unable to find redefined worldfile %s" % (outputWorldPath,) ) newWorldName = "world_{0}".format(mask) newWorldPath = os.path.join(self.paths.RHESSYS_WORLD, newWorldName) shutil.move(outputWorldPath, newWorldPath) if not os.path.exists(newWorldPath): raise RunException("Failed to copy redefined worldfile %s to %s" % (outputWorldPath, newWorldPath) ) final_worldfiles.append(newWorldPath) # Copy world file header from init worldfile to final world file newHeader = "%s.hdr" % (newWorldName,) newHeaderPath = os.path.join(self.paths.RHESSYS_WORLD, newHeader) shutil.copyfile(headerPath, newHeaderPath) if verbose: sys.stdout.write('\n\nSuccessfully used lairead to initialize vegetation carbon stores.\n') # Write metadata RHESSysMetadata.writeRHESSysEntry(self.context, 'worldfiles', RHESSysMetadata.VALUE_DELIM.join([self.paths.relpath(w) for w in final_worldfiles])) RHESSysMetadata.writeRHESSysEntry(self.context, 'lairead_tecfiles', RHESSysMetadata.VALUE_DELIM.join([self.paths.relpath(t) for t in lairead_tecfiles])) RHESSysMetadata.writeRHESSysEntry(self.context, 'lairead_mode_topmodel', str(topmodel)) # Write processing history RHESSysMetadata.appendProcessingHistoryItem(self.context, RHESSysMetadata.getCommandLine())
def run(self, *args, **kwargs): """ Create flow tables for multiple worldfiles Arguments: routeRoads -- boolean Whether road routing should be enabled in createflowpaths. Default: False. routeRoofs -- boolean Whether roof routing should be enabled in createflowpaths. Default: False. ignoreBurnedDEM -- boolean If true, use the base DEM when running createflowpaths. If false, use the stream-burned DEM (if present). Default: False. force -- boolean Whether to force createflowpaths to run if DEM X resolution != Y resolution. Default: False. verbose -- boolean Produce verbose output. Default: False. """ routeRoads = kwargs.get('routeRoads', False) routeRoofs = kwargs.get('routeRoofs', False) force = kwargs.get('force', False) ignoreBurnedDEM = kwargs.get('ignoreBurnedDEM', False) verbose = kwargs.get('verbose', False) self.checkMetadata(routeRoads=routeRoads, routeRoofs=routeRoofs) rhessysDir = self.metadata['rhessys_dir'] self.paths = RHESSysPaths(self.context.projectDir, rhessysDir) demResX = float(self.studyArea['dem_res_x']) demResY = float(self.studyArea['dem_res_y']) if demResX != demResY: self.outfp.write( "DEM x resolution (%f) does not match y resolution (%f)" % (demResX, demResY)) if not force: raise RunException('Exiting. Use force option to override') # Determine DEM raster to use demRast = self.grassMetadata['dem_rast'] if ('stream_burned_dem_rast' in self.grassMetadata) and (not ignoreBurnedDEM): demRast = self.grassMetadata['stream_burned_dem_rast'] self.outfp.write( "Using raster named '%s' to calculate flow direction map\n" % (demRast, )) # Make sure region is properly set demRast = self.grassMetadata['dem_rast'] result = self.grassLib.script.run_command('g.region', rast=demRast) if result != 0: raise RunException( "g.region failed to set region to DEM, returning {0}".format( result)) # Get paths for CF binary and template cfPath = os.path.join(self.context.projectDir, self.metadata['cf_bin']) templatePath = os.path.join(self.context.projectDir, self.metadata['template']) if verbose: self.outfp.write(self.templatePath) self.outfp.write('\n') # Make output file paths and file name templates flowTableNameBase = "world_{mask}" flowOutpath = os.path.join(self.paths.RHESSYS_FLOW, flowTableNameBase) cfOutpath = os.path.join(self.paths.RHESSYS_FLOW, "cf_{mask}.out") roads = None if routeRoads: roads = self.grassMetadata['roads_rast'] else: roads = self.grassMetadata['zero_rast'] roofs = None impervious = None # These filenames are only for metadata if routeRoofs: roofs = self.grassMetadata['roof_connectivity_rast'] impervious = self.grassMetadata['impervious_rast'] surfaceFlowtableTemplate = "world_{mask}_surface.flow" subsurfaceFlowtableTemplate = "world_{mask}_subsurface.flow" else: surfaceFlowtableTemplate = subsurfaceFlowtableTemplate = "world_{mask}.flow" # Make flowtable for each masked region if verbose: self.outfp.write( 'Running createflowpaths (this may take a few minutes)...') self.outfp.flush() surfaceFlowtables = [] subsurfaceFlowtables = [] masks = self.metadata['subbasin_masks'].split( RHESSysMetadata.VALUE_DELIM) for mask in masks: result = self.grassLib.script.run_command('r.mask', flags='o', input=mask, maskcats='1', quiet=True) if result != 0: raise RunException( "r.mask failed to set mask to sub-basin {0}, returning {1}" .format(mask, result)) # Run CF p = self.grassLib.script.pipe_command( cfPath, out=flowOutpath.format(mask=mask), template=templatePath, dem=demRast, slope=self.grassMetadata['slope_rast'], stream=self.grassMetadata['streams_rast'], road=roads, roof=roofs, impervious=impervious, cellsize=demResX) (pStdout, pStderr) = p.communicate() if verbose: self.outfp.write("CF output:\n") self.outfp.write(pStdout) if pStderr: self.outfp.write(pStderr) if p.returncode != 0: raise RunException("createflowpaths failed, returning %s" % (str(p.returncode), )) # Write cf output to project directory cfOut = open(cfOutpath.format(mask=mask), 'w') cfOut.write(pStdout) if pStderr: cfOut.write("\n\nStandard error output:\n\n") cfOut.write(pStderr) cfOut.close() surfFlow = os.path.join(self.paths.RHESSYS_FLOW, surfaceFlowtableTemplate.format(mask=mask)) surfaceFlowtables.append(surfFlow) subsurfFlow = os.path.join( self.paths.RHESSYS_FLOW, subsurfaceFlowtableTemplate.format(mask=mask)) subsurfaceFlowtables.append(subsurfFlow) # Remove mask result = self.grassLib.script.run_command('r.mask', flags='r', quiet=True) if result != 0: raise RunException("r.mask failed to remove mask") # Write metadata cfCmd = "%s out=%s template=%s dem=%s slope=%s stream=%s road=%s roof=%s impervious=%s cellsize=%s" % \ (cfPath, flowOutpath, templatePath, demRast, self.grassMetadata['slope_rast'], self.grassMetadata['streams_rast'], roads, roofs, impervious, demResX) RHESSysMetadata.writeRHESSysEntry(self.context, 'flowtable_cmd', cfCmd) RHESSysMetadata.writeRHESSysEntry( self.context, 'surface_flowtables', RHESSysMetadata.VALUE_DELIM.join( [self.paths.relpath(s) for s in surfaceFlowtables])) RHESSysMetadata.writeRHESSysEntry( self.context, 'subsurface_flowtables', RHESSysMetadata.VALUE_DELIM.join( [self.paths.relpath(s) for s in subsurfaceFlowtables])) if verbose: self.outfp.write('\n\nFinished creating flow tables\n') # Write processing history RHESSysMetadata.appendProcessingHistoryItem( self.context, RHESSysMetadata.getCommandLine())
def run(self, *args, **kwargs): """ Multiple worldfiles, one worldfile for each subbasin delineated. Arguments: verbose -- boolean Produce verbose output. Default: False. """ verbose = kwargs.get('verbose', False) self.checkMetadata() rhessysDir = self.metadata['rhessys_dir'] self.paths = RHESSysPaths(self.context.projectDir, rhessysDir) templateFilename = os.path.basename(self.metadata['template']) templateFilepath = os.path.join(self.context.projectDir, self.metadata['template']) g2wPath = os.path.join(self.context.projectDir, self.metadata['g2w_bin']) # Make sure g2w can find rat g2wEnv = dict(os.environ) g2wEnv['PATH'] = self.paths.RHESSYS_BIN + os.pathsep + g2wEnv['PATH'] # Make sure region is properly set demRast = self.grassMetadata['dem_rast'] result = self.grassLib.script.run_command('g.region', rast=demRast) if result != 0: raise RunException( "g.region failed to set region to DEM, returning {0}".format( result)) # Mask subbasin to basin basin_rast = self.grassMetadata['basin_rast'] result = self.grassLib.script.run_command('r.mask', flags='o', input=basin_rast, maskcats='1', quiet=True) if result != 0: sys.exit("r.mask failed to set mask to basin, returning %s" % (result, )) subbasin_raster = self.grassMetadata['subbasins_rast'] subbasin_mask = "{0}_mask".format(subbasin_raster) mapcalc_input = "{subbasin_mask}={subbasins}".format( subbasin_mask=subbasin_mask, subbasins=subbasin_raster) result = self.grassLib.script.write_command('r.mapcalc', stdin=mapcalc_input, stdout=PIPE, stderr=PIPE) if result != 0: raise RunException( "r.mapcalc failed to generate masked subbasin map {0}, input: {1}" .format(subbasin_raster, mapcalc_input)) # Get list of subbasins result = self.grassLib.script.read_command('r.stats', flags='n', input=subbasin_raster, quiet=True) if result is None or result == '': raise RunException( "Error reading subbasin map {0}".format(subbasin_raster)) subbasins = result.split() subbasin_masks = [] worldfiles = [] for subbasin in subbasins: # Remove mask result = self.grassLib.script.run_command('r.mask', flags='r', quiet=True) if result != 0: raise RunException("r.mask failed to remove mask") # Make a mask layer for the sub-basin mask_name = "subbasin_{0}".format(subbasin) subbasin_masks.append(mask_name) result = self.grassLib.script.write_command( 'r.mapcalc', stdin="{mask_name}={subbasins} == {subbasin_number}".format( mask_name=mask_name, subbasins=subbasin_mask, subbasin_number=subbasin), stdout=PIPE, stderr=PIPE) if result != 0: raise RunException( "r.mapcalc failed to generate mask for subbasin {0}". format(subbasin)) # Mask to the sub-basin result = self.grassLib.script.run_command('r.mask', flags='o', input=mask_name, maskcats='1', quiet=True) if result != 0: raise RunException( "r.mask failed to set mask to sub-basin {0}, returning {1}" .format(mask_name, result)) worldfileName = "world_subbasin_{0}_init".format(subbasin) worldfilePath = os.path.join(self.paths.RHESSYS_WORLD, worldfileName) worldfiles.append(worldfilePath) g2wCommand = "{g2w} -t {template} -w {worldfile}".format( g2w=g2wPath, template=templateFilepath, worldfile=worldfilePath) if verbose: self.outfp.write("{0}\n".format(g2wCommand)) self.outfp.write("\nRunning grass2world from {0}...".format( self.paths.RHESSYS_BIN)) self.outfp.flush() cmdArgs = g2wCommand.split() process = Popen(cmdArgs, cwd=self.paths.RHESSYS_BIN, env=g2wEnv, stdout=PIPE, stderr=PIPE) (process_stdout, process_stderr) = process.communicate() if process.returncode != 0: raise RunException("grass2world failed, returning {0}".format( process.returncode)) if verbose: self.outfp.write(process_stdout) self.outfp.write(process_stderr) # Remove mask result = self.grassLib.script.run_command('r.mask', flags='r', quiet=True) if result != 0: raise RunException("r.mask failed to remove mask") # Write metadata RHESSysMetadata.writeRHESSysEntry( self.context, 'worldfiles_init', RHESSysMetadata.VALUE_DELIM.join( [self.paths.relpath(w) for w in worldfiles])) RHESSysMetadata.writeRHESSysEntry( self.context, 'subbasin_masks', RHESSysMetadata.VALUE_DELIM.join([m for m in subbasin_masks])) if verbose: self.outfp.write('\n\nFinished creating worldfiles\n') # Write processing history RHESSysMetadata.appendProcessingHistoryItem( self.context, RHESSysMetadata.getCommandLine())
def run(self, *args, **kwargs): """ Create flow tables for multiple worldfiles Arguments: scenario_id -- int ID of the GI Notebook scenario whose GI instances are to be parameterized. auth_token -- string Authorization token to use for authenticating to the GI Notebook. host -- string Hostname of GI Notebook server. Default: None. api_root -- string The root of the API URL to use. Default: None. use_HTTPS -- boolean Use HTTPS for communication with the GI Notebook. force -- boolean Force overwrite of existing scenario output. Default: False. verbose -- boolean Produce verbose output. Default: False. """ scenario_id = kwargs.get('scenario_id') if scenario_id is None: raise RunException('Scenario ID was not specified.') auth_token = kwargs.get('auth_token') if auth_token is None: raise RunException('Authorization token was not specified.') host = kwargs.get('host', DEFAULT_HOSTNAME) api_root = kwargs.get('api_path', DEFAULT_API_ROOT) use_HTTPS = kwargs.get('use_HTTPS', False) force = kwargs.get('force', False) verbose = kwargs.get('verbose', False) self.checkMetadata() self.param_const, self.param_db = self._init_paramdb() self.paths = RHESSysPaths(self.context.projectDir, self.metadata['rhessys_dir']) gi_scenario_base = 'gi_scenario' gi_scenario_data = "{0}.geojson".format(gi_scenario_base) scenario_geojson_path = os.path.join(self.context.projectDir, gi_scenario_data) gi_scenario_soils_base = "{0}_wsoils".format(gi_scenario_base) gi_scenario_soils = "{0}.geojson".format(gi_scenario_soils_base) scenario_soils_geojson_path = os.path.join(self.context.projectDir, gi_scenario_soils) gi_scenario_landuse_base = "{0}_landuse".format(gi_scenario_base) gi_scenario_landuse = "{0}.geojson".format(gi_scenario_landuse_base) scenario_landuse_geojson_path = os.path.join(self.context.projectDir, gi_scenario_landuse) gi_scenario_data_key = 'gi_scenario_data' gi_scenario_soils_data_key = "{0}_soils".format(gi_scenario_data_key) gi_scenario_landuse_data_key = "{0}_landuse".format(gi_scenario_data_key) if gi_scenario_data_key in self.metadata: if verbose: self.outfp.write('Existing GI scenario found.\n') if force: if verbose: self.outfp.write('Force option specified, overwriting existing GI scenario.\n') if os.path.exists(scenario_geojson_path): os.unlink(scenario_geojson_path) if os.path.exists(scenario_soils_geojson_path): os.unlink(scenario_soils_geojson_path) if os.path.exists(scenario_landuse_geojson_path): os.unlink(scenario_landuse_geojson_path) else: raise RunException('Exiting. Use force option to overwrite.') if verbose: output = None else: output = open('/dev/null') try: # Connect to GI Notebook and fetch GI instance information (in GeoJSON format) # for this scenario ID. if verbose: self.outfp.write("\nDownloading GI scenario {0} from GI database...\n".format(scenario_id)) nb = GINotebook(hostname=host, api_root=api_root, use_https=use_HTTPS, auth_token=auth_token) scenario = nb.get_scenario(scenario_id) scenario_geojson = scenario.get_instances_as_geojson(indent=2, shorten=True) (gi_scenario_data_wgs84, scenario_geojson_wgs84_path), (gi_scenario_data, scenario_geojson_path) = \ self._write_geojson_and_reproject(scenario_geojson, gi_scenario_base, verbose=verbose, output=output) # Filter out instances that do not contain soils data gi_scenario_soils_base = "{0}_wsoils".format(gi_scenario_base) scenario_geojson_wsoils = scenario.get_instances_as_geojson(indent=2, shorten=True, filter=lambda a: a.get('e_1_pedid') is not None) (gi_scenario_soils_wgs84, scenario_soils_geojson_wgs84_path), (gi_scenario_soils, scenario_soils_geojson_path) = \ self._write_geojson_and_reproject(scenario_geojson_wsoils, gi_scenario_soils_base, verbose=verbose, output=output) # Import scenario GeoJSON into GRASS self._import_vector_into_grass(scenario_geojson_path, gi_scenario_data_key, force=force, verbose=verbose, output=output) # Import scenario (instances with soils data) GeoJSON into GRASS self._import_vector_into_grass(scenario_soils_geojson_path, gi_scenario_soils_data_key, force=force, verbose=verbose, output=output) # Generate raster layers from vector-based GI Scenario # Raster for updating soil type self._rasterize(gi_scenario_soils_data_key, gi_scenario_soils_data_key, column='e_1_pedid', labelcolumn='e_1_pednm', rast_title='GI soil types', verbose=verbose, force=force, redir_fp=output) # Raster for updating stratum type gi_scenario_strata = "gi_scenario_strata" self._rasterize(gi_scenario_data_key, gi_scenario_strata, column='e_1_vegid', labelcolumn='e_1_vegnm', rast_title='GI vegetation types', verbose=verbose, force=force, redir_fp=output) # Raster for updating land use # Filter out instances that are not rain gardens (i.e. the only GI type for which we currently have a # land use). scenario_geojson_landuse = scenario.get_instances_as_geojson(indent=2, shorten=True, filter=lambda a: a.get('type', '') == 'Rain Garden') (gi_scenario_landuse_wgs84, scenario_landuse_geojson_wgs84_path), \ (gi_scenario_landuse, scenario_landuse_geojson_path) = \ self._write_geojson_and_reproject(scenario_geojson_landuse, gi_scenario_landuse_base, verbose=verbose, output=output) # Import land use (i.e. instances that are rain gardens) GeoJSON into GRASS self._import_vector_into_grass(scenario_landuse_geojson_path, gi_scenario_landuse_data_key, force=force, verbose=verbose, output=output) # Search for raster value for rain gardens in RHESSys parameter DB rg_name = 'raingarden' rg_found = self.param_db.search(self.param_const.SEARCH_TYPE_HIERARCHICAL, 'landuse', rg_name, None, None, None, None, None, None, None, None) if not rg_found: raise RunException("Unable to find raingarden landuse class in parameter database") rg_id = [c[1][2] for c in self.param_db.classes.iteritems()][0] # Generate raster layer from vector-based GI Scenario # Raster for updating landuse type self._rasterize_single_value(gi_scenario_landuse_data_key, gi_scenario_landuse_data_key, value=rg_id, label=rg_name, rast_title='GI landuse types', verbose=verbose, force=force, redir_fp=output) # Write out updated landuse, stratum, and soil rasters and parameter definitions # Backup landuse raster self._backup_raster(self.grassMetadata['landuse_rast']) # Update landuse raster self._update_raster(self.grassMetadata['landuse_rast'], gi_scenario_landuse_data_key) # Generate parameter definition file for landuse raster self._generate_parameter_definitions_for_raster(self.grassMetadata['landuse_rast'], 'landuse', verbose=verbose) # Backup stratum raster self._backup_raster(self.grassMetadata['stratum_rast']) # Update stratum raster self._update_raster(self.grassMetadata['stratum_rast'], gi_scenario_strata) # Generate parameter definition file for stratum raster self._generate_parameter_definitions_for_raster(self.grassMetadata['stratum_rast'], 'stratum', verbose=verbose) # Backup soils raster self._backup_raster(self.grassMetadata['soil_rast']) # Update soils raster self._update_raster(self.grassMetadata['soil_rast'], gi_scenario_soils_data_key) # Generate parameter definition file for soil raster self._generate_parameter_definitions_for_raster(self.grassMetadata['soil_rast'], 'soil', verbose=verbose) # Write metadata RHESSysMetadata.writeGRASSEntry(self.context, "{0}_rast".format(gi_scenario_landuse_data_key), gi_scenario_landuse_data_key) RHESSysMetadata.writeGRASSEntry(self.context, "{0}_rast".format(gi_scenario_soils_data_key), gi_scenario_soils_data_key) RHESSysMetadata.writeGRASSEntry(self.context, "{0}_rast".format(gi_scenario_strata), gi_scenario_strata) RHESSysMetadata.writeGRASSEntry(self.context, "{0}_vect".format(gi_scenario_data_key), gi_scenario_data_key) RHESSysMetadata.writeGRASSEntry(self.context, "{0}_vect".format(gi_scenario_soils_data_key), gi_scenario_soils_data_key) RHESSysMetadata.writeGRASSEntry(self.context, "{0}_vect".format(gi_scenario_landuse_data_key), gi_scenario_landuse_data_key) RHESSysMetadata.writeRHESSysEntry(self.context, gi_scenario_data_key, gi_scenario_data) if verbose: self.outfp.write('\n\nFinished parameterizing GI.\n') # Write processing history RHESSysMetadata.appendProcessingHistoryItem(self.context, RHESSysMetadata.getCommandLine()) finally: if output: output.close()
def run(self, *args, **kwargs): """ Create flow tables for multiple worldfiles Arguments: scenario_id -- int ID of the GI Notebook scenario whose GI instances are to be parameterized. auth_token -- string Authorization token to use for authenticating to the GI Notebook. host -- string Hostname of GI Notebook server. Default: None. api_root -- string The root of the API URL to use. Default: None. use_HTTPS -- boolean Use HTTPS for communication with the GI Notebook. force -- boolean Force overwrite of existing scenario output. Default: False. verbose -- boolean Produce verbose output. Default: False. """ scenario_id = kwargs.get('scenario_id') if scenario_id is None: raise RunException('Scenario ID was not specified.') auth_token = kwargs.get('auth_token') if auth_token is None: raise RunException('Authorization token was not specified.') host = kwargs.get('host', DEFAULT_HOSTNAME) api_root = kwargs.get('api_path', DEFAULT_API_ROOT) use_HTTPS = kwargs.get('use_HTTPS', False) force = kwargs.get('force', False) verbose = kwargs.get('verbose', False) self.checkMetadata() self.param_const, self.param_db = self._init_paramdb() self.paths = RHESSysPaths(self.context.projectDir, self.metadata['rhessys_dir']) gi_scenario_base = 'gi_scenario' gi_scenario_data = "{0}.geojson".format(gi_scenario_base) scenario_geojson_path = os.path.join(self.context.projectDir, gi_scenario_data) gi_scenario_soils_base = "{0}_wsoils".format(gi_scenario_base) gi_scenario_soils = "{0}.geojson".format(gi_scenario_soils_base) scenario_soils_geojson_path = os.path.join(self.context.projectDir, gi_scenario_soils) gi_scenario_landuse_base = "{0}_landuse".format(gi_scenario_base) gi_scenario_landuse = "{0}.geojson".format(gi_scenario_landuse_base) scenario_landuse_geojson_path = os.path.join(self.context.projectDir, gi_scenario_landuse) gi_scenario_data_key = 'gi_scenario_data' gi_scenario_soils_data_key = "{0}_soils".format(gi_scenario_data_key) gi_scenario_landuse_data_key = "{0}_landuse".format( gi_scenario_data_key) if gi_scenario_data_key in self.metadata: if verbose: self.outfp.write('Existing GI scenario found.\n') if force: if verbose: self.outfp.write( 'Force option specified, overwriting existing GI scenario.\n' ) if os.path.exists(scenario_geojson_path): os.unlink(scenario_geojson_path) if os.path.exists(scenario_soils_geojson_path): os.unlink(scenario_soils_geojson_path) if os.path.exists(scenario_landuse_geojson_path): os.unlink(scenario_landuse_geojson_path) else: raise RunException('Exiting. Use force option to overwrite.') if verbose: output = None else: output = open('/dev/null') try: # Connect to GI Notebook and fetch GI instance information (in GeoJSON format) # for this scenario ID. if verbose: self.outfp.write( "\nDownloading GI scenario {0} from GI database...\n". format(scenario_id)) nb = GINotebook(hostname=host, api_root=api_root, use_https=use_HTTPS, auth_token=auth_token) scenario = nb.get_scenario(scenario_id) scenario_geojson = scenario.get_instances_as_geojson(indent=2, shorten=True) (gi_scenario_data_wgs84, scenario_geojson_wgs84_path), (gi_scenario_data, scenario_geojson_path) = \ self._write_geojson_and_reproject(scenario_geojson, gi_scenario_base, verbose=verbose, output=output) # Filter out instances that do not contain soils data gi_scenario_soils_base = "{0}_wsoils".format(gi_scenario_base) scenario_geojson_wsoils = scenario.get_instances_as_geojson( indent=2, shorten=True, filter=lambda a: a.get('e_1_pedid') is not None) (gi_scenario_soils_wgs84, scenario_soils_geojson_wgs84_path), (gi_scenario_soils, scenario_soils_geojson_path) = \ self._write_geojson_and_reproject(scenario_geojson_wsoils, gi_scenario_soils_base, verbose=verbose, output=output) # Import scenario GeoJSON into GRASS self._import_vector_into_grass(scenario_geojson_path, gi_scenario_data_key, force=force, verbose=verbose, output=output) # Import scenario (instances with soils data) GeoJSON into GRASS self._import_vector_into_grass(scenario_soils_geojson_path, gi_scenario_soils_data_key, force=force, verbose=verbose, output=output) # Generate raster layers from vector-based GI Scenario # Raster for updating soil type self._rasterize(gi_scenario_soils_data_key, gi_scenario_soils_data_key, column='e_1_pedid', labelcolumn='e_1_pednm', rast_title='GI soil types', verbose=verbose, force=force, redir_fp=output) # Raster for updating stratum type gi_scenario_strata = "gi_scenario_strata" self._rasterize(gi_scenario_data_key, gi_scenario_strata, column='e_1_vegid', labelcolumn='e_1_vegnm', rast_title='GI vegetation types', verbose=verbose, force=force, redir_fp=output) # Raster for updating land use # Filter out instances that are not rain gardens (i.e. the only GI type for which we currently have a # land use). scenario_geojson_landuse = scenario.get_instances_as_geojson( indent=2, shorten=True, filter=lambda a: a.get('type', '') == 'Rain Garden') (gi_scenario_landuse_wgs84, scenario_landuse_geojson_wgs84_path), \ (gi_scenario_landuse, scenario_landuse_geojson_path) = \ self._write_geojson_and_reproject(scenario_geojson_landuse, gi_scenario_landuse_base, verbose=verbose, output=output) # Import land use (i.e. instances that are rain gardens) GeoJSON into GRASS self._import_vector_into_grass(scenario_landuse_geojson_path, gi_scenario_landuse_data_key, force=force, verbose=verbose, output=output) # Search for raster value for rain gardens in RHESSys parameter DB rg_name = 'raingarden' rg_found = self.param_db.search( self.param_const.SEARCH_TYPE_HIERARCHICAL, 'landuse', rg_name, None, None, None, None, None, None, None, None) if not rg_found: raise RunException( "Unable to find raingarden landuse class in parameter database" ) rg_id = [c[1][2] for c in self.param_db.classes.iteritems()][0] # Generate raster layer from vector-based GI Scenario # Raster for updating landuse type self._rasterize_single_value(gi_scenario_landuse_data_key, gi_scenario_landuse_data_key, value=rg_id, label=rg_name, rast_title='GI landuse types', verbose=verbose, force=force, redir_fp=output) # Write out updated landuse, stratum, and soil rasters and parameter definitions # Backup landuse raster self._backup_raster(self.grassMetadata['landuse_rast']) # Update landuse raster self._update_raster(self.grassMetadata['landuse_rast'], gi_scenario_landuse_data_key) # Generate parameter definition file for landuse raster self._generate_parameter_definitions_for_raster( self.grassMetadata['landuse_rast'], 'landuse', verbose=verbose) # Backup stratum raster self._backup_raster(self.grassMetadata['stratum_rast']) # Update stratum raster self._update_raster(self.grassMetadata['stratum_rast'], gi_scenario_strata) # Generate parameter definition file for stratum raster self._generate_parameter_definitions_for_raster( self.grassMetadata['stratum_rast'], 'stratum', verbose=verbose) # Backup soils raster self._backup_raster(self.grassMetadata['soil_rast']) # Update soils raster self._update_raster(self.grassMetadata['soil_rast'], gi_scenario_soils_data_key) # Generate parameter definition file for soil raster self._generate_parameter_definitions_for_raster( self.grassMetadata['soil_rast'], 'soil', verbose=verbose) # Write metadata RHESSysMetadata.writeGRASSEntry( self.context, "{0}_rast".format(gi_scenario_landuse_data_key), gi_scenario_landuse_data_key) RHESSysMetadata.writeGRASSEntry( self.context, "{0}_rast".format(gi_scenario_soils_data_key), gi_scenario_soils_data_key) RHESSysMetadata.writeGRASSEntry( self.context, "{0}_rast".format(gi_scenario_strata), gi_scenario_strata) RHESSysMetadata.writeGRASSEntry( self.context, "{0}_vect".format(gi_scenario_data_key), gi_scenario_data_key) RHESSysMetadata.writeGRASSEntry( self.context, "{0}_vect".format(gi_scenario_soils_data_key), gi_scenario_soils_data_key) RHESSysMetadata.writeGRASSEntry( self.context, "{0}_vect".format(gi_scenario_landuse_data_key), gi_scenario_landuse_data_key) RHESSysMetadata.writeRHESSysEntry(self.context, gi_scenario_data_key, gi_scenario_data) if verbose: self.outfp.write('\n\nFinished parameterizing GI.\n') # Write processing history RHESSysMetadata.appendProcessingHistoryItem( self.context, RHESSysMetadata.getCommandLine()) finally: if output: output.close()
def run(self, *args, **kwargs): """ Create flow tables for multiple worldfiles Arguments: routeRoads -- boolean Whether road routing should be enabled in createflowpaths. Default: False. routeRoofs -- boolean Whether roof routing should be enabled in createflowpaths. Default: False. ignoreBurnedDEM -- boolean If true, use the base DEM when running createflowpaths. If false, use the stream-burned DEM (if present). Default: False. force -- boolean Whether to force createflowpaths to run if DEM X resolution != Y resolution. Default: False. verbose -- boolean Produce verbose output. Default: False. """ routeRoads = kwargs.get('routeRoads', False) routeRoofs = kwargs.get('routeRoofs', False) force = kwargs.get('force', False) ignoreBurnedDEM = kwargs.get('ignoreBurnedDEM', False) verbose = kwargs.get('verbose', False) self.checkMetadata(routeRoads=routeRoads, routeRoofs=routeRoofs) rhessysDir = self.metadata['rhessys_dir'] self.paths = RHESSysPaths(self.context.projectDir, rhessysDir) demResX = float(self.studyArea['dem_res_x']) demResY = float(self.studyArea['dem_res_y']) if demResX != demResY: self.outfp.write("DEM x resolution (%f) does not match y resolution (%f)" % (demResX, demResY) ) if not force: raise RunException('Exiting. Use force option to override') # Determine DEM raster to use demRast = self.grassMetadata['dem_rast'] if ('stream_burned_dem_rast' in self.grassMetadata) and (not ignoreBurnedDEM): demRast = self.grassMetadata['stream_burned_dem_rast'] self.outfp.write("Using raster named '%s' to calculate flow direction map\n" % (demRast,) ) # Make sure region is properly set demRast = self.grassMetadata['dem_rast'] result = self.grassLib.script.run_command('g.region', rast=demRast) if result != 0: raise RunException("g.region failed to set region to DEM, returning {0}".format(result)) # Get paths for CF binary and template cfPath = os.path.join(self.context.projectDir, self.metadata['cf_bin']) templatePath = os.path.join(self.context.projectDir, self.metadata['template']) if verbose: self.outfp.write(self.templatePath) self.outfp.write('\n') # Make output file paths and file name templates flowTableNameBase = "world_{mask}" flowOutpath = os.path.join(self.paths.RHESSYS_FLOW, flowTableNameBase) cfOutpath = os.path.join(self.paths.RHESSYS_FLOW, "cf_{mask}.out") roads = None if routeRoads: roads = self.grassMetadata['roads_rast'] else: roads = self.grassMetadata['zero_rast'] roofs = None impervious = None # These filenames are only for metadata if routeRoofs: roofs = self.grassMetadata['roof_connectivity_rast'] impervious = self.grassMetadata['impervious_rast'] surfaceFlowtableTemplate = "world_{mask}_surface.flow" subsurfaceFlowtableTemplate = "world_{mask}_subsurface.flow" else: surfaceFlowtableTemplate = subsurfaceFlowtableTemplate = "world_{mask}.flow" # Make flowtable for each masked region if verbose: self.outfp.write('Running createflowpaths (this may take a few minutes)...') self.outfp.flush() surfaceFlowtables = [] subsurfaceFlowtables = [] masks = self.metadata['subbasin_masks'].split(RHESSysMetadata.VALUE_DELIM) for mask in masks: result = self.grassLib.script.run_command('r.mask', flags='o', input=mask, maskcats='1', quiet=True) if result != 0: raise RunException("r.mask failed to set mask to sub-basin {0}, returning {1}".format(mask, result)) # Run CF p = self.grassLib.script.pipe_command(cfPath, out=flowOutpath.format(mask=mask), template=templatePath, dem=demRast, slope=self.grassMetadata['slope_rast'], stream=self.grassMetadata['streams_rast'], road=roads, roof=roofs, impervious=impervious, cellsize=demResX) (pStdout, pStderr) = p.communicate() if verbose: self.outfp.write("CF output:\n") self.outfp.write(pStdout) if pStderr: self.outfp.write(pStderr) if p.returncode != 0: raise RunException("createflowpaths failed, returning %s" % ( str(p.returncode),)) # Write cf output to project directory cfOut = open(cfOutpath.format(mask=mask), 'w') cfOut.write(pStdout) if pStderr: cfOut.write("\n\nStandard error output:\n\n") cfOut.write(pStderr) cfOut.close() surfFlow = os.path.join(self.paths.RHESSYS_FLOW, surfaceFlowtableTemplate.format(mask=mask)) surfaceFlowtables.append(surfFlow) subsurfFlow = os.path.join(self.paths.RHESSYS_FLOW, subsurfaceFlowtableTemplate.format(mask=mask)) subsurfaceFlowtables.append(subsurfFlow) # Remove mask result = self.grassLib.script.run_command('r.mask', flags='r', quiet=True) if result != 0: raise RunException("r.mask failed to remove mask") # Write metadata cfCmd = "%s out=%s template=%s dem=%s slope=%s stream=%s road=%s roof=%s impervious=%s cellsize=%s" % \ (cfPath, flowOutpath, templatePath, demRast, self.grassMetadata['slope_rast'], self.grassMetadata['streams_rast'], roads, roofs, impervious, demResX) RHESSysMetadata.writeRHESSysEntry(self.context, 'flowtable_cmd', cfCmd) RHESSysMetadata.writeRHESSysEntry(self.context, 'surface_flowtables', RHESSysMetadata.VALUE_DELIM.join([self.paths.relpath(s) for s in surfaceFlowtables]) ) RHESSysMetadata.writeRHESSysEntry(self.context, 'subsurface_flowtables', RHESSysMetadata.VALUE_DELIM.join([self.paths.relpath(s) for s in subsurfaceFlowtables]) ) if verbose: self.outfp.write('\n\nFinished creating flow tables\n') # Write processing history RHESSysMetadata.appendProcessingHistoryItem(self.context, RHESSysMetadata.getCommandLine())
def run(self, *args, **kwargs): """ Multiple worldfiles, one worldfile for each subbasin delineated. Arguments: verbose -- boolean Produce verbose output. Default: False. """ verbose = kwargs.get('verbose', False) self.checkMetadata() rhessysDir = self.metadata['rhessys_dir'] self.paths = RHESSysPaths(self.context.projectDir, rhessysDir) templateFilename = os.path.basename(self.metadata['template']) templateFilepath = os.path.join(self.context.projectDir, self.metadata['template']) g2wPath = os.path.join(self.context.projectDir, self.metadata['g2w_bin']) # Make sure g2w can find rat g2wEnv = dict(os.environ) g2wEnv['PATH'] = self.paths.RHESSYS_BIN + os.pathsep + g2wEnv['PATH'] # Make sure region is properly set demRast = self.grassMetadata['dem_rast'] result = self.grassLib.script.run_command('g.region', rast=demRast) if result != 0: raise RunException("g.region failed to set region to DEM, returning {0}".format(result)) # Mask subbasin to basin basin_rast = self.grassMetadata['basin_rast'] result = self.grassLib.script.run_command('r.mask', flags='o', input=basin_rast, maskcats='1', quiet=True) if result != 0: sys.exit("r.mask failed to set mask to basin, returning %s" % (result,)) subbasin_raster = self.grassMetadata['subbasins_rast'] subbasin_mask = "{0}_mask".format(subbasin_raster) mapcalc_input = "{subbasin_mask}={subbasins}".format(subbasin_mask=subbasin_mask, subbasins=subbasin_raster) result = self.grassLib.script.write_command('r.mapcalc', stdin=mapcalc_input, stdout=PIPE, stderr=PIPE) if result != 0: raise RunException("r.mapcalc failed to generate masked subbasin map {0}, input: {1}".format(subbasin_raster, mapcalc_input)) # Get list of subbasins result = self.grassLib.script.read_command('r.stats', flags='n', input=subbasin_raster, quiet=True) if result is None or result == '': raise RunException("Error reading subbasin map {0}".format(subbasin_raster)) subbasins = result.split() subbasin_masks = [] worldfiles = [] for subbasin in subbasins: # Remove mask result = self.grassLib.script.run_command('r.mask', flags='r', quiet=True) if result != 0: raise RunException("r.mask failed to remove mask") # Make a mask layer for the sub-basin mask_name = "subbasin_{0}".format(subbasin) subbasin_masks.append(mask_name) result = self.grassLib.script.write_command('r.mapcalc', stdin="{mask_name}={subbasins} == {subbasin_number}".format(mask_name=mask_name, subbasins=subbasin_mask, subbasin_number=subbasin), stdout=PIPE, stderr=PIPE) if result != 0: raise RunException("r.mapcalc failed to generate mask for subbasin {0}".format(subbasin)) # Mask to the sub-basin result = self.grassLib.script.run_command('r.mask', flags='o', input=mask_name, maskcats='1', quiet=True) if result != 0: raise RunException("r.mask failed to set mask to sub-basin {0}, returning {1}".format(mask_name, result)) worldfileName = "world_subbasin_{0}_init".format(subbasin) worldfilePath = os.path.join(self.paths.RHESSYS_WORLD, worldfileName) worldfiles.append(worldfilePath) g2wCommand = "{g2w} -t {template} -w {worldfile}".format(g2w=g2wPath, template=templateFilepath, worldfile=worldfilePath) if verbose: self.outfp.write("{0}\n".format(g2wCommand)) self.outfp.write("\nRunning grass2world from {0}...".format(self.paths.RHESSYS_BIN)) self.outfp.flush() cmdArgs = g2wCommand.split() process = Popen(cmdArgs, cwd=self.paths.RHESSYS_BIN, env=g2wEnv, stdout=PIPE, stderr=PIPE) (process_stdout, process_stderr) = process.communicate() if process.returncode != 0: raise RunException("grass2world failed, returning {0}".format(process.returncode)) if verbose: self.outfp.write(process_stdout) self.outfp.write(process_stderr) # Remove mask result = self.grassLib.script.run_command('r.mask', flags='r', quiet=True) if result != 0: raise RunException("r.mask failed to remove mask") # Write metadata RHESSysMetadata.writeRHESSysEntry(self.context, 'worldfiles_init', RHESSysMetadata.VALUE_DELIM.join([self.paths.relpath(w) for w in worldfiles])) RHESSysMetadata.writeRHESSysEntry(self.context, 'subbasin_masks', RHESSysMetadata.VALUE_DELIM.join([m for m in subbasin_masks])) if verbose: self.outfp.write('\n\nFinished creating worldfiles\n') # Write processing history RHESSysMetadata.appendProcessingHistoryItem(self.context, RHESSysMetadata.getCommandLine())