def apply_linear_correction(rasterlist, factor, offset, suffix = 'lc', outdir = None, floor = -999999): """ Applies a linear correction to a raster dataset. New offset rasters are saved in the output directory with a suffix of "lc" unless one is specified. This may be used to apply any kind of linear relationship that can be described with "mx + b" such as conversion between between K,C, and F. Also useful when ground truthing satellite data and discovering linear errors. All outputs are 32 bit floating point values. :param rasterlist: list of rasters, a single raster, or a directory full of tiffs to Have a linear correction applied to them. :param factor: every pixel in the raster will be MULTIPLIED by this value. :param offset: this offset value will be ADDED to every pixel in the raster. :param suffix: output files will take the same name as input files with this string appended to the end. So input "FILE.tif" outputs "FILE_suffix.tif" :param outdir: directory to save output rasters. "None" will save output images in the same folder as the input images. :param floor: Used to manage NoData. All values less than floor are set to floor then floor is set to the new NoData value. defaults to -999,999 return outputpath: filepath to output files created by this function Example Usage to convert from MODIS Land surface temperature from digital number to kelvin, you must simply multiply by 0.02 as the stated scale factor listed at the link below [https://lpdaac.usgs.gov/products/modis_products_table/myd11a1]. Now that it is in kelvin, converting to Celsius can be done by adding (-273.15) So, use this function with:: factor = 0.02 offset = -273.15 and one may convert MODIS land surface temperature digital numbers directly to celsius! """ output_filelist = [] if outdir is not None and not os.path.isdir(outdir): os.makedirs(outdir) rasterlist = enf_rastlist(rasterlist) for raster in rasterlist: print("applying a linear correction to " + raster) image, metadata = to_numpy(raster, "float32") new_NoData = floor output = image * factor + offset low_value_indices = output < new_NoData output[low_value_indices] = new_NoData outname = core.create_outname(outdir,raster,suffix) from_numpy(output, metadata, outname, new_NoData) output_filelist.append(outname) print("Finished! \n ") return output_filelist
def gap_fill_temporal(rasterlist, outdir = None, continuous = True, NoData_Value = None, numpy_datatype = "float32"): """ This function is designed to input a time sequence of rasters with partial voids and output a copy of each input image with every pixel equal to the last good value taken. This function will step forward in time through each raster and fill voids from the values of previous rasters. The resulting output image will contain all the data that was in the original image, with the voids filled with older data. A second output image will be generated where the pixel values are equal to the age of each pixel in the image. So if a void was filled with data that's 5 days old, the "age" raster will have a value of "5" at that location. Inputs: :param rasterlist: a list of filepaths for rasters with which to fill gaps. THESE IMAGES MUST BE ORDERED FROM OLDEST TO NEWEST (ascending time). :param outdir: the path to the desired output folder, if left "None", outputs will be saved right next to respective inputs. :param continuous: if "True" an output raster will be generated for every single input raster, which can be used to fill gaps in an entire time series. So, for example output raster 2 will have all the good points in input raster 2, with gaps filled with data from raster 1. output raster 3 will then be gap filled with output raster 2, which might contain some fill values from raster 1, and so forth. If "False" an output raster will only be generated for the LAST raster in the input rasterlist. :param numpy_datatype the numpy datatype of the output raster. usually "float32" :returns a list of filepaths to new files created by this function. """ # enforce the list of rasters to ensure it's sanitized rasterlist = enf_rastlist(rasterlist) # create an empty list to store output arrays in output_filelist = [] # grab the first raster, then start stepping through the list old_rast, old_meta = to_numpy(rasterlist[0]) rastfig = raster_fig(old_rast) for i, araster in enumerate(rasterlist[1:]): new_rast, new_meta = to_numpy(araster) # combine new and old data and mask matrices outrast = new_rast outrast.data[new_rast.mask] = old_rast.data[new_rast.mask] outrast.mask[new_rast.mask] = old_rast.mask[new_rast.mask] # only save output if continuous is true or is last raster in series if continuous is True or i == (len(rasterlist[1:]) - 1): # create output name and save it if outdir is None: this_outdir = os.path.dirname(araster) else: this_outdir = outdir # update the figure rastfig.update_fig(outrast) outpath = core.create_outname(this_outdir, araster, "gft", "tif") print("Filled gaps in {0}".format(os.path.basename(araster))) outrast = outrast.astype(numpy_datatype) from_numpy(outrast, new_meta, outpath, NoData_Value) output_filelist.append(outpath) # prepare for next time step by setting current to old old_rast = new_rast return output_filelist
def gap_fill_temporal(rasterlist, outdir=None, continuous=True, NoData_Value=None, numpy_datatype="float32"): """ This function is designed to input a time sequence of rasters with partial voids and output a copy of each input image with every pixel equal to the last good value taken. This function will step forward in time through each raster and fill voids from the values of previous rasters. The resulting output image will contain all the data that was in the original image, with the voids filled with older data. A second output image will be generated where the pixel values are equal to the age of each pixel in the image. So if a void was filled with data that's 5 days old, the "age" raster will have a value of "5" at that location. :param rasterlist: A list of filepaths for rasters with which to fill gaps. THESE IMAGES MUST BE ORDERED FROM OLDEST TO NEWEST (ascending time). :param outdir: the path to the desired output folder, if left "None", outputs will be saved right next to respective inputs. :param continuous: if "True" an output raster will be generated for every single input raster, which can be used to fill gaps in an entire time series. So, for example output raster 2 will have all the good points in input raster 2, with gaps filled with data from raster 1. output raster 3 will then be gap filled with output raster 2, which might contain some fill values from raster 1, and so forth. If "False" an output raster will only be generated for the LAST raster in the input rasterlist. :param numpy_datatype: the numpy datatype of the output raster. usually "float32" :return output_filelist: returns a list of filepaths to new files created by this function. """ # enforce the list of rasters to ensure it's sanitized rasterlist = enf_rastlist(rasterlist) # create an empty list to store output arrays in output_filelist = [] # grab the first raster, then start stepping through the list old_rast, old_meta = to_numpy(rasterlist[0]) rastfig = raster_fig(old_rast) for i, araster in enumerate(rasterlist[1:]): new_rast, new_meta = to_numpy(araster) # combine new and old data and mask matrices outrast = new_rast outrast.data[new_rast.mask] = old_rast.data[new_rast.mask] outrast.mask[new_rast.mask] = old_rast.mask[new_rast.mask] # only save output if continuous is true or is last raster in series if continuous is True or i == (len(rasterlist[1:]) - 1): # create output name and save it if outdir is None: this_outdir = os.path.dirname(araster) else: this_outdir = outdir # update the figure rastfig.update_fig(outrast) outpath = core.create_outname(this_outdir, araster, "gft", "tif") print("Filled gaps in {0}".format(os.path.basename(araster))) outrast = outrast.astype(numpy_datatype) from_numpy(outrast, new_meta, outpath, NoData_Value) output_filelist.append(outpath) # prepare for next time step by setting current to old old_rast = new_rast return output_filelist