示例#1
0
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())
示例#2
0
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)
示例#3
0
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)
示例#7
0
## 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)
示例#8
0
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)
示例#9
0
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(
示例#11
0
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)
示例#12
0
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):
示例#13
0
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())
         
示例#14
0
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)
示例#17
0
                                 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)