def run(self, *args, **kwargs): """ Run the command: Acquire USGS DEM data. Arguments: coverage -- string Source dataset from which DEM tile should be extracted. outfile -- string The name of the DEM file to be written. File extension ".tif" will be added. demResolution list<float>[2] Two floating point numbers representing the desired X and Y output resolution of soil property raster maps; unit: meters. srs -- string Target spatial reference system of output, in EPSG:num format. verbose -- boolean Produce verbose output. Default: False. overwrite -- boolean Overwrite existing output. Default: False. """ coverage = kwargs.get('coverage', self.DEFAULT_COVERAGE) outfile = kwargs.get('outfile', None) demResolution = kwargs.get('demResolution', None) srs = kwargs.get('srs', None) verbose = kwargs.get('verbose', False) overwrite = kwargs.get('overwrite', False) self.checkMetadata() bbox = bboxFromString(self.studyArea['bbox_wgs84']) if not outfile: outfile = 'DEM' demFilename = "%s.tif" % (outfile) demResolutionX = demResolutionY = None if demResolution: demResolutionX = demResolution[0] demResolutionY = demResolution[1] if srs: if not isValidSrs(srs): msg = "ERROR: '%s' is not a valid spatial reference. Spatial reference must be of the form 'EPSG:XXXX', e.g. 'EPSG:32617'. For more information, see: http://www.spatialreference.org/" % (srs,) raise RunException(msg) else: # Default for UTM (centerLon, centerLat) = calculateBoundingBoxCenter(bbox) (utmZone, isNorth) = getUTMZoneFromCoordinates(centerLon, centerLat) srs = getEPSGStringForUTMZone(utmZone, isNorth) try: (dataFetched, urlFetched) = ecohydrolib.usgs.demwcs.getDEMForBoundingBox(self.context.config, self.context.projectDir, demFilename, bbox, srs, coverage=coverage, resx=demResolutionX, resy=demResolutionY, scale=0.01, overwrite=overwrite, verbose=verbose, outfp=self.outfp) except Exception as e: traceback.print_exc(file=self.outfp) raise RunException(e) if not dataFetched: raise RunException("Failed to download DEM data from URL {0}".format(urlFetched)) # Write metadata entries cmdline = GenericMetadata.getCommandLine() # Write metadata demFilepath = os.path.join(self.context.projectDir, demFilename) demSrs = getSpatialReferenceForRaster(demFilepath) GenericMetadata.writeStudyAreaEntry(self.context, 'dem_res_x', demSrs[0]) GenericMetadata.writeStudyAreaEntry(self.context, 'dem_res_y', demSrs[1]) GenericMetadata.writeStudyAreaEntry(self.context, 'dem_srs', srs) # Get rows and columns for DEM (columns, rows) = getDimensionsForRaster(demFilepath) GenericMetadata.writeStudyAreaEntry(self.context, 'dem_columns', columns) GenericMetadata.writeStudyAreaEntry(self.context, 'dem_rows', rows) # Write provenance asset = AssetProvenance(GenericMetadata.MANIFEST_SECTION) asset.name = 'dem' asset.dcIdentifier = demFilename asset.dcSource = urlFetched asset.dcTitle = "Digital Elevation Model ({0})".format(coverage) asset.dcPublisher = 'U.S. Geological Survey' asset.dcDescription = cmdline asset.processingNotes = "Elevation values rescaled from centimeters to meters. " asset.processingNotes += "Spatial grid resampled to {srs} with X resolution {xres} and Y resolution {yres}." asset.processingNotes = asset.processingNotes.format(srs=srs, xres=demSrs[0], yres=demSrs[1]) asset.writeToMetadata(self.context) # Write processing history GenericMetadata.appendProcessingHistoryItem(self.context, cmdline)
# Get DEM from DEMExplorer sys.stdout.write('Downloading DEM from Geoscience Australia web service...') sys.stdout.flush() tmpDEMFilename = "%s-TEMP.tif" % (outfile) (returnCode, demURL) = getDEMForBoundingBox(context.config, context.projectDir, tmpDEMFilename, bbox=bbox, coverage=args.demType, srs=t_srs) assert (returnCode) sys.stdout.write('done\n') tmpDEMFilepath = os.path.join(context.projectDir, tmpDEMFilename) demSrs = getSpatialReferenceForRaster(tmpDEMFilepath) resample = False if args.demResolution: demResolutionX = args.demResolution[0] demResolutionY = args.demResolution[1] if demSrs[0] != demResolutionX or demSrs[1] != demResolutionY: resample = True else: demResolutionX = demSrs[0] demResolutionY = demSrs[1] # Resample DEM to target srs and resolution if resample: sys.stdout.write("Resampling DEM to resolution %.2f x %.2f..." %
else: # Default for UTM (centerLon, centerLat) = calculateBoundingBoxCenter(bbox) (utmZone, isNorth) = getUTMZoneFromCoordinates(centerLon, centerLat) t_srs = getEPSGStringForUTMZone(utmZone, isNorth) # Get DEM from DEMExplorer sys.stdout.write('Downloading DEM from DEMExplorer...') sys.stdout.flush() tmpDEMFilename = "%s-TEMP.tif" % (outfile) (returnCode, demURL) = getDEMForBoundingBox(context.config, context.projectDir, tmpDEMFilename, bbox=bbox, coverage=args.demType, srs=t_srs) assert(returnCode) sys.stdout.write('done\n') tmpDEMFilepath = os.path.join(context.projectDir, tmpDEMFilename) demSrs = getSpatialReferenceForRaster(tmpDEMFilepath) resample = False if args.demResolution: demResolutionX = args.demResolution[0] demResolutionY = args.demResolution[1] if demSrs[0] != demResolutionX or demSrs[1] != demResolutionY: resample = True else: demResolutionX = demSrs[0] demResolutionY = demSrs[1] # Resample DEM to target srs and resolution if resample: sys.stdout.write("Resampling DEM to resolution %.2f x %.2f..." % (demResolutionX, demResolutionY) )
def rasterizeSSURGOFeatures(config, outputDir, featureFilename, featureLayername, featureAttrList, \ getResolutionFromRasterFileNamed=None, rasterResolutionX=None, rasterResolutionY=None): """ Create raster maps, in GeoTIFF format, for SSURGO attributes associated with SSURGO MapunitPoly/MapunitPolyExtended features @note Will silently exit if rasters already exist. @note If getResolutionFromRasterFileNamed as well as rasterResolutionX and rasterResolutionY are specified, output raster resolution will be determined from the file named by getResolutionFromRasterFileNamed. @param config onfigParser containing the section 'GDAL/OGR' and option 'PATH_OF_GDAL_RASTERIZE' @param outputDir String representing the absolute/relative path of the directory into which output rasters should be written @param featureFilename String representing the absolute/relative path of the input feature in ESRI shapefile or OGC GML format @param featureLayername String representing the name of feature layer whose features are to be rasterize @param featureAttrList List containing the SSURGO attributes for which raster maps are to be created @param getResolutionFromRasterFileNamed String representing the absolute path of an existing raster file from which the output raster resolution should be determined @param rasterResolutionX Float representing the X resolution of the output rasters @param rasterResolutionY Float representing the Y resolution of the output rasters @return Dictionary containing the keys for each soil attribute and values of the names of the raster files generated for that attribute @exception ConfigParser.NoSectionError @exception ConfigParser.NoOptionError @exception Exception if featureFilename is neither a SHP nor a GML file @exception IOError(errno.ENOTDIR) if outputDir is not a directory @exception IOError(errno.EACCESS) if outputDir is not writable @exception IOError(errno.EACCESS) if featureFilename is not readable @exception IOError(errno.ENOENT) if featureFilename is not a file @exception IOError(errno.EACCES) if getResolutionFromRasterFileNamed is not readable @exception ValueError if rasterResolutionX or rasterResolutionY are not floating point numbers greater than 0 @exception Exception if a gdal_rasterize command fails """ gdalCmdPath = config.get('GDAL/OGR', 'PATH_OF_GDAL_RASTERIZE') if not os.access(gdalCmdPath, os.X_OK): raise IOError( errno.EACCES, "The gdal_rasterize binary at %s is not executable" % gdalCmdPath) gdalCmdPath = os.path.abspath(gdalCmdPath) if not os.path.isdir(outputDir): raise IOError(errno.ENOTDIR, "Output directory %s is not a directory" % (outputDir, )) if not os.access(outputDir, os.W_OK): raise IOError( errno.EACCES, "Not allowed to write to output directory %s" % (outputDir, )) outputDir = os.path.abspath(outputDir) featureFilepath = os.path.join(outputDir, featureFilename) if not os.access(featureFilepath, os.R_OK): raise IOError( errno.EACCES, "Not allowed to read feature file %s" % (featureFilepath, )) if not os.path.isfile(featureFilepath): raise IOError(errno.ENOENT, "Feature file %s does not exist" % (featureFilepath, )) if getResolutionFromRasterFileNamed is None: rasterResolutionX = float(rasterResolutionX) if rasterResolutionX <= 0.0: raise ValueError("rasterResolutionX must be > 0.0") rasterResolutionY = float(rasterResolutionY) if rasterResolutionY <= 0.0: raise ValueError("rasterResolutionY must be > 0.0") else: if not os.access(getResolutionFromRasterFileNamed, os.R_OK): raise IOError(errno.EACCES, "Not allowed to read existing raster file %s from which to get resolution" % \ (getResolutionFromRasterFileNamed)) featureType = os.path.splitext(featureFilepath)[1].lstrip('.').upper() # Get conversion factor for converting soil feature linear unit into meters if featureType == "GML": soilMeterConvFactor = getMeterConversionFactorForLinearUnitOfGMLfile( featureFilepath) elif featureType == "SHP": soilMeterConvFactor = getMeterConversionFactorForLinearUnitOfShapefile( featureFilepath) else: raise Exception( "Argument featureFilename must be either a GML or SHP file") # Determine soil property raster map resolution, in the same linear units as soil feature layer if getResolutionFromRasterFileNamed is not None: # Use DEM raster resolution as soil property raster resolution #sys.stderr.write("Using input raster resolution for soil property rasters ...\n") demPixelSizeAndUnits = getSpatialReferenceForRaster( getResolutionFromRasterFileNamed) # Default, DEM raster linear unit is the same as soil feature linear units rasterResolutionX = demPixelSizeAndUnits[0] rasterResolutionY = demPixelSizeAndUnits[1] # Get DEM raster linear units demSrs = osr.SpatialReference() if demSrs.ImportFromWkt( demPixelSizeAndUnits[4]) == 0: # OGRERR_NONE = 0 #sys.stderr.write("Spatial reference found for DEM, converting DEM linear units to soil feature linear units\n") demMeterConvFactor = demSrs.GetLinearUnits() if soilMeterConvFactor != demMeterConvFactor: # Soil feature linear units differ from DEM linear units, convert to meters rasterResolutionX = (demPixelSizeAndUnits[0] * demMeterConvFactor) rasterResolutionY = (demPixelSizeAndUnits[1] * demMeterConvFactor) else: pass #sys.stderr.write("No spatial reference found for DEM, assuming DEM linear units are the same as soil feature linear units\n") else: # Use user-specified soil raster resolution, but convert from meters into soil feature linear units pass #sys.stderr.write("Using user-supplied resolution, %d meters x %d meters, for soil property rasters ...\n" % (rasterResolutionX, rasterResolutionY)) # Convert output raster resolution from meters into the linear units of the soil feature shapefile rasterResolutionX = rasterResolutionX / soilMeterConvFactor rasterResolutionY = rasterResolutionY / soilMeterConvFactor # Build base filename for all output raster maps rasterFilenameProto = os.path.splitext(featureFilename)[0] filesCreated = dict() # Rasterize soil feature attributes using gdal_rasterize for attr in featureAttrList: rasterFilename = "%s_%s.tif" % (rasterFilenameProto, attr) filesCreated[attr] = rasterFilename rasterFilepath = os.path.join(outputDir, rasterFilename) if not os.path.exists(rasterFilepath): gdalCommand = "%s -q -of GTiff -co 'COMPRESS=LZW' -tr %d %d -a_nodata -9999 -a %s -l %s %s %s" % ( gdalCmdPath, rasterResolutionX, rasterResolutionY, attr, featureLayername, featureFilepath, rasterFilepath) #print gdalCommand returnCode = os.system(gdalCommand) if returnCode != 0: raise Exception( "GDAL command %s failed. Check spatial reference system of input vector dataset (geographic coordinate systems may not work)." % (gdalCommand, )) return filesCreated
bbox = bboxFromString(studyArea['bbox_wgs84']) demResolutionX = float(studyArea['dem_res_x']) demResolutionY = float(studyArea['dem_res_y']) demColumns = int(studyArea['dem_columns']) demRows = int(studyArea['dem_rows']) srs = studyArea['dem_srs'] rasterFilename = "%s%stif" % (outfile, os.extsep) # Overwrite raster if already present rasterFilepath = os.path.join(context.projectDir, rasterFilename) if os.path.exists(rasterFilepath): os.unlink(rasterFilepath) # Determine whether we need to resample resample = False rasterMetadata = getSpatialReferenceForRaster(inRasterPath) rasterSrs = rasterMetadata[5] rasterX = float(rasterMetadata[0]) rasterY = float(rasterMetadata[1]) if (rasterSrs != srs): resample = True elif (not args.noresample) and ((rasterX != demResolutionX) or (rasterY != demResolutionY)): resample = True if args.clip: processingNotes = "Clipping %s raster %s to DEM extent" % (args.type, inRasterPath) manifest = GenericMetadata.readManifestEntries(context) demFilename = manifest['dem'] demFilepath = os.path.join(context.projectDir, demFilename)
configFile = None if args.configfile: configFile = args.configfile context = Context(args.projectDir, configFile) if not context.config.has_option('GDAL/OGR', 'PATH_OF_GDAL_WARP'): sys.exit("Config file %s does not define option %s in section %s" & \ (args.configfile, 'GDAL/OGR', 'PATH_OF_GDAL_WARP')) if not os.access(args.demfile, os.R_OK): raise IOError(errno.EACCES, "Not allowed to read input DEM %s" (args.demfile, )) inDEMPath = os.path.abspath(args.demfile) inSpatialMetadata = getSpatialReferenceForRaster(inDEMPath) resample = False s_srs = inSpatialMetadata[5] t_srs = s_srs if args.t_srs: if not isValidSrs(args.t_srs): sys.exit( textwrap.fill( "ERROR: '%s' is not a valid spatial reference. Spatial reference must be of the form 'EPSG:XXXX', e.g. 'EPSG:32617'. For more information, see: http://www.spatialreference.org/" % (args.t_srs, ))) if s_srs != args.t_srs: t_srs = args.t_srs resample = True
def rasterizeSSURGOFeatures(config, outputDir, featureFilename, featureLayername, featureAttrList, \ getResolutionFromRasterFileNamed=None, rasterResolutionX=None, rasterResolutionY=None): """ Create raster maps, in GeoTIFF format, for SSURGO attributes associated with SSURGO MapunitPoly/MapunitPolyExtended features @note Will silently exit if rasters already exist. @note If getResolutionFromRasterFileNamed as well as rasterResolutionX and rasterResolutionY are specified, output raster resolution will be determined from the file named by getResolutionFromRasterFileNamed. @param config onfigParser containing the section 'GDAL/OGR' and option 'PATH_OF_GDAL_RASTERIZE' @param outputDir String representing the absolute/relative path of the directory into which output rasters should be written @param featureFilename String representing the absolute/relative path of the input feature in ESRI shapefile or OGC GML format @param featureLayername String representing the name of feature layer whose features are to be rasterize @param featureAttrList List containing the SSURGO attributes for which raster maps are to be created @param getResolutionFromRasterFileNamed String representing the absolute path of an existing raster file from which the output raster resolution should be determined @param rasterResolutionX Float representing the X resolution of the output rasters @param rasterResolutionY Float representing the Y resolution of the output rasters @return Dictionary containing the keys for each soil attribute and values of the names of the raster files generated for that attribute @exception ConfigParser.NoSectionError @exception ConfigParser.NoOptionError @exception Exception if featureFilename is neither a SHP nor a GML file @exception IOError(errno.ENOTDIR) if outputDir is not a directory @exception IOError(errno.EACCESS) if outputDir is not writable @exception IOError(errno.EACCESS) if featureFilename is not readable @exception IOError(errno.ENOENT) if featureFilename is not a file @exception IOError(errno.EACCES) if getResolutionFromRasterFileNamed is not readable @exception ValueError if rasterResolutionX or rasterResolutionY are not floating point numbers greater than 0 @exception Exception if a gdal_rasterize command fails """ gdalCmdPath = config.get('GDAL/OGR', 'PATH_OF_GDAL_RASTERIZE') if not os.access(gdalCmdPath, os.X_OK): raise IOError(errno.EACCES, "The gdal_rasterize binary at %s is not executable" % gdalCmdPath) gdalCmdPath = os.path.abspath(gdalCmdPath) if not os.path.isdir(outputDir): raise IOError(errno.ENOTDIR, "Output directory %s is not a directory" % (outputDir,)) if not os.access(outputDir, os.W_OK): raise IOError(errno.EACCES, "Not allowed to write to output directory %s" % (outputDir,)) outputDir = os.path.abspath(outputDir) featureFilepath = os.path.join(outputDir, featureFilename) if not os.access(featureFilepath, os.R_OK): raise IOError(errno.EACCES, "Not allowed to read feature file %s" % (featureFilepath,)) if not os.path.isfile(featureFilepath): raise IOError(errno.ENOENT, "Feature file %s does not exist" % (featureFilepath,)) if getResolutionFromRasterFileNamed is None: rasterResolutionX = float(rasterResolutionX) if rasterResolutionX <= 0.0: raise ValueError("rasterResolutionX must be > 0.0") rasterResolutionY = float(rasterResolutionY) if rasterResolutionY <= 0.0: raise ValueError("rasterResolutionY must be > 0.0") else: if not os.access(getResolutionFromRasterFileNamed, os.R_OK): raise IOError(errno.EACCES, "Not allowed to read existing raster file %s from which to get resolution" % \ (getResolutionFromRasterFileNamed)) featureType = os.path.splitext(featureFilepath)[1].lstrip('.').upper() # Get conversion factor for converting soil feature linear unit into meters if featureType == "GML": soilMeterConvFactor = getMeterConversionFactorForLinearUnitOfGMLfile(featureFilepath) elif featureType == "SHP": soilMeterConvFactor = getMeterConversionFactorForLinearUnitOfShapefile(featureFilepath) else: raise Exception("Argument featureFilename must be either a GML or SHP file") # Determine soil property raster map resolution, in the same linear units as soil feature layer if getResolutionFromRasterFileNamed is not None: # Use DEM raster resolution as soil property raster resolution #sys.stderr.write("Using input raster resolution for soil property rasters ...\n") demPixelSizeAndUnits = getSpatialReferenceForRaster(getResolutionFromRasterFileNamed) # Default, DEM raster linear unit is the same as soil feature linear units rasterResolutionX = demPixelSizeAndUnits[0] rasterResolutionY = demPixelSizeAndUnits[1] # Get DEM raster linear units demSrs = osr.SpatialReference() if demSrs.ImportFromWkt(demPixelSizeAndUnits[4]) == 0: # OGRERR_NONE = 0 #sys.stderr.write("Spatial reference found for DEM, converting DEM linear units to soil feature linear units\n") demMeterConvFactor = demSrs.GetLinearUnits() if soilMeterConvFactor != demMeterConvFactor: # Soil feature linear units differ from DEM linear units, convert to meters rasterResolutionX = (demPixelSizeAndUnits[0] * demMeterConvFactor) rasterResolutionY = (demPixelSizeAndUnits[1] * demMeterConvFactor) else: pass #sys.stderr.write("No spatial reference found for DEM, assuming DEM linear units are the same as soil feature linear units\n") else: # Use user-specified soil raster resolution, but convert from meters into soil feature linear units pass #sys.stderr.write("Using user-supplied resolution, %d meters x %d meters, for soil property rasters ...\n" % (rasterResolutionX, rasterResolutionY)) # Convert output raster resolution from meters into the linear units of the soil feature shapefile rasterResolutionX = rasterResolutionX / soilMeterConvFactor rasterResolutionY = rasterResolutionY / soilMeterConvFactor # Build base filename for all output raster maps rasterFilenameProto = os.path.splitext(featureFilename)[0] filesCreated = dict() # Rasterize soil feature attributes using gdal_rasterize for attr in featureAttrList: rasterFilename = "%s_%s.tif" % (rasterFilenameProto, attr) filesCreated[attr] = rasterFilename rasterFilepath = os.path.join(outputDir, rasterFilename) if not os.path.exists(rasterFilepath): gdalCommand = "%s -q -of GTiff -co 'COMPRESS=LZW' -tr %d %d -a_nodata -9999 -a %s -l %s %s %s" % (gdalCmdPath, rasterResolutionX, rasterResolutionY, attr, featureLayername, featureFilepath, rasterFilepath) #print gdalCommand returnCode = os.system(gdalCommand) if returnCode != 0: raise Exception("GDAL command %s failed. Check spatial reference system of input vector dataset (geographic coordinate systems may not work)." % (gdalCommand,)) return filesCreated
cmdline = GenericMetadata.getCommandLine() configFile = None if args.configfile: configFile = args.configfile context = Context(args.projectDir, configFile) if not context.config.has_option('GDAL/OGR', 'PATH_OF_GDAL_WARP'): sys.exit("Config file %s does not define option %s in section %s" & \ (args.configfile, 'GDAL/OGR', 'PATH_OF_GDAL_WARP')) if not os.access(args.demfile, os.R_OK): raise IOError(errno.EACCES, "Not allowed to read input DEM %s" (args.demfile,)) inDEMPath = os.path.abspath(args.demfile) inSpatialMetadata = getSpatialReferenceForRaster(inDEMPath) resample = False s_srs = inSpatialMetadata[5] t_srs = s_srs if args.t_srs: if not isValidSrs(args.t_srs): sys.exit(textwrap.fill("ERROR: '%s' is not a valid spatial reference. Spatial reference must be of the form 'EPSG:XXXX', e.g. 'EPSG:32617'. For more information, see: http://www.spatialreference.org/" % (args.t_srs,) ) ) if s_srs != args.t_srs: t_srs = args.t_srs resample = True if args.demResolution: if args.demResolution[0] != inSpatialMetadata[0] or args.demResolution[1] != inSpatialMetadata[1]: resample = True
bbox = bboxFromString(studyArea['bbox_wgs84']) demResolutionX = float(studyArea['dem_res_x']) demResolutionY = float(studyArea['dem_res_y']) demColumns = studyArea['dem_columns'] demRows = studyArea['dem_rows'] srs = studyArea['dem_srs'] rasterFilename = "%s%stif" % (outfile, os.extsep) # Overwrite raster if already present rasterFilepath = os.path.join(context.projectDir, rasterFilename) if os.path.exists(rasterFilepath): os.unlink(rasterFilepath) # Determine whether we need to resample resample = False rasterMetadata = getSpatialReferenceForRaster(inRasterPath) rasterSrs = rasterMetadata[5] rasterX = float(rasterMetadata[0]) rasterY = float(rasterMetadata[1]) if (rasterSrs != srs): resample = True elif (not args.noresample) and ( (rasterX != demResolutionX) or (rasterY != demResolutionY) ): resample = True if resample: # Reproject raster, copying into project directory in the process processingNotes = "Resampling %s raster from %s to %s, spatial resolution (%.2f, %.2f) to (%.2f, %.2f)" % \ (args.type, rasterSrs, srs, rasterX, rasterX, demResolutionX, demResolutionY) sys.stdout.write("%s..." % (processingNotes,) ) resampleRaster(context.config, context.projectDir, inRasterPath, rasterFilepath, \