parser = argparse.ArgumentParser(description='Generate landcover maps in GRASS GIS')
parser.add_argument('-i', '--configfile', dest='configfile', required=False,
                    help='The configuration file. Must define section "GRASS" and option "GISBASE"')
parser.add_argument('-p', '--projectDir', dest='projectDir', required=True,
                    help='The directory to which metadata, intermediate, and final files should be saved')
group = parser.add_mutually_exclusive_group(required=True)
group.add_argument('-k', '--generateKnownRules', dest='generateKnownRules', required=False, action='store_true',
                    help="Generate rules for known landcover type; known types include: %s" % (str(RHESSysMetadata.KNOWN_LC_TYPES), ) )
group.add_argument('-b', '--buildPrototypeRules', dest='buildPrototypeRules', required=False, action='store_true',
                    help='Write prototype landcover reclass rules to the project directory. You must edit these rules to match the classes in your own landcover data')
group.add_argument('-r', '--ruleDir', dest='ruleDir', required=False,
                    help="The directory where landcover reclass rules can be found; must contain these files %s" % (str(RHESSysMetadata.LC_RULES),) )
parser.add_argument('-l', '--includeLaiRules', dest='includeLaiRules', required=False, action='store_true',
                    help='Make LAI map')
args = parser.parse_args()
cmdline = RHESSysMetadata.getCommandLine()

configFile = None
if args.configfile:
    configFile = args.configfile

context = Context(args.projectDir, configFile) 

# Check for necessary information in metadata
metadata = RHESSysMetadata.readRHESSysEntries(context)
studyArea = RHESSysMetadata.readStudyAreaEntries(context)
manifest = RHESSysMetadata.readManifestEntries(context)

paths = RHESSysPaths(args.projectDir, metadata['rhessys_dir'])

# Get path of place to store reclass rules
    dest='defonly',
    required=False,
    action='store_true',
    help=
    'Only generate landuse and stratum definition files, do not try to create maps.  Maps must already exist.'
)
parser.add_argument(
    '--overwrite',
    dest='overwrite',
    action='store_true',
    required=False,
    help=
    'Overwrite existing datasets in the GRASS mapset.  If not specified, program will halt if a dataset already exists.'
)
args = parser.parse_args()
cmdline = RHESSysMetadata.getCommandLine()

configFile = None
if args.configfile:
    configFile = args.configfile

context = Context(args.projectDir, configFile)

# Check for necessary information in metadata
grassMetadata = RHESSysMetadata.readGRASSEntries(context)
if not 'landcover_rast' in grassMetadata:
    sys.exit(
        "Metadata in project directory %s does not contain a GRASS dataset with a landcover raster"
        % (context.projectDir, ))
if not 'dem_rast' in grassMetadata:
    sys.exit(
Пример #3
0
 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())
Пример #4
0
    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())
Пример #5
0
    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())
Пример #6
0
    def run(self, *args, **kwargs):
        """ Create flow tables for multiple worldfiles

        Arguments:
        scenario_id -- int    ID of the GI Notebook scenario whose GI instances are to be parameterized.
        auth_token -- string    Authorization token to use for authenticating to the GI Notebook.
        host -- string    Hostname of GI Notebook server. Default: None.
        api_root -- string    The root of the API URL to use. Default: None.
        use_HTTPS -- boolean    Use HTTPS for communication with the GI Notebook.
        force -- boolean        Force overwrite of existing scenario output. Default: False.
        verbose -- boolean    Produce verbose output. Default: False.
        """
        scenario_id = kwargs.get('scenario_id')
        if scenario_id is None:
            raise RunException('Scenario ID was not specified.')
        auth_token = kwargs.get('auth_token')
        if auth_token is None:
            raise RunException('Authorization token was not specified.')
        host = kwargs.get('host', DEFAULT_HOSTNAME)
        api_root = kwargs.get('api_path', DEFAULT_API_ROOT)
        use_HTTPS = kwargs.get('use_HTTPS', False)
        force = kwargs.get('force', False)
        verbose = kwargs.get('verbose', False)

        self.checkMetadata()
        self.param_const, self.param_db = self._init_paramdb()
        self.paths = RHESSysPaths(self.context.projectDir, self.metadata['rhessys_dir'])

        gi_scenario_base = 'gi_scenario'
        gi_scenario_data = "{0}.geojson".format(gi_scenario_base)
        scenario_geojson_path = os.path.join(self.context.projectDir, gi_scenario_data)
        gi_scenario_soils_base = "{0}_wsoils".format(gi_scenario_base)
        gi_scenario_soils = "{0}.geojson".format(gi_scenario_soils_base)
        scenario_soils_geojson_path = os.path.join(self.context.projectDir, gi_scenario_soils)
        gi_scenario_landuse_base = "{0}_landuse".format(gi_scenario_base)
        gi_scenario_landuse = "{0}.geojson".format(gi_scenario_landuse_base)
        scenario_landuse_geojson_path = os.path.join(self.context.projectDir, gi_scenario_landuse)
        gi_scenario_data_key = 'gi_scenario_data'
        gi_scenario_soils_data_key = "{0}_soils".format(gi_scenario_data_key)
        gi_scenario_landuse_data_key = "{0}_landuse".format(gi_scenario_data_key)
        if gi_scenario_data_key in self.metadata:
            if verbose:
                self.outfp.write('Existing GI scenario found.\n')
            if force:
                if verbose:
                    self.outfp.write('Force option specified, overwriting existing GI scenario.\n')
                if os.path.exists(scenario_geojson_path):
                    os.unlink(scenario_geojson_path)
                if os.path.exists(scenario_soils_geojson_path):
                    os.unlink(scenario_soils_geojson_path)
                if os.path.exists(scenario_landuse_geojson_path):
                    os.unlink(scenario_landuse_geojson_path)
            else:
                raise RunException('Exiting.  Use force option to overwrite.')

        if verbose:
            output = None
        else:
            output = open('/dev/null')
        try:
            # Connect to GI Notebook and fetch GI instance information (in GeoJSON format)
            # for this scenario ID.
            if verbose:
                self.outfp.write("\nDownloading GI scenario {0} from GI database...\n".format(scenario_id))
            nb = GINotebook(hostname=host,
                            api_root=api_root,
                            use_https=use_HTTPS, auth_token=auth_token)
            scenario = nb.get_scenario(scenario_id)
            scenario_geojson = scenario.get_instances_as_geojson(indent=2, shorten=True)
            (gi_scenario_data_wgs84, scenario_geojson_wgs84_path), (gi_scenario_data, scenario_geojson_path) = \
                self._write_geojson_and_reproject(scenario_geojson, gi_scenario_base, verbose=verbose, output=output)

            # Filter out instances that do not contain soils data
            gi_scenario_soils_base = "{0}_wsoils".format(gi_scenario_base)
            scenario_geojson_wsoils = scenario.get_instances_as_geojson(indent=2, shorten=True,
                                                                        filter=lambda a: a.get('e_1_pedid') is not None)
            (gi_scenario_soils_wgs84, scenario_soils_geojson_wgs84_path), (gi_scenario_soils, scenario_soils_geojson_path) = \
                self._write_geojson_and_reproject(scenario_geojson_wsoils, gi_scenario_soils_base,
                                                  verbose=verbose, output=output)

            # Import scenario GeoJSON into GRASS
            self._import_vector_into_grass(scenario_geojson_path, gi_scenario_data_key,
                                           force=force, verbose=verbose, output=output)

            # Import scenario (instances with soils data) GeoJSON into GRASS
            self._import_vector_into_grass(scenario_soils_geojson_path, gi_scenario_soils_data_key,
                                           force=force, verbose=verbose, output=output)

            # Generate raster layers from vector-based GI Scenario
            # Raster for updating soil type
            self._rasterize(gi_scenario_soils_data_key, gi_scenario_soils_data_key,
                            column='e_1_pedid', labelcolumn='e_1_pednm',
                            rast_title='GI soil types',
                            verbose=verbose,
                            force=force,
                            redir_fp=output)
            # Raster for updating stratum type
            gi_scenario_strata = "gi_scenario_strata"
            self._rasterize(gi_scenario_data_key, gi_scenario_strata,
                            column='e_1_vegid', labelcolumn='e_1_vegnm',
                            rast_title='GI vegetation types',
                            verbose=verbose,
                            force=force,
                            redir_fp=output)

            # Raster for updating land use
            # Filter out instances that are not rain gardens (i.e. the only GI type for which we currently have a
            #   land use).
            scenario_geojson_landuse = scenario.get_instances_as_geojson(indent=2, shorten=True,
                                                                         filter=lambda a: a.get('type',
                                                                                                '') == 'Rain Garden')
            (gi_scenario_landuse_wgs84, scenario_landuse_geojson_wgs84_path), \
            (gi_scenario_landuse, scenario_landuse_geojson_path) = \
                self._write_geojson_and_reproject(scenario_geojson_landuse, gi_scenario_landuse_base,
                                                  verbose=verbose, output=output)
            # Import land use (i.e. instances that are rain gardens) GeoJSON into GRASS
            self._import_vector_into_grass(scenario_landuse_geojson_path, gi_scenario_landuse_data_key,
                                           force=force, verbose=verbose, output=output)

            # Search for raster value for rain gardens in RHESSys parameter DB
            rg_name = 'raingarden'
            rg_found = self.param_db.search(self.param_const.SEARCH_TYPE_HIERARCHICAL, 'landuse', rg_name,
                                            None, None, None, None, None, None, None, None)
            if not rg_found:
                raise RunException("Unable to find raingarden landuse class in parameter database")

            rg_id = [c[1][2] for c in self.param_db.classes.iteritems()][0]

            # Generate raster layer from vector-based GI Scenario
            # Raster for updating landuse type
            self._rasterize_single_value(gi_scenario_landuse_data_key, gi_scenario_landuse_data_key,
                                         value=rg_id, label=rg_name,
                                         rast_title='GI landuse types',
                                         verbose=verbose,
                                         force=force,
                                         redir_fp=output)

            # Write out updated landuse, stratum, and soil rasters and parameter definitions
            # Backup landuse raster
            self._backup_raster(self.grassMetadata['landuse_rast'])
            # Update landuse raster
            self._update_raster(self.grassMetadata['landuse_rast'], gi_scenario_landuse_data_key)
            # Generate parameter definition file for landuse raster
            self._generate_parameter_definitions_for_raster(self.grassMetadata['landuse_rast'], 'landuse',
                                                            verbose=verbose)
            # Backup stratum raster
            self._backup_raster(self.grassMetadata['stratum_rast'])
            # Update stratum raster
            self._update_raster(self.grassMetadata['stratum_rast'], gi_scenario_strata)
            # Generate parameter definition file for stratum raster
            self._generate_parameter_definitions_for_raster(self.grassMetadata['stratum_rast'], 'stratum',
                                                            verbose=verbose)
            # Backup soils raster
            self._backup_raster(self.grassMetadata['soil_rast'])
            # Update soils raster
            self._update_raster(self.grassMetadata['soil_rast'], gi_scenario_soils_data_key)
            # Generate parameter definition file for soil raster
            self._generate_parameter_definitions_for_raster(self.grassMetadata['soil_rast'], 'soil',
                                                            verbose=verbose)
            # Write metadata
            RHESSysMetadata.writeGRASSEntry(self.context, "{0}_rast".format(gi_scenario_landuse_data_key),
                                            gi_scenario_landuse_data_key)
            RHESSysMetadata.writeGRASSEntry(self.context, "{0}_rast".format(gi_scenario_soils_data_key),
                                            gi_scenario_soils_data_key)
            RHESSysMetadata.writeGRASSEntry(self.context, "{0}_rast".format(gi_scenario_strata), gi_scenario_strata)

            RHESSysMetadata.writeGRASSEntry(self.context, "{0}_vect".format(gi_scenario_data_key), gi_scenario_data_key)
            RHESSysMetadata.writeGRASSEntry(self.context, "{0}_vect".format(gi_scenario_soils_data_key),
                                            gi_scenario_soils_data_key)
            RHESSysMetadata.writeGRASSEntry(self.context, "{0}_vect".format(gi_scenario_landuse_data_key),
                                            gi_scenario_landuse_data_key)
            RHESSysMetadata.writeRHESSysEntry(self.context, gi_scenario_data_key, gi_scenario_data)

            if verbose:
                self.outfp.write('\n\nFinished parameterizing GI.\n')

            # Write processing history
            RHESSysMetadata.appendProcessingHistoryItem(self.context, RHESSysMetadata.getCommandLine())

        finally:
            if output:
                output.close()
Пример #7
0
    def run(self, *args, **kwargs):
        """ Create flow tables for multiple worldfiles

        Arguments:
        scenario_id -- int    ID of the GI Notebook scenario whose GI instances are to be parameterized.
        auth_token -- string    Authorization token to use for authenticating to the GI Notebook.
        host -- string    Hostname of GI Notebook server. Default: None.
        api_root -- string    The root of the API URL to use. Default: None.
        use_HTTPS -- boolean    Use HTTPS for communication with the GI Notebook.
        force -- boolean        Force overwrite of existing scenario output. Default: False.
        verbose -- boolean    Produce verbose output. Default: False.
        """
        scenario_id = kwargs.get('scenario_id')
        if scenario_id is None:
            raise RunException('Scenario ID was not specified.')
        auth_token = kwargs.get('auth_token')
        if auth_token is None:
            raise RunException('Authorization token was not specified.')
        host = kwargs.get('host', DEFAULT_HOSTNAME)
        api_root = kwargs.get('api_path', DEFAULT_API_ROOT)
        use_HTTPS = kwargs.get('use_HTTPS', False)
        force = kwargs.get('force', False)
        verbose = kwargs.get('verbose', False)

        self.checkMetadata()
        self.param_const, self.param_db = self._init_paramdb()
        self.paths = RHESSysPaths(self.context.projectDir,
                                  self.metadata['rhessys_dir'])

        gi_scenario_base = 'gi_scenario'
        gi_scenario_data = "{0}.geojson".format(gi_scenario_base)
        scenario_geojson_path = os.path.join(self.context.projectDir,
                                             gi_scenario_data)
        gi_scenario_soils_base = "{0}_wsoils".format(gi_scenario_base)
        gi_scenario_soils = "{0}.geojson".format(gi_scenario_soils_base)
        scenario_soils_geojson_path = os.path.join(self.context.projectDir,
                                                   gi_scenario_soils)
        gi_scenario_landuse_base = "{0}_landuse".format(gi_scenario_base)
        gi_scenario_landuse = "{0}.geojson".format(gi_scenario_landuse_base)
        scenario_landuse_geojson_path = os.path.join(self.context.projectDir,
                                                     gi_scenario_landuse)
        gi_scenario_data_key = 'gi_scenario_data'
        gi_scenario_soils_data_key = "{0}_soils".format(gi_scenario_data_key)
        gi_scenario_landuse_data_key = "{0}_landuse".format(
            gi_scenario_data_key)
        if gi_scenario_data_key in self.metadata:
            if verbose:
                self.outfp.write('Existing GI scenario found.\n')
            if force:
                if verbose:
                    self.outfp.write(
                        'Force option specified, overwriting existing GI scenario.\n'
                    )
                if os.path.exists(scenario_geojson_path):
                    os.unlink(scenario_geojson_path)
                if os.path.exists(scenario_soils_geojson_path):
                    os.unlink(scenario_soils_geojson_path)
                if os.path.exists(scenario_landuse_geojson_path):
                    os.unlink(scenario_landuse_geojson_path)
            else:
                raise RunException('Exiting.  Use force option to overwrite.')

        if verbose:
            output = None
        else:
            output = open('/dev/null')
        try:
            # Connect to GI Notebook and fetch GI instance information (in GeoJSON format)
            # for this scenario ID.
            if verbose:
                self.outfp.write(
                    "\nDownloading GI scenario {0} from GI database...\n".
                    format(scenario_id))
            nb = GINotebook(hostname=host,
                            api_root=api_root,
                            use_https=use_HTTPS,
                            auth_token=auth_token)
            scenario = nb.get_scenario(scenario_id)
            scenario_geojson = scenario.get_instances_as_geojson(indent=2,
                                                                 shorten=True)
            (gi_scenario_data_wgs84, scenario_geojson_wgs84_path), (gi_scenario_data, scenario_geojson_path) = \
                self._write_geojson_and_reproject(scenario_geojson, gi_scenario_base, verbose=verbose, output=output)

            # Filter out instances that do not contain soils data
            gi_scenario_soils_base = "{0}_wsoils".format(gi_scenario_base)
            scenario_geojson_wsoils = scenario.get_instances_as_geojson(
                indent=2,
                shorten=True,
                filter=lambda a: a.get('e_1_pedid') is not None)
            (gi_scenario_soils_wgs84, scenario_soils_geojson_wgs84_path), (gi_scenario_soils, scenario_soils_geojson_path) = \
                self._write_geojson_and_reproject(scenario_geojson_wsoils, gi_scenario_soils_base,
                                                  verbose=verbose, output=output)

            # Import scenario GeoJSON into GRASS
            self._import_vector_into_grass(scenario_geojson_path,
                                           gi_scenario_data_key,
                                           force=force,
                                           verbose=verbose,
                                           output=output)

            # Import scenario (instances with soils data) GeoJSON into GRASS
            self._import_vector_into_grass(scenario_soils_geojson_path,
                                           gi_scenario_soils_data_key,
                                           force=force,
                                           verbose=verbose,
                                           output=output)

            # Generate raster layers from vector-based GI Scenario
            # Raster for updating soil type
            self._rasterize(gi_scenario_soils_data_key,
                            gi_scenario_soils_data_key,
                            column='e_1_pedid',
                            labelcolumn='e_1_pednm',
                            rast_title='GI soil types',
                            verbose=verbose,
                            force=force,
                            redir_fp=output)
            # Raster for updating stratum type
            gi_scenario_strata = "gi_scenario_strata"
            self._rasterize(gi_scenario_data_key,
                            gi_scenario_strata,
                            column='e_1_vegid',
                            labelcolumn='e_1_vegnm',
                            rast_title='GI vegetation types',
                            verbose=verbose,
                            force=force,
                            redir_fp=output)

            # Raster for updating land use
            # Filter out instances that are not rain gardens (i.e. the only GI type for which we currently have a
            #   land use).
            scenario_geojson_landuse = scenario.get_instances_as_geojson(
                indent=2,
                shorten=True,
                filter=lambda a: a.get('type', '') == 'Rain Garden')
            (gi_scenario_landuse_wgs84, scenario_landuse_geojson_wgs84_path), \
            (gi_scenario_landuse, scenario_landuse_geojson_path) = \
                self._write_geojson_and_reproject(scenario_geojson_landuse, gi_scenario_landuse_base,
                                                  verbose=verbose, output=output)
            # Import land use (i.e. instances that are rain gardens) GeoJSON into GRASS
            self._import_vector_into_grass(scenario_landuse_geojson_path,
                                           gi_scenario_landuse_data_key,
                                           force=force,
                                           verbose=verbose,
                                           output=output)

            # Search for raster value for rain gardens in RHESSys parameter DB
            rg_name = 'raingarden'
            rg_found = self.param_db.search(
                self.param_const.SEARCH_TYPE_HIERARCHICAL, 'landuse', rg_name,
                None, None, None, None, None, None, None, None)
            if not rg_found:
                raise RunException(
                    "Unable to find raingarden landuse class in parameter database"
                )

            rg_id = [c[1][2] for c in self.param_db.classes.iteritems()][0]

            # Generate raster layer from vector-based GI Scenario
            # Raster for updating landuse type
            self._rasterize_single_value(gi_scenario_landuse_data_key,
                                         gi_scenario_landuse_data_key,
                                         value=rg_id,
                                         label=rg_name,
                                         rast_title='GI landuse types',
                                         verbose=verbose,
                                         force=force,
                                         redir_fp=output)

            # Write out updated landuse, stratum, and soil rasters and parameter definitions
            # Backup landuse raster
            self._backup_raster(self.grassMetadata['landuse_rast'])
            # Update landuse raster
            self._update_raster(self.grassMetadata['landuse_rast'],
                                gi_scenario_landuse_data_key)
            # Generate parameter definition file for landuse raster
            self._generate_parameter_definitions_for_raster(
                self.grassMetadata['landuse_rast'], 'landuse', verbose=verbose)
            # Backup stratum raster
            self._backup_raster(self.grassMetadata['stratum_rast'])
            # Update stratum raster
            self._update_raster(self.grassMetadata['stratum_rast'],
                                gi_scenario_strata)
            # Generate parameter definition file for stratum raster
            self._generate_parameter_definitions_for_raster(
                self.grassMetadata['stratum_rast'], 'stratum', verbose=verbose)
            # Backup soils raster
            self._backup_raster(self.grassMetadata['soil_rast'])
            # Update soils raster
            self._update_raster(self.grassMetadata['soil_rast'],
                                gi_scenario_soils_data_key)
            # Generate parameter definition file for soil raster
            self._generate_parameter_definitions_for_raster(
                self.grassMetadata['soil_rast'], 'soil', verbose=verbose)
            # Write metadata
            RHESSysMetadata.writeGRASSEntry(
                self.context, "{0}_rast".format(gi_scenario_landuse_data_key),
                gi_scenario_landuse_data_key)
            RHESSysMetadata.writeGRASSEntry(
                self.context, "{0}_rast".format(gi_scenario_soils_data_key),
                gi_scenario_soils_data_key)
            RHESSysMetadata.writeGRASSEntry(
                self.context, "{0}_rast".format(gi_scenario_strata),
                gi_scenario_strata)

            RHESSysMetadata.writeGRASSEntry(
                self.context, "{0}_vect".format(gi_scenario_data_key),
                gi_scenario_data_key)
            RHESSysMetadata.writeGRASSEntry(
                self.context, "{0}_vect".format(gi_scenario_soils_data_key),
                gi_scenario_soils_data_key)
            RHESSysMetadata.writeGRASSEntry(
                self.context, "{0}_vect".format(gi_scenario_landuse_data_key),
                gi_scenario_landuse_data_key)
            RHESSysMetadata.writeRHESSysEntry(self.context,
                                              gi_scenario_data_key,
                                              gi_scenario_data)

            if verbose:
                self.outfp.write('\n\nFinished parameterizing GI.\n')

            # Write processing history
            RHESSysMetadata.appendProcessingHistoryItem(
                self.context, RHESSysMetadata.getCommandLine())

        finally:
            if output:
                output.close()
Пример #8
0
    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())
         
Пример #9
0
    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())