class FlowtableMultiple(GrassCommand): def __init__(self, projectDir, configFile=None, outfp=sys.stdout): """ Construct a FlowtableMultiple command. Arguments: projectDir -- string The path to the project directory configFile -- string The path to an EcohydroLib configuration file outfp -- file-like object Where output should be written to """ super(FlowtableMultiple, self).__init__(projectDir, configFile, outfp) def checkMetadata(self, *args, **kwargs): """ Check to make sure the project directory has the necessary metadata to run this command. """ super(FlowtableMultiple, self).checkMetadata(args, kwargs) # Check for necessary information in metadata if not 'dem_rast' in self.grassMetadata: raise MetadataException( "Metadata in project directory %s does not contain a GRASS dataset with a DEM raster" % (self.context.projectDir, )) if not 'slope_rast' in self.grassMetadata: raise MetadataException( "Metadata in project directory %s does not contain a GRASS dataset with a slope raster" % (self.context.projectDir, )) if not 'streams_rast' in self.grassMetadata: raise MetadataException( "Metadata in project directory %s does not contain a GRASS dataset with a stream raster" % (self.context.projectDir, )) if not 'zero_rast' in self.grassMetadata: raise MetadataException( "Metadata in project directory %s does not contain a GRASS dataset with a zero raster" % (self.context.projectDir, )) if not 'dem_res_x' in self.studyArea: raise MetadataException( "Metadata in project directory %s does not contain a DEM x resolution" % (self.context.projectDir, )) if not 'dem_res_y' in self.studyArea: raise MetadataException( "Metadata in project directory %s does not contain a DEM y resolution" % (self.context.projectDir, )) if not 'rhessys_dir' in self.metadata: raise MetadataException( "Metadata in project directory %s does not contain a RHESSys directory" % (self.self.context.projectDir, )) if not 'cf_bin' in self.metadata: raise MetadataException( "Metadata in project directory %s does not contain a createflowpaths executable" % (self.context.projectDir, )) if not 'subbasin_masks' in self.metadata: raise MetadataException( "Metadata in project directory %s does not contain multiple worldfile masks" % (self.context.projectDir, )) if not 'template' in self.metadata: raise MetadataException( "Metadata in project directory %s does not contain a template" % (self.context.projectDir, )) routeRoads = kwargs.get('routeRoads', False) if routeRoads: if not 'roads_rast' in self.grassMetadata: raise MetadataException( "Metadata in project directory %s does not contain a GRASS dataset with a roads raster" % (self.context.projectDir, )) routeRoofs = kwargs.get('routeRoofs', False) if routeRoofs: if not 'roof_connectivity_rast' in self.grassMetadata: raise MetadataException( "Metadata in project directory %s does not contain a GRASS dataset with a roofs raster" % (self.context.projectDir, )) if not 'impervious_rast' in self.grassMetadata: raise MetadataException( "Metadata in project directory %s does not contain a GRASS dataset with a impervious raster" % (self.context.projectDir, )) 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())
rhessysBinPathRel = metadata['rhessys_bin'] rhessysBinPath = os.path.join(context.projectDir, rhessysBinPathRel) if not os.path.isfile(rhessysBinPath) or not os.access(rhessysBinPath, os.X_OK): sys.exit("Putative RHESSys executable '%s' is not an executable file" % (rhessysBinPath,) ) if args.outputPrefix.count(os.sep) > 1: sys.exit("Output prefix cannot contain a path separator ('%s')" % (args.outputPrefix,) ) if not os.access(paths.RHESSYS_OUT, os.W_OK): sys.exit("RHESSys output directory '%s' is not writable" % (paths.RHESSYS_OUT,) ) outputDir = os.path.join(paths.RHESSYS_OUT, args.outputPrefix) # Append path separator and 'rhessys' so that RHESSys will write output into a subdirectory outputPrefix = os.path.join(outputDir, RHESSysMetadata.MODEL_NAME) if os.path.isdir(outputPrefix): sys.exit( textwrap.fill("\nOutput directory '%s' already exists, please choose another output prefix." % (outputPrefix,) ) ) outputPrefixRel = paths.relpath(outputPrefix) outputDirRel = paths.relpath(outputDir) if args.worldfile.count(os.sep) > 1: sys.exit("Worldfile cannot contain a path separator ('%s')" % (args.worldfile,) ) worldfile = os.path.join(paths.RHESSYS_WORLD, args.worldfile) if not os.path.isfile(worldfile) or not os.access(worldfile, os.R_OK): sys.exit("Worldfile '%s' is not a readable file" % (worldfile,) ) worldfileRel = paths.relpath(worldfile) if args.tecfile.count(os.sep) > 1: sys.exit("TEC file cannot contain a path separator ('%s')" % (args.tecfile,) ) tecfile = os.path.join(paths.RHESSYS_TEC, args.tecfile) if not os.path.isfile(tecfile) or not os.access(tecfile, os.R_OK): sys.exit("TEC file '%s' is not a readable file" % (tecfile,) ) tecfileRel = paths.relpath(tecfile)
class LAIReadMultiple(GrassCommand): def __init__(self, projectDir, configFile=None, outfp=sys.stdout): """ Construct a LAIReadMultiple command. Arguments: projectDir -- string The path to the project directory configFile -- string The path to an EcohydroLib configuration file outfp -- file-like object Where output should be written to """ super(LAIReadMultiple, self).__init__(projectDir, configFile, outfp) def checkMetadata(self, *args, **kwargs): """ Check to make sure the project directory has the necessary metadata to run this command. """ super(LAIReadMultiple, self).checkMetadata() # Check for necessary information in self.metadata if not 'subbasin_masks' in self.metadata: raise MetadataException("Metadata in project directory %s does not contain multiple worldfile masks" % (self.context.projectDir,)) if not 'dem_rast' in self.grassMetadata: raise MetadataException("Metadata in project directory %s does not contain a GRASS dataset with a DEM raster" % (self.context.projectDir,)) if not 'hillslope_rast' in self.grassMetadata: raise MetadataException("Metadata in project directory %s does not contain a GRASS dataset with a hillslope raster" % (self.context.projectDir,)) if not 'zone_rast' in self.grassMetadata: raise MetadataException("Metadata in project directory %s does not contain a GRASS dataset with a zone raster" % (self.context.projectDir,)) if not 'patch_rast' in self.grassMetadata: raise MetadataException("Metadata in project directory %s does not contain a GRASS dataset with a patch raster" % (self.context.projectDir,)) if not 'stratum_rast' in self.grassMetadata: raise MetadataException("Metadata in project directory %s does not contain a GRASS dataset with a stratum raster" % (self.context.projectDir,)) if not 'lai_rast' in self.grassMetadata: raise MetadataException("Metadata in project directory %s does not contain a GRASS dataset with an LAI raster" % (self.context.projectDir,)) if not 'rhessys_dir' in self.metadata: raise MetadataException("Metadata in project directory %s does not contain a RHESSys directory" % (self.context.projectDir,)) if not 'rhessys_bin' in self.metadata: raise MetadataException("Metadata in project directory %s does not contain a RHESSys binary" % (self.context.projectDir,)) if not 'lairead_bin' in self.metadata: raise MetadataException("Metadata in project directory %s does not contain a lairead executable" % (self.context.projectDir,)) if not 'worldfiles_init' in self.metadata: raise MetadataException("Metadata in project directory %s does not contain initial worldfiles" % (self.context.projectDir,)) if not 'allometric_table' in self.metadata: raise MetadataException("Metadata in project directory %s does not contain an allometric table" % (self.context.projectDir,)) topmodel = kwargs.get('topmodel', False) if not topmodel: if not 'surface_flowtables' in self.metadata: raise MetadataException("Metadata in project directory %s does not contain surface flowtables" % (self.context.projectDir,)) if not 'subsurface_flowtables' in self.metadata: raise MetadataException("Metadata in project directory %s does not contain a subsurface flowtables" % (self.context.projectDir,)) 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())
(stdoutStr, stderrStr) = p.communicate() result = p.returncode if result != 0: sys.stdout.write(stdoutStr) sys.exit("\nv.in.ascii failed, returning %s" % (result,)) # Generate Thiessen polygons p = grassLib.script.pipe_command('v.voronoi', input='basestation_points', output='basestation_areas', overwrite=args.overwrite) (stdoutStr, stderrStr) = p.communicate() result = p.returncode if result != 0: sys.stdout.write(stdoutStr) sys.exit("\nv.voronoi failed, returning %s" % (result,)) # Rasterize Thiessen polygons p = grassLib.script.pipe_command('v.to.rast', input='basestation_areas', output='basestations', use='cat', labelcolumn='name', overwrite=args.overwrite) (stdoutStr, stderrStr) = p.communicate() result = p.returncode if result != 0: sys.stdout.write(stdoutStr) sys.exit("\nv.to.rast failed, returning %s" % (result,)) # Write metadata RHESSysMetadata.writeRHESSysEntry( context, 'basestations_text', paths.relpath(basestationsDest) ) RHESSysMetadata.writeGRASSEntry( context, 'basestations_rast', 'basestations' ) # Write processing history RHESSysMetadata.appendProcessingHistoryItem(context, cmdline)
## 3. Write TEC file for redefining the initial world file ## Redefine on the second day of the simulation, write output ## on the third day tecName = 'tec.lairead' tecPath = os.path.join(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() RHESSysMetadata.writeRHESSysEntry( context, 'tec_lairead', paths.relpath(tecPath) ) ## 4. Run RHESSys for the first 4 legal days with redefine TEC rhessysStart = startDate rhessysDur = datetime.timedelta(days=3) rhessysEnd = startDate + rhessysDur surfaceFlowtablePath = os.path.join(context.projectDir, metadata['surface_flowtable']) subSurfaceFlowtablePath = os.path.join(context.projectDir, metadata['subsurface_flowtable']) rhessysBinPath = os.path.join(context.projectDir, metadata['rhessys_bin']) rhessysCmd = generateCommandString(rhessysBinPath, None, rhessysStart, rhessysEnd, tecPath, oldWorldPath, subSurfaceFlowtablePath, surfaceFlowtablePath) if args.verbose: print(rhessysCmd)
worldfileName = "%s_init" % (templateFilename.replace("template", "world"),) worldfilePath = os.path.join(paths.RHESSYS_WORLD, worldfileName) g2wPath = os.path.join(context.projectDir, metadata["g2w_bin"]) g2wCommand = "%s -t %s -w %s" % (g2wPath, templateFilepath, worldfilePath) # Make sure g2w can find rat g2wEnv = dict(os.environ) g2wEnv["PATH"] = paths.RHESSYS_BIN + os.pathsep + g2wEnv["PATH"] if args.verbose: print(g2wCommand) sys.stdout.write("\nRunning grass2world from %s..." % (paths.RHESSYS_BIN,)) sys.stdout.flush() cmdArgs = g2wCommand.split() process = Popen(cmdArgs, cwd=paths.RHESSYS_BIN, env=g2wEnv, stdout=PIPE, stderr=PIPE) (process_stdout, process_stderr) = process.communicate() if args.verbose: sys.stdout.write(process_stdout) sys.stderr.write(process_stderr) if process.returncode != 0: sys.exit("\n\ngrass2world failed, returning %s" % (process.returncode,)) RHESSysMetadata.writeRHESSysEntry(context, "worldfile_zero", paths.relpath(worldfilePath)) sys.stdout.write("\n\nFinished creating worldfile\n") # Write processing history RHESSysMetadata.appendProcessingHistoryItem(context, cmdline)
## 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' tecPath = os.path.join(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() RHESSysMetadata.writeRHESSysEntry(context, 'tec_lairead', paths.relpath(tecPath)) ## 4. Run RHESSys for the first 4 legal days with redefine TEC rhessysStart = startDate rhessysDur = datetime.timedelta(days=3) rhessysEnd = startDate + rhessysDur surfaceFlowtablePath = os.path.join(context.projectDir, metadata['surface_flowtable']) subSurfaceFlowtablePath = os.path.join(context.projectDir, metadata['subsurface_flowtable']) rhessysBinPath = os.path.join(context.projectDir, metadata['rhessys_bin']) rhessysCmd = generateCommandString(rhessysBinPath, None, rhessysStart, rhessysEnd, tecPath, oldWorldPath, surfaceFlowtablePath, subSurfaceFlowtablePath)
p = grassLib.script.pipe_command('v.voronoi', input='basestation_points', output='basestation_areas', overwrite=args.overwrite) (stdoutStr, stderrStr) = p.communicate() result = p.returncode if result != 0: sys.stdout.write(stdoutStr) sys.exit("\nv.voronoi failed, returning %s" % (result, )) # Rasterize Thiessen polygons p = grassLib.script.pipe_command('v.to.rast', input='basestation_areas', output='basestations', use='cat', labelcolumn='name', overwrite=args.overwrite) (stdoutStr, stderrStr) = p.communicate() result = p.returncode if result != 0: sys.stdout.write(stdoutStr) sys.exit("\nv.to.rast failed, returning %s" % (result, )) # Write metadata RHESSysMetadata.writeRHESSysEntry(context, 'basestations_text', paths.relpath(basestationsDest)) RHESSysMetadata.writeGRASSEntry(context, 'basestations_rast', 'basestations') # Write processing history RHESSysMetadata.appendProcessingHistoryItem(context, cmdline)
class WorldfileMultiple(GrassCommand): def __init__(self, projectDir, configFile=None, outfp=sys.stdout): """ Construct a WorldfileMultiple command. Arguments: projectDir -- string The path to the project directory configFile -- string The path to an EcohydroLib configuration file outfp -- file-like object Where output should be written to """ super(WorldfileMultiple, self).__init__(projectDir, configFile, outfp) def checkMetadata(self): """ Check to make sure the project directory has the necessary metadata to run this command. """ super(WorldfileMultiple, self).checkMetadata() # Check for necessary information in metadata if not 'basin_rast' in self.grassMetadata: raise MetadataException( "Metadata in project directory %s does not contain a basin raster in a GRASS mapset" % (self.context.projectDir, )) if not 'subbasins_rast' in self.grassMetadata: raise MetadataException( "Metadata in project directory %s does not contain a sub-basin raster in a GRASS mapset" % (self.context.projectDir, )) if not 'dem_rast' in self.grassMetadata: raise MetadataException( "Metadata in project directory %s does not contain a DEM raster in a GRASS mapset" % (self.context.projectDir, )) if not 'soil_rast' in self.grassMetadata: raise MetadataException( "Metadata in project directory %s does not contain a soil raster in a GRASS mapset" % (self.context.projectDir, )) if not 'patch_rast' in self.grassMetadata: raise MetadataException( "Metadata in project directory %s does not contain a patch raster in a GRASS mapset" % (self.context.projectDir, )) if not 'rhessys_dir' in self.metadata: raise MetadataException( "Metadata in project directory %s does not contain a RHESSys directory" % (self.context.projectDir, )) if not 'g2w_bin' in self.metadata: raise MetadataException( "Metadata in project directory %s does not contain a grass2world executable" % (self.context.projectDir, )) if not 'rat_bin' in self.metadata: raise MetadataException( "Metadata in project directory %s does not contain an AverageTables executable" % (self.context.projectDir, )) if not 'template' in self.metadata: raise MetadataException( "Metadata in project directory %s does not contain a world template" % (self.context.projectDir, )) if not 'rhessys_dir' in self.metadata: raise MetadataException( "Metadata in project directory {0} does not contain a RHESSys directory" .format(self.context.projectDir)) 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())
paramDB = os.path.join(paramDBPath, paramDBName) # Make sure there is a template in the imported source templatePath = os.path.join(paramDBPath, TEMPLATE_PATH) #print(templatePath) if not os.path.exists(templatePath): sys.exit("Template template not found in ParamDB git clone") # Make sure there is an allometric.txt in the imported source allometricPath = os.path.join(paramDBPath, ALLOMETRIC_PATH) #print(allometricPath) if not os.path.exists(allometricPath): sys.exit("Allometric table not found in ParamDB git clone") RHESSysMetadata.writeRHESSysEntry(context, 'paramdb_dir', paths.relpath(paramDBPath)) RHESSysMetadata.writeRHESSysEntry(context, 'paramdb', paths.relpath(paramDB)) RHESSysMetadata.writeRHESSysEntry(context, 'template_template', paths.relpath(templatePath)) RHESSysMetadata.writeRHESSysEntry(context, 'allometric_table', paths.relpath(allometricPath)) ## 2. Import code from local disk, or from GitHub if args.sourceDir: # Import source code from sourceDir if not os.access(args.sourceDir, os.R_OK): sys.exit( "The specified path of the RHESSys source directory, %s, is not readable" % (args.sourceDir, )) if not os.path.isdir(args.sourceDir): sys.exit(
subs['impervious_rast'] = grassMetadata['impervious_rast'] subs['wetness_index_rast'] = grassMetadata['wetness_index_rast'] subs['stratum_rast'] = grassMetadata['stratum_rast'] subs['xmap_rast'] = grassMetadata['xmap_rast'] subs['ymap_rast'] = grassMetadata['ymap_rast'] # Third, substitute into the template template, producing the template, which we write to disk for g2w templateStr = '' try: templateStr = templateTemplate.substitute(subs) if args.verbose: print("Template:") print(templateStr) except KeyError as e: sys.exit("ERROR creating worldfile template: template variable %s was not specified" % (str(e),) ) except ValueError: sys.exit("A '$' character was found in the template template, which is illegal") # Write the template to a file stored in paths.RHESSYS_TEMPLATES, using the filename # of the template template as a basis templateFilename = os.path.splitext( os.path.split( metadata['template_template'] )[1] )[0] templateFilepath = os.path.join(paths.RHESSYS_TEMPLATES, templateFilename) f = open(templateFilepath, 'w') f.write(templateStr) f.close() RHESSysMetadata.writeRHESSysEntry(context, 'template', paths.relpath(templateFilepath) ) sys.stdout.write('done\n') # Write processing history RHESSysMetadata.appendProcessingHistoryItem(context, cmdline)
if args.outputPrefix.count(os.sep) > 1: sys.exit("Output prefix cannot contain a path separator ('%s')" % (args.outputPrefix, )) if not os.access(paths.RHESSYS_OUT, os.W_OK): sys.exit("RHESSys output directory '%s' is not writable" % (paths.RHESSYS_OUT, )) outputDir = os.path.join(paths.RHESSYS_OUT, args.outputPrefix) # Append path separator and 'rhessys' so that RHESSys will write output into a subdirectory outputPrefix = os.path.join(outputDir, RHESSysMetadata.MODEL_NAME) if os.path.isdir(outputPrefix): sys.exit( textwrap.fill( "\nOutput directory '%s' already exists, please choose another output prefix." % (outputPrefix, ))) outputPrefixRel = paths.relpath(outputPrefix) outputDirRel = paths.relpath(outputDir) if args.worldfile.count(os.sep) > 1: sys.exit("Worldfile cannot contain a path separator ('%s')" % (args.worldfile, )) worldfile = os.path.join(paths.RHESSYS_WORLD, args.worldfile) if not os.path.isfile(worldfile) or not os.access(worldfile, os.R_OK): sys.exit("Worldfile '%s' is not a readable file" % (worldfile, )) worldfileRel = paths.relpath(worldfile) if args.tecfile.count(os.sep) > 1: sys.exit("TEC file cannot contain a path separator ('%s')" % (args.tecfile, )) tecfile = os.path.join(paths.RHESSYS_TEC, args.tecfile) if not os.path.isfile(tecfile) or not os.access(tecfile, os.R_OK):
class FlowtableMultiple(GrassCommand): def __init__(self, projectDir, configFile=None, outfp=sys.stdout): """ Construct a FlowtableMultiple command. Arguments: projectDir -- string The path to the project directory configFile -- string The path to an EcohydroLib configuration file outfp -- file-like object Where output should be written to """ super(FlowtableMultiple, self).__init__(projectDir, configFile, outfp) def checkMetadata(self, *args, **kwargs): """ Check to make sure the project directory has the necessary metadata to run this command. """ super(FlowtableMultiple, self).checkMetadata(args, kwargs) # Check for necessary information in metadata if not 'dem_rast' in self.grassMetadata: raise MetadataException("Metadata in project directory %s does not contain a GRASS dataset with a DEM raster" % (self.context.projectDir,)) if not 'slope_rast' in self.grassMetadata: raise MetadataException("Metadata in project directory %s does not contain a GRASS dataset with a slope raster" % (self.context.projectDir,)) if not 'streams_rast' in self.grassMetadata: raise MetadataException("Metadata in project directory %s does not contain a GRASS dataset with a stream raster" % (self.context.projectDir,)) if not 'zero_rast' in self.grassMetadata: raise MetadataException("Metadata in project directory %s does not contain a GRASS dataset with a zero raster" % (self.context.projectDir,)) if not 'dem_res_x' in self.studyArea: raise MetadataException("Metadata in project directory %s does not contain a DEM x resolution" % (self.context.projectDir,)) if not 'dem_res_y' in self.studyArea: raise MetadataException("Metadata in project directory %s does not contain a DEM y resolution" % (self.context.projectDir,)) if not 'rhessys_dir' in self.metadata: raise MetadataException("Metadata in project directory %s does not contain a RHESSys directory" % (self.self.context.projectDir,)) if not 'cf_bin' in self.metadata: raise MetadataException("Metadata in project directory %s does not contain a createflowpaths executable" % (self.context.projectDir,)) if not 'subbasin_masks' in self.metadata: raise MetadataException("Metadata in project directory %s does not contain multiple worldfile masks" % (self.context.projectDir,)) if not 'template' in self.metadata: raise MetadataException("Metadata in project directory %s does not contain a template" % (self.context.projectDir,)) routeRoads = kwargs.get('routeRoads', False) if routeRoads: if not 'roads_rast' in self.grassMetadata: raise MetadataException("Metadata in project directory %s does not contain a GRASS dataset with a roads raster" % (self.context.projectDir,)) routeRoofs = kwargs.get('routeRoofs', False) if routeRoofs: if not 'roof_connectivity_rast' in self.grassMetadata: raise MetadataException("Metadata in project directory %s does not contain a GRASS dataset with a roofs raster" % (self.context.projectDir,)) if not 'impervious_rast' in self.grassMetadata: raise MetadataException("Metadata in project directory %s does not contain a GRASS dataset with a impervious raster" % (self.context.projectDir,)) 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())
class WorldfileMultiple(GrassCommand): def __init__(self, projectDir, configFile=None, outfp=sys.stdout): """ Construct a WorldfileMultiple command. Arguments: projectDir -- string The path to the project directory configFile -- string The path to an EcohydroLib configuration file outfp -- file-like object Where output should be written to """ super(WorldfileMultiple, self).__init__(projectDir, configFile, outfp) def checkMetadata(self): """ Check to make sure the project directory has the necessary metadata to run this command. """ super(WorldfileMultiple, self).checkMetadata() # Check for necessary information in metadata if not 'basin_rast' in self.grassMetadata: raise MetadataException("Metadata in project directory %s does not contain a basin raster in a GRASS mapset" % (self.context.projectDir,)) if not 'subbasins_rast' in self.grassMetadata: raise MetadataException("Metadata in project directory %s does not contain a sub-basin raster in a GRASS mapset" % (self.context.projectDir,)) if not 'dem_rast' in self.grassMetadata: raise MetadataException("Metadata in project directory %s does not contain a DEM raster in a GRASS mapset" % (self.context.projectDir,)) if not 'soil_rast' in self.grassMetadata: raise MetadataException("Metadata in project directory %s does not contain a soil raster in a GRASS mapset" % (self.context.projectDir,)) if not 'patch_rast' in self.grassMetadata: raise MetadataException("Metadata in project directory %s does not contain a patch raster in a GRASS mapset" % (self.context.projectDir,)) if not 'rhessys_dir' in self.metadata: raise MetadataException("Metadata in project directory %s does not contain a RHESSys directory" % (self.context.projectDir,)) if not 'g2w_bin' in self.metadata: raise MetadataException("Metadata in project directory %s does not contain a grass2world executable" % (self.context.projectDir,)) if not 'rat_bin' in self.metadata: raise MetadataException("Metadata in project directory %s does not contain an AverageTables executable" % (self.context.projectDir,)) if not 'template' in self.metadata: raise MetadataException("Metadata in project directory %s does not contain a world template" % (self.context.projectDir,)) if not 'rhessys_dir' in self.metadata: raise MetadataException("Metadata in project directory {0} does not contain a RHESSys directory".format(self.context.projectDir)) 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())
sys.exit("Unable to find parameter database %s in %s" % (paramDBName, paramDBPath) ) paramDB = os.path.join(paramDBPath, paramDBName) # Make sure there is a template in the imported source templatePath = os.path.join(paramDBPath, TEMPLATE_PATH) #print(templatePath) if not os.path.exists(templatePath): sys.exit("Template template not found in ParamDB git clone") # Make sure there is an allometric.txt in the imported source allometricPath = os.path.join(paramDBPath, ALLOMETRIC_PATH) #print(allometricPath) if not os.path.exists(allometricPath): sys.exit("Allometric table not found in ParamDB git clone") RHESSysMetadata.writeRHESSysEntry(context, 'paramdb_dir', paths.relpath(paramDBPath) ) RHESSysMetadata.writeRHESSysEntry(context, 'paramdb', paths.relpath(paramDB) ) RHESSysMetadata.writeRHESSysEntry(context, 'template_template', paths.relpath(templatePath) ) RHESSysMetadata.writeRHESSysEntry(context, 'allometric_table', paths.relpath(allometricPath) ) ## 2. Import code from local disk, or from GitHub if args.sourceDir: # Import source code from sourceDir if not os.access(args.sourceDir, os.R_OK): sys.exit("The specified path of the RHESSys source directory, %s, is not readable" % (args.sourceDir,) ) if not os.path.isdir(args.sourceDir): sys.exit("The specified path of the RHESSys source directory, %s, is not a directory" % (args.sourceDir,) ) g2wSrc = os.path.join(args.sourceDir, 'g2w') if not os.path.exists(g2wSrc) or not os.path.isdir(g2wSrc): sys.exit("The specified path of the RHESSys source directory, %s, does not seem to contain grass2world source code in a directory called 'g2w'" %
print("CF output:") print(pStdout) if pStderr: print(pStderr) if p.returncode != 0: sys.exit("createflowpaths failed, returning %s" % (str(p.returncode), )) # Write cf output to project directory cfOut = open(cfOutpath, 'w') cfOut.write(pStdout) if pStderr: cfOut.write("\n\nStandard error output:\n\n") cfOut.write(pStderr) cfOut.close() cfCmd = "%s out=%s template=%s dem=%s slope=%s stream=%s road=%s roof=%s impervious=%s cellsize=%s" % \ (cfPath, flowOutpath, templatePath, grassMetadata['dem_rast'], grassMetadata['slope_rast'], grassMetadata['streams_rast'], roads, roofs, impervious, demResX) RHESSysMetadata.writeRHESSysEntry(context, 'flowtable_cmd', cfCmd) RHESSysMetadata.writeRHESSysEntry( context, 'surface_flowtable', paths.relpath(os.path.join(paths.RHESSYS_FLOW, surfaceFlowtable))) RHESSysMetadata.writeRHESSysEntry( context, 'subsurface_flowtable', paths.relpath(os.path.join(paths.RHESSYS_FLOW, subsurfaceFlowtable))) sys.stdout.write('\nFinished creating flowtable\n') # Write processing history RHESSysMetadata.appendProcessingHistoryItem(context, cmdline)
cellsize=demResX) (pStdout, pStderr) = p.communicate() if args.verbose: print("CF output:") print(pStdout) if pStderr: print(pStderr) if p.returncode != 0: sys.exit("createflowpaths failed, returning %s" % ( str(p.returncode),)) # Write cf output to project directory cfOut = open(cfOutpath, 'w') cfOut.write(pStdout) if pStderr: cfOut.write("\n\nStandard error output:\n\n") cfOut.write(pStderr) cfOut.close() cfCmd = "%s out=%s template=%s dem=%s slope=%s stream=%s road=%s roof=%s impervious=%s cellsize=%s" % \ (cfPath, flowOutpath, templatePath, grassMetadata['dem_rast'], grassMetadata['slope_rast'], grassMetadata['streams_rast'], roads, roofs, impervious, demResX) RHESSysMetadata.writeRHESSysEntry(context, 'flowtable_cmd', cfCmd) RHESSysMetadata.writeRHESSysEntry(context, 'surface_flowtable', paths.relpath(os.path.join(paths.RHESSYS_FLOW, surfaceFlowtable) ) ) RHESSysMetadata.writeRHESSysEntry(context, 'subsurface_flowtable', paths.relpath(os.path.join(paths.RHESSYS_FLOW, subsurfaceFlowtable) ) ) sys.stdout.write('\nFinished creating flowtable\n') # Write processing history RHESSysMetadata.appendProcessingHistoryItem(context, cmdline)
g2wCommand = "%s -t %s -w %s" % (g2wPath, templateFilepath, worldfilePath) # Make sure g2w can find rat g2wEnv = dict(os.environ) g2wEnv['PATH'] = paths.RHESSYS_BIN + os.pathsep + g2wEnv['PATH'] if args.verbose: print(g2wCommand) sys.stdout.write("\nRunning grass2world from %s..." % (paths.RHESSYS_BIN, )) sys.stdout.flush() cmdArgs = g2wCommand.split() process = Popen(cmdArgs, cwd=paths.RHESSYS_BIN, env=g2wEnv, stdout=PIPE, stderr=PIPE) (process_stdout, process_stderr) = process.communicate() if args.verbose: sys.stdout.write(process_stdout) sys.stderr.write(process_stderr) if process.returncode != 0: sys.exit("\n\ngrass2world failed, returning %s" % (process.returncode, )) RHESSysMetadata.writeRHESSysEntry(context, 'worldfile_zero', paths.relpath(worldfilePath)) sys.stdout.write('\n\nFinished creating worldfile\n') # Write processing history RHESSysMetadata.appendProcessingHistoryItem(context, cmdline)