def null_define(rastlist, NoData_Value): """ Simple batch NoData setting function. Makes raster data more arcmap viewing friendly Function inputs a list of raster (usually tifs) files and sets no data values. This function does not actually change the raster values in any way, and simply defines which numerical values to be considered NoData in metadata. :param rastlist: list of rasters for which to set nodata value :param NoData_Value: Value to declare as NoData (usually 0 or -9999) :return rastlist: returns list of modified files """ rastlist = enf_rastlist(rastlist) # iterate through each file in the filelist and set nodata values for rastname in rastlist: arcpy.SetRasterProperties_management(rastname, data_type="#", statistics="#", stats_file="#", nodata="1 " + str(NoData_Value)) print("Set nulls in {0}".format(rastname)) return rastlist
def clip_to_shape(rasterlist, shapefile, outdir = False): """ Simple batch clipping script to clip rasters to shapefiles. :param rasterlist: single file, list of files, or directory for which to clip rasters :param shapefile: shapefile to which rasters will be clipped :param outdir: desired output directory. If no output directory is specified, the new files will simply have '_c' added as a suffix. :return output_filelist: list of files created by this function. """ rasterlist = enf_rastlist(rasterlist) output_filelist = [] # ensure output directorycore.exists if outdir and not os.path.exists(outdir): os.makedirs(outdir) for raster in rasterlist: # create output filename with "c" suffix outname = core.create_outname(outdir,raster,'c') # perform double clip , first using clip_management (preserves no data values) # then using arcpy.sa module which can actually do clipping geometry unlike the management tool. arcpy.Clip_management(raster, "#", outname, shapefile, "ClippingGeometry") out = ExtractByMask(outname, shapefile) out.save(outname) output_filelist.append(outname) print("Clipped and saved: {0}".format(outname)) return output_filelist
def null_set_range(rastlist, high_thresh = None, low_thresh = None, NoData_Value = None): """ Changes values within a certain range to NoData similar to raster.null_define, but can take an entire range of values to set to NoData. useful in filtering obviously erroneous high or low values from a raster dataset. inputs: rastlist list of files for which to set NoData values. easily created with "core.list_files" function high_thresh will set all values above this to NoData low_thresh will set all values below this to NoData """ # sanitize filelist input rastlist = enf_rastlist(rastlist) # iterate through each file in the filelist and set nodata values for rastname in rastlist: #load raster as numpy array and save spatial referencing. rast, meta = to_numpy(rastname) if not NoData_Value == None: NoData_Value = meta.NoData_Value if not high_thresh == None: rast[rast >= high_thresh] = NoData_Value if not low_thresh == None: rast[rast <= low_thresh] = NoData_Value from_numpy(rast, meta, rastname) arcpy.SetRasterProperties_management(rastname, data_type="#",statistics="#", stats_file = "#", nodata = "1 " + str(NoData_Value)) return
def null_define(rastlist, NoData_Value): """ Simple batch NoData setting function. Makes raster data more arcmap viewing friendly Function inputs a list of raster (usually tifs) files and sets no data values. This function does not actually change the raster values in any way, and simply defines which numerical values to be considered NoData in metadata. inputs: rastlist list of files for which to set NoData values. easily created with "core.list_files" function NoData_Value Value to declare as NoData (usually 0 or -9999) Quiet Set Quiet to 'True' if you don't want anything printed to screen. Defaults to 'False' if left blank. """ rastlist = enf_rastlist(rastlist) # iterate through each file in the filelist and set nodata values for rastname in rastlist: arcpy.SetRasterProperties_management(rastname,data_type="#",statistics="#", stats_file="#",nodata="1 "+str(NoData_Value)) print("Set nulls in {0}".format(rastname)) return
def clip_to_shape(rasterlist, shapefile, outdir = False): """ Simple batch clipping script to clip rasters to shapefiles. Inputs: rasterlist single file, list of files, or directory for which to clip rasters shapefile shapefile to which rasters will be clipped outdir desired output directory. If no output directory is specified, the new files will simply have '_c' added as a suffix. """ rasterlist = enf_rastlist(rasterlist) # ensure output directorycore.exists if outdir and not os.path.exists(outdir): os.makedirs(outdir) for raster in rasterlist: # create output filename with "c" suffix outname = core.create_outname(outdir,raster,'c') # perform double clip , first using clip_management (preserves no data values) # then using arcpy.sa module which can actually do clipping geometry unlike the management tool. arcpy.Clip_management(raster, "#", outname, shapefile, "ClippingGeometry") out = ExtractByMask(outname, shapefile) out.save(outname) print("Clipped and saved: {0}".format(outname)) return
def in_dir(dir_name, recursive=False): """ lists all the rasters in an input directory """ rast_list = core.list_files(recursive, dir_name) rast_list = enf_rastlist(rast_list) print("Found {0} file with valid raster format".format(len(rast_list))) return rast_list
def in_dir(dir_name, recursive = False): """ lists all the rasters in an input directory """ rast_list = core.list_files(recursive, dir_name) rast_list = enf_rastlist(rast_list) print("Found {0} file with valid raster format".format(len(rast_list))) return rast_list
def new_mosaic(rasterpaths, output_path, mosaic_method=None, cell_size=None, number_of_bands=None): """ Simply creates a new raster dataset mosaic of input rasters by wrapping the arcpy.MosaicToNewRaster_management function. learn more about the fields here http://help.arcgis.com/en/arcgisdesktop/10.0/help/index.html#//001700000098000000 :param rasterpaths: list of complete filepaths to raster data to mosaic :param output_path: place to save new mosaic raster dataset :param mosaic_method: options are "FIRST", "LAST", "BLEND", "MEAN", "MINIMUM","MAXIMUM" :param cell_size: of format "[cellwidth] [cellheight]" in the appropriate linear units, usually meters. :return output_path: returns filepath to new file, same as input ``output_path`` """ # set up input parameters if mosaic_method is None: mosaic_method = "FIRST" if cell_size is not None: print("using custom cell size of '{0}'".format(cell_size)) if number_of_bands is None: number_of_bands = 1 rasterpaths = enf_rastlist(rasterpaths) # get some metadata about the first raster in the mosaic numpy, meta = to_numpy(rasterpaths[0]) # check output directories and set up inputs for arcpy function outdir, outname = os.path.split(output_path) if not os.path.exists(outdir): os.makedirs(outdir) arcpy.MosaicToNewRaster_management( rasterpaths, outdir, outname, None, # coordinate system meta.pixel_type, cell_size, str(number_of_bands), mosaic_method=mosaic_method) print("Created raster mosaic at {0}".format(output_path)) return output_path
def in_dir(dir_name, recursive = False): """ Lists all the rasters in an input directory. finds all formats supported by ``raster.enf_rastlist()``. :param dir_name: directory to search rasters for :param recursive: Set to "True" to search within subfolders of input directory "dir_name" """ rast_list = core.list_files(recursive, dir_name) rast_list = enf_rastlist(rast_list) print("Found {0} file with valid raster format".format(len(rast_list))) return rast_list
def in_dir(dir_name, recursive=False): """ Lists all the rasters in an input directory. finds all formats supported by ``raster.enf_rastlist()``. :param dir_name: directory to search rasters for :param recursive: Set to "True" to search within subfolders of input directory "dir_name" """ rast_list = core.list_files(recursive, dir_name) rast_list = enf_rastlist(rast_list) print("Found {0} file with valid raster format".format(len(rast_list))) return rast_list
def null_set_range(rastlist, high_thresh=None, low_thresh=None, NoData_Value=None): """ Changes values within a certain range to NoData. similar to ``raster.null_define``, but can take an entire range of values to set to NoData. useful in filtering obviously erroneous high or low values from a raster dataset. :param rastlist: list of rasters for which to set no dta values :param high_thresh: will set all values above this to NoData :param low_thresh: will set all values below this to NoData :return rastlist: list of all rasters modified by this function """ # sanitize filelist input rastlist = enf_rastlist(rastlist) # iterate through each file in the filelist and set nodata values for rastname in rastlist: #load raster as numpy array and save spatial referencing. rast, meta = to_numpy(rastname) if not NoData_Value is None: NoData_Value = meta.NoData_Value if not high_thresh is None: rast[rast >= high_thresh] = NoData_Value if not low_thresh is None: rast[rast <= low_thresh] = NoData_Value from_numpy(rast, meta, rastname) try: arcpy.SetRasterProperties_management(rastname, data_type="#", statistics="#", stats_file="#", nodata="1 " + str(NoData_Value)) except RuntimeError: print("failed to set nodata in {0}".format(rastname)) return
def new_mosaic(rasterpaths, output_path, mosaic_method = None, cell_size = None, number_of_bands = None): """ Simply creates a new raster dataset mosaic of input rasters by wrapping the arcpy.MosaicToNewRaster_management function. learn more about the fields here http://help.arcgis.com/en/arcgisdesktop/10.0/help/index.html#//001700000098000000 :param rasterpaths: list of complete filepaths to raster data to mosaic :param output_path: place to save new mosaic raster dataset :param mosaic_method: options are "FIRST", "LAST", "BLEND", "MEAN", "MINIMUM","MAXIMUM" :param cell_size: of format "[cellwidth] [cellheight]" in the appropriate linear units, usually meters. :return output_path: returns filepath to new file, same as input ``output_path`` """ # set up input parameters if mosaic_method is None: mosaic_method = "FIRST" if cell_size is not None: print("using custom cell size of '{0}'".format(cell_size)) if number_of_bands is None: number_of_bands = 1 rasterpaths = enf_rastlist(rasterpaths) # get some metadata about the first raster in the mosaic numpy, meta = to_numpy(rasterpaths[0]) # check output directories and set up inputs for arcpy function outdir, outname = os.path.split(output_path) if not os.path.exists(outdir): os.makedirs(outdir) arcpy.MosaicToNewRaster_management(rasterpaths, outdir, outname, None, # coordinate system meta.pixel_type, cell_size, str(number_of_bands), mosaic_method = mosaic_method) print("Created raster mosaic at {0}".format(output_path)) return output_path
def null_set_range(rastlist, high_thresh=None, low_thresh=None, NoData_Value=None): """ Changes values within a certain range to NoData similar to raster.null_define, but can take an entire range of values to set to NoData. useful in filtering obviously erroneous high or low values from a raster dataset. inputs: rastlist list of files for which to set NoData values. easily created with "core.list_files" function high_thresh will set all values above this to NoData low_thresh will set all values below this to NoData """ # sanitize filelist input rastlist = enf_rastlist(rastlist) # iterate through each file in the filelist and set nodata values for rastname in rastlist: #load raster as numpy array and save spatial referencing. rast, meta = to_numpy(rastname) if not NoData_Value == None: NoData_Value = meta.NoData_Value if not high_thresh == None: rast[rast >= high_thresh] = NoData_Value if not low_thresh == None: rast[rast <= low_thresh] = NoData_Value from_numpy(rast, meta, rastname) arcpy.SetRasterProperties_management(rastname, data_type="#", statistics="#", stats_file="#", nodata="1 " + str(NoData_Value)) return
def null_set_range(rastlist, high_thresh = None, low_thresh = None, NoData_Value = None): """ Changes values within a certain range to NoData. similar to ``raster.null_define``, but can take an entire range of values to set to NoData. useful in filtering obviously erroneous high or low values from a raster dataset. :param rastlist: list of rasters for which to set no dta values :param high_thresh: will set all values above this to NoData :param low_thresh: will set all values below this to NoData :return rastlist: list of all rasters modified by this function """ # sanitize filelist input rastlist = enf_rastlist(rastlist) # iterate through each file in the filelist and set nodata values for rastname in rastlist: #load raster as numpy array and save spatial referencing. rast, meta = to_numpy(rastname) if not NoData_Value is None: NoData_Value = meta.NoData_Value if not high_thresh is None: rast[rast >= high_thresh] = NoData_Value if not low_thresh is None: rast[rast <= low_thresh] = NoData_Value from_numpy(rast, meta, rastname) try: arcpy.SetRasterProperties_management(rastname, data_type = "#", statistics = "#", stats_file = "#", nodata = "1 " + str(NoData_Value)) except RuntimeError: print("failed to set nodata in {0}".format(rastname)) return
def null_define(rastlist, NoData_Value): """ Simple batch NoData setting function. Makes raster data more arcmap viewing friendly Function inputs a list of raster (usually tifs) files and sets no data values. This function does not actually change the raster values in any way, and simply defines which numerical values to be considered NoData in metadata. :param rastlist: list of rasters for which to set nodata value :param NoData_Value: Value to declare as NoData (usually 0 or -9999) :return rastlist: returns list of modified files """ rastlist = enf_rastlist(rastlist) # iterate through each file in the filelist and set nodata values for rastname in rastlist: arcpy.SetRasterProperties_management(rastname,data_type="#",statistics="#", stats_file="#",nodata="1 "+str(NoData_Value)) print("Set nulls in {0}".format(rastname)) return rastlist
def project_resample(filelist, reference_file, outdir=False, resampling_type=None, cell_size=None): """ Wrapper for multiple arcpy projecting functions. Projects to reference file Inputs a filelist and a reference file, then projects all rasters or feature classes in the filelist to match the projection of the reference file. Writes new files with a "_p" appended to the end of the input filenames. This also will perform resampling. Inputs: filelist list of files to be projected outdir optional desired output directory. If none is specified, output files will be named with '_p' as a suffix. reference_file Either a file with the desired projection, or a .prj file. resampling type exactly as the input for arcmaps project_Raster_management function cell_size exactly as the input for arcmaps project_Raster_management function Output: Spatial reference spatial referencing information for further checking. """ output_filelist = [] # sanitize inputs core.exists(reference_file) rasterlist = enf_rastlist(filelist) featurelist = core.enf_featlist(filelist) cleanlist = rasterlist + featurelist # ensure output directory exists if not os.path.exists(outdir): os.makedirs(outdir) # grab data about the spatial reference of the reference file. (prj or otherwise) if reference_file[-3:] == 'prj': Spatial_Reference = arcpy.SpatialReference(reference_file) else: Spatial_Reference = arcpy.Describe(reference_file).spatialReference # determine cell size if cell_size is None: cx = arcpy.GetRasterProperties_management(reference_file, "CELLSIZEX").getOutput(0) cy = arcpy.GetRasterProperties_management(reference_file, "CELLSIZEY").getOutput(0) cell_size = "{0} {1}".format(cx, cy) # determine wether coordinate system is projected or geographic and print info if Spatial_Reference.type == 'Projected': print('Found {0} projected coord system'.format( Spatial_Reference.PCSName)) else: print('Found {0} geographic coord system'.format( Spatial_Reference.GCSName)) for filename in cleanlist: # create the output filename outname = core.create_outname(outdir, filename, 'p') output_filelist.append(Spatial_Reference) # use ProjectRaster_management for rast files if is_rast(filename): arcpy.ProjectRaster_management(filename, outname, Spatial_Reference, resampling_type, cell_size) print('Wrote projected and resampled file to {0}'.format(outname)) # otherwise, use Project_management for featureclasses and featurelayers else: arcpy.Project_management(filename, outname, Spatial_Reference) print('Wrote projected file to {0}'.format(outname)) print("finished projecting!") return output_filelist
def project_resample(filelist, reference_file, outdir = False, resampling_type = None, cell_size = None): """ Wrapper for multiple arcpy projecting functions. Projects to reference file Inputs a filelist and a reference file, then projects all rasters or feature classes in the filelist to match the projection of the reference file. Writes new files with a "_p" appended to the end of the input filenames. This also will perform resampling. Inputs: filelist list of files to be projected outdir optional desired output directory. If none is specified, output files will be named with '_p' as a suffix. reference_file Either a file with the desired projection, or a .prj file. resampling type exactly as the input for arcmaps project_Raster_management function cell_size exactly as the input for arcmaps project_Raster_management function Output: Spatial reference spatial referencing information for further checking. """ output_filelist = [] # sanitize inputs core.exists(reference_file) rasterlist = enf_rastlist(filelist) featurelist = core.enf_featlist(filelist) cleanlist = rasterlist + featurelist # ensure output directory exists if not os.path.exists(outdir): os.makedirs(outdir) # grab data about the spatial reference of the reference file. (prj or otherwise) if reference_file[-3:]=='prj': Spatial_Reference = arcpy.SpatialReference(reference_file) else: Spatial_Reference = arcpy.Describe(reference_file).spatialReference # determine cell size if cell_size is None: cx = arcpy.GetRasterProperties_management(reference_file, "CELLSIZEX").getOutput(0) cy = arcpy.GetRasterProperties_management(reference_file, "CELLSIZEY").getOutput(0) cell_size = "{0} {1}".format(cx,cy) # determine wether coordinate system is projected or geographic and print info if Spatial_Reference.type == 'Projected': print('Found {0} projected coord system'.format(Spatial_Reference.PCSName)) else: print('Found {0} geographic coord system'.format(Spatial_Reference.GCSName)) for filename in cleanlist: # create the output filename outname = core.create_outname(outdir, filename, 'p') output_filelist.append(Spatial_Reference) # use ProjectRaster_management for rast files if is_rast(filename): arcpy.ProjectRaster_management(filename, outname, Spatial_Reference, resampling_type, cell_size) print('Wrote projected and resampled file to {0}'.format(outname)) # otherwise, use Project_management for featureclasses and featurelayers else: arcpy.Project_management(filename,outname,Spatial_Reference) print('Wrote projected file to {0}'.format(outname)) print("finished projecting!") return output_filelist
def many_stats(rasterlist, outdir, outname, saves=['AVG', 'NUM', 'STD', 'SUM'], low_thresh=None, high_thresh=None, numtype='float32'): """ Take statitics across many input rasters this function is used to take statistics on large groups of rasters with identical spatial extents. Similar to Rolling_Raster_Stats Inputs: rasterlist list of raster filepaths for which to take statistics outdir Directory where output should be stored. saves which statistics to save in a raster. In addition to the options supported by Defaults to all three ['AVG','NUM','STD']. low_thresh values below low_thresh are assumed erroneous and set to NoData high_thresh values above high_thresh are assumed erroneous and set to NoData. numtype type of numerical value. defaults to 32bit float. """ if not os.path.isdir(outdir): os.makedirs(outdir) rasterlist = enf_rastlist(rasterlist) # build the empty numpy array based on size of first raster temp_rast, metadata = to_numpy(rasterlist[0]) xs, ys = temp_rast.shape zs = len(rasterlist) rast_3d = numpy.zeros((xs, ys, zs)) metadata.NoData_Value = numpy.nan # open up the initial figure rastfig = raster_fig(temp_rast) # populate the 3d matrix with values from all rasters for i, raster in enumerate(rasterlist): # print a status and open a figure print('working on file {0}'.format(os.path.basename(raster))) new_rast, new_meta = to_numpy(raster, numtype) new_rast = new_rast.data if not new_rast.shape == (xs, ys): print new_rast.shape # set rasters to have 'nan' NoData_Value if new_meta.NoData_Value != metadata.NoData_Value: new_rast[new_rast == new_meta.NoData_Value] = metadata.NoData_Value # set values outside thresholds to nodata values if not low_thresh == None: new_rast[new_rast < low_thresh] = metadata.NoData_Value if not high_thresh == None: new_rast[new_rast > high_thresh] = metadata.NoData_Value new_rast = numpy.ma.masked_array(new_rast, numpy.isnan(new_rast)) # display a figure rastfig.update_fig(new_rast) rast_3d[:, :, i] = new_rast # build up our statistics by masking nan values and performin matrix opperations rastfig.close_fig() rast_3d_masked = numpy.ma.masked_array(rast_3d, numpy.isnan(rast_3d)) if "AVG" in saves: avg_rast = numpy.mean(rast_3d_masked, axis=2) avg_rast = numpy.array(avg_rast) rastfig = raster_fig(avg_rast, title="Average") avg_name = core.create_outname(outdir, outname, 'AVG', 'tif') print("Saving AVERAGE output raster as {0}".format(avg_name)) from_numpy(avg_rast, metadata, avg_name) rastfig.close_fig() del avg_rast if "STD" in saves: std_rast = numpy.std(rast_3d_masked, axis=2) std_rast = numpy.array(std_rast) rastfig = raster_fig(std_rast, title="Standard Deviation") std_name = core.create_outname(outdir, outname, 'STD', 'tif') print( "Saving STANDARD DEVIATION output raster as {0}".format(std_name)) from_numpy(std_rast, metadata, std_name) rastfig.close_fig() del std_rast if "NUM" in saves: num_rast = (numpy.zeros( (xs, ys)) + zs) - numpy.sum(rast_3d_masked.mask, axis=2) num_rast = numpy.array(num_rast) rastfig = raster_fig(num_rast, title="Good pixel count (NUM)") rastfig.close_fig() num_name = core.create_outname(outdir, outname, 'NUM', 'tif') print("Saving NUMBER output raster as {0}".format(num_name)) from_numpy(num_rast, metadata, num_name) rastfig.close_fig() del num_rast if "SUM" in saves: sum_rast = numpy.sum(rast_3d_masked, axis=2) sum_rast = numpy.array(sum_rast) rastfig = raster_fig(sum_rast, title="Good pixel count (NUM)") rastfig.close_fig() sum_name = core.create_outname(outdir, outname, 'SUM', 'tif') print("Saving NUMBER output raster as {0}".format(sum_name)) from_numpy(sum_rast, metadata, sum_name) rastfig.close_fig() del sum_rast rastfig.close_fig() return
def spatially_match(snap_raster, rasterlist, outdir, NoData_Value=False, resamp_type=False): """ Prepares input rasters for further numerical processing This function simply ensures all rasters in "rasterlist" are identically projected and have the same cell size, then calls the raster.clip_and_snap function to ensure that the cells are perfectly coincident and that the total spatial extents of the images are identical, even when NoData values are considered. This is useful because it allows the two images to be passed on for numerical processing as nothing more than matrices of values, and the user can be sure that any index in any matrix is exactly coincident with the same index in any other matrix. This is especially important to use when comparing different datasets from different sources outside arcmap, for example MODIS and Landsat data with an ASTER DEM. inputs: snap_raster raster to which all other images will be snapped rasterlist list of rasters, a single raster, or a directory full of tiffs which will be clipped to the extent of "snap_raster" and aligned such that the cells are perfectly coincident. outdir the output directory to save newly created spatially matched tifs. resamp_type The resampling type to use if images are not identical cell sizes. "NEAREST","BILINEAR",and "CUBIC" are the most common. this function automatically invokes clip_and_snap project_resample """ # import modules and sanitize inputs tempdir = os.path.join(outdir, 'temp') if not os.path.isdir(outdir): os.makedirs(outdir) if not os.path.isdir(tempdir): os.makedirs(tempdir) rasterlist = enf_rastlist(rasterlist) core.exists(snap_raster) usetemp = False # set the snap raster environment in arcmap. arcpy.env.snapRaster = snap_raster print('Loading snap raster {0}'.format(snap_raster)) _, snap_meta = to_numpy(snap_raster) print('Bounds of rectangle to define boundaries: [{0}]'.format( snap_meta.rectangle)) # for every raster in the raster list, snap rasters and clip. for rastname in rasterlist: _, meta = to_numpy(rastname) head, tail = os.path.split(rastname) if snap_meta.projection.projectionName != meta.projection.projectionName: print('Projection discrepancy found. Reprojecting...') project_resample(rastname, snap_raster, tempdir, resamp_type) tempname = core.create_outname(tempdir, tail, "p") usetemp = True # define an output name and run the Clip_ans_Snap_Raster function on formatted tifs outname = core.create_outname(outdir, rastname, "sm") # if a temporary file was created in previous steps, use that one for clip and snap if usetemp: clip_and_snap(snap_raster, tempname, outname, NoData_Value) else: clip_and_snap(snap_raster, rastname, outname, NoData_Value) print('Finished matching raster {0}'.format(rastname)) return
def spatially_match(snap_raster, rasterlist, outdir, NoData_Value = False, resamp_type = False): """ Prepares input rasters for further numerical processing This function simply ensures all rasters in "rasterlist" are identically projected and have the same cell size, then calls the raster.clip_and_snap function to ensure that the cells are perfectly coincident and that the total spatial extents of the images are identical, even when NoData values are considered. This is useful because it allows the two images to be passed on for numerical processing as nothing more than matrices of values, and the user can be sure that any index in any matrix is exactly coincident with the same index in any other matrix. This is especially important to use when comparing different datasets from different sources outside arcmap, for example MODIS and Landsat data with an ASTER DEM. inputs: snap_raster raster to which all other images will be snapped rasterlist list of rasters, a single raster, or a directory full of tiffs which will be clipped to the extent of "snap_raster" and aligned such that the cells are perfectly coincident. outdir the output directory to save newly created spatially matched tifs. resamp_type The resampling type to use if images are not identical cell sizes. "NEAREST","BILINEAR",and "CUBIC" are the most common. this function automatically invokes clip_and_snap project_resample """ # import modules and sanitize inputs tempdir = os.path.join(outdir, 'temp') if not os.path.isdir(outdir): os.makedirs(outdir) if not os.path.isdir(tempdir): os.makedirs(tempdir) rasterlist = enf_rastlist(rasterlist) core.exists(snap_raster) usetemp = False # set the snap raster environment in arcmap. arcpy.env.snapRaster = snap_raster print('Loading snap raster {0}'.format(snap_raster)) _,snap_meta = to_numpy(snap_raster) print('Bounds of rectangle to define boundaries: [{0}]'.format(snap_meta.rectangle)) # for every raster in the raster list, snap rasters and clip. for rastname in rasterlist: _,meta = to_numpy(rastname) head,tail = os.path.split(rastname) if snap_meta.projection.projectionName != meta.projection.projectionName: print('Projection discrepancy found. Reprojecting...') project_resample(rastname, snap_raster, tempdir, resamp_type) tempname = core.create_outname(tempdir,tail,"p") usetemp = True # define an output name and run the Clip_ans_Snap_Raster function on formatted tifs outname = core.create_outname(outdir, rastname, "sm") # if a temporary file was created in previous steps, use that one for clip and snap if usetemp: clip_and_snap(snap_raster, tempname, outname, NoData_Value) else: clip_and_snap(snap_raster, rastname, outname, NoData_Value) print('Finished matching raster {0}'.format(rastname)) return
def degree_days_accum(rasterlist, critical_values=None, outdir=None): """ Accumulates degree days in a time series rasterlist This function is the logical successor to calc.degree_days. Input a list of rasters containing daily data to be accumulated. Output raster for a given day will be the sum total of the input raster for that day and all preceding days. The last output raster in a years worth of data (image 356) would be the sum of all 365 images. The 25th output raster would be a sum of the first 25 days. Critical value rasters will also be created. Usefull for example: we wish to know on what day of our 365 day sequence every pixel hits a value of 100. Input 100 as a critical value and that output raster will be generated. :param rasterlist: list of files, or directory containing rasters to accumulate :param critical_values: Values at which the user wishes to know WHEN the total accumulation value reaches this point. For every critical value, an output raster will be created. This raster contains integer values denoting the index number of the file at which the value was reached. This input must be a list of ints or floats, not strings. :param outdir: Desired output directory for all output files. :return output_filelist: a list of all files created by this function. """ output_filelist = [] rasterlist = enf_rastlist(rasterlist) if critical_values: critical_values = core.enf_list(critical_values) # critical values of zero are problematic, so replace it with a small value. if 0 in critical_values: critical_values.remove(0) critical_values.append(0.000001) if outdir is not None and not os.path.exists(outdir): os.makedirs(outdir) for i, rast in enumerate(rasterlist): image, meta = to_numpy(rast, "float32") xs, ys = image.shape if i == 0: Sum = numpy.zeros((xs, ys)) Crit = numpy.zeros((len(critical_values), xs, ys)) if image.shape == Sum.shape: # only bother to proceed if at least one pixel is positive if numpy.max(image) >= 0: for x in range(xs): for y in range(ys): if image[x, y] >= 0: Sum[x, y] = Sum[x, y] + image[x, y] if critical_values is not None: for z, critical_value in enumerate( critical_values): if Sum[x, y] >= critical_value and Crit[z, x, y] == 0: Crit[z, x, y] = i else: print "Encountered an image of incorrect size! Skipping it!" Sum = Sum.astype('float32') outname = core.create_outname(outdir, rast, "Accum") from_numpy(Sum, meta, outname) output_filelist.append(outname) del image # output critical accumulation rasters using some data from the last raster in previous loop Crit = Crit.astype('int16') crit_meta = meta crit_meta.NoData_Value = 0 head, tail = os.path.split( outname) # place these in the last raster output location for z, critical_value in enumerate(critical_values): outname = os.path.join( head, "Crit_Accum_Index_Val-{0}.tif".format(str(critical_value))) print("Saving {0}".format(outname)) from_numpy(Crit[z, :, :], crit_meta, outname) return output_filelist
def many_stats(rasterlist, outdir, outname, saves = ['AVG','NUM','STD','SUM'], low_thresh = None, high_thresh = None, numtype = 'float32'): """ Take statitics across many input rasters this function is used to take statistics on large groups of rasters with identical spatial extents. Similar to Rolling_Raster_Stats Inputs: rasterlist list of raster filepaths for which to take statistics outdir Directory where output should be stored. saves which statistics to save in a raster. In addition to the options supported by Defaults to all three ['AVG','NUM','STD']. low_thresh values below low_thresh are assumed erroneous and set to NoData high_thresh values above high_thresh are assumed erroneous and set to NoData. numtype type of numerical value. defaults to 32bit float. """ if not os.path.isdir(outdir): os.makedirs(outdir) rasterlist = enf_rastlist(rasterlist) # build the empty numpy array based on size of first raster temp_rast, metadata = to_numpy(rasterlist[0]) xs, ys = temp_rast.shape zs = len(rasterlist) rast_3d = numpy.zeros((xs,ys,zs)) metadata.NoData_Value = numpy.nan # open up the initial figure rastfig = raster_fig(temp_rast) # populate the 3d matrix with values from all rasters for i, raster in enumerate(rasterlist): # print a status and open a figure print('working on file {0}'.format(os.path.basename(raster))) new_rast, new_meta = to_numpy(raster, numtype) new_rast = new_rast.data if not new_rast.shape == (xs, ys): print new_rast.shape # set rasters to have 'nan' NoData_Value if new_meta.NoData_Value != metadata.NoData_Value: new_rast[new_rast == new_meta.NoData_Value] = metadata.NoData_Value # set values outside thresholds to nodata values if not low_thresh == None: new_rast[new_rast < low_thresh] = metadata.NoData_Value if not high_thresh == None: new_rast[new_rast > high_thresh] = metadata.NoData_Value new_rast = numpy.ma.masked_array(new_rast, numpy.isnan(new_rast)) # display a figure rastfig.update_fig(new_rast) rast_3d[:,:,i] = new_rast # build up our statistics by masking nan values and performin matrix opperations rastfig.close_fig() rast_3d_masked = numpy.ma.masked_array(rast_3d, numpy.isnan(rast_3d)) if "AVG" in saves: avg_rast = numpy.mean(rast_3d_masked, axis = 2) avg_rast = numpy.array(avg_rast) rastfig = raster_fig(avg_rast, title = "Average") avg_name = core.create_outname(outdir, outname, 'AVG', 'tif') print("Saving AVERAGE output raster as {0}".format(avg_name)) from_numpy(avg_rast, metadata, avg_name) rastfig.close_fig() del avg_rast if "STD" in saves: std_rast = numpy.std(rast_3d_masked, axis = 2) std_rast = numpy.array(std_rast) rastfig = raster_fig(std_rast, title = "Standard Deviation") std_name = core.create_outname(outdir, outname, 'STD', 'tif') print("Saving STANDARD DEVIATION output raster as {0}".format(std_name)) from_numpy(std_rast, metadata, std_name) rastfig.close_fig() del std_rast if "NUM" in saves: num_rast = (numpy.zeros((xs,ys)) + zs) - numpy.sum(rast_3d_masked.mask, axis = 2) num_rast = numpy.array(num_rast) rastfig = raster_fig(num_rast, title = "Good pixel count (NUM)") rastfig.close_fig() num_name = core.create_outname(outdir, outname, 'NUM', 'tif') print("Saving NUMBER output raster as {0}".format(num_name)) from_numpy(num_rast, metadata, num_name) rastfig.close_fig() del num_rast if "SUM" in saves: sum_rast = numpy.sum(rast_3d_masked, axis = 2) sum_rast = numpy.array(sum_rast) rastfig = raster_fig(sum_rast, title = "Good pixel count (NUM)") rastfig.close_fig() sum_name = core.create_outname(outdir, outname, 'SUM', 'tif') print("Saving NUMBER output raster as {0}".format(sum_name)) from_numpy(sum_rast, metadata, sum_name) rastfig.close_fig() del sum_rast rastfig.close_fig() return
def degree_days_accum(rasterlist, critical_values = None, outdir = None): """ Accumulates degree days in a time series rasterlist This function is the logical successor to calc.degree_days. Input a list of rasters containing daily data to be accumulated. Output raster for a given day will be the sum total of the input raster for that day and all preceding days. The last output raster in a years worth of data (image 356) would be the sum of all 365 images. The 25th output raster would be a sum of the first 25 days. Critical value rasters will also be created. Usefull for example: we wish to know on what day of our 365 day sequence every pixel hits a value of 100. Input 100 as a critical value and that output raster will be generated. :param rasterlist: list of files, or directory containing rasters to accumulate :param critical_values: Values at which the user wishes to know WHEN the total accumulation value reaches this point. For every critical value, an output raster will be created. This raster contains integer values denoting the index number of the file at which the value was reached. This input must be a list of ints or floats, not strings. :param outdir: Desired output directory for all output files. :return output_filelist: a list of all files created by this function. """ output_filelist = [] rasterlist = enf_rastlist(rasterlist) if critical_values: critical_values = core.enf_list(critical_values) # critical values of zero are problematic, so replace it with a small value. if 0 in critical_values: critical_values.remove(0) critical_values.append(0.000001) if outdir is not None and not os.path.exists(outdir): os.makedirs(outdir) for i, rast in enumerate(rasterlist): image, meta = to_numpy(rast,"float32") xs, ys = image.shape if i == 0: Sum = numpy.zeros((xs,ys)) Crit = numpy.zeros((len(critical_values),xs,ys)) if image.shape == Sum.shape: # only bother to proceed if at least one pixel is positive if numpy.max(image) >= 0: for x in range(xs): for y in range(ys): if image[x,y] >= 0: Sum[x,y] = Sum[x,y]+image[x,y] if critical_values is not None: for z,critical_value in enumerate(critical_values): if Sum[x,y] >= critical_value and Crit[z,x,y]==0: Crit[z,x,y] = i else: print "Encountered an image of incorrect size! Skipping it!" Sum = Sum.astype('float32') outname = core.create_outname(outdir, rast, "Accum") from_numpy(Sum, meta, outname) output_filelist.append(outname) del image # output critical accumulation rasters using some data from the last raster in previous loop Crit = Crit.astype('int16') crit_meta = meta crit_meta.NoData_Value = 0 head , tail = os.path.split(outname) # place these in the last raster output location for z, critical_value in enumerate(critical_values): outname = os.path.join(head, "Crit_Accum_Index_Val-{0}.tif".format(str(critical_value))) print("Saving {0}".format(outname)) from_numpy(Crit[z,:,:], crit_meta, outname) return output_filelist