(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) sys.stdout.write('\nRunning RHESSys to redefine worldfile with vegetation carbon stores...') sys.stdout.flush() cmdArgs = rhessysCmd.split() process = Popen(cmdArgs, cwd=paths.RHESSYS_DIR, 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\nRHESSys failed, returning %s" % (process.returncode,) )
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())
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) if args.verbose: print(rhessysCmd) sys.stdout.write( '\nRunning RHESSys to redefine worldfile with vegetation carbon stores...') sys.stdout.flush() cmdArgs = rhessysCmd.split() process = Popen(cmdArgs, cwd=paths.RHESSYS_DIR, 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\nRHESSys failed, returning %s" % (process.returncode, ))