def atsat_bright_temp_8(meta_path, outdir = False):
    """
    Converts Landsat 8 TIRS bands to at satellite brightnes temperature in Kelvins

    To be performed on raw Landsat 8 level 1 data. See link below for details
    see here http://landsat.usgs.gov/Landsat8_Using_Product.php

    :param band_nums:   A list of desired band numbers, which should be [10,11]
    :param meta_path:   The full filepath to the metadata file for those bands
    :param outdir:      Output directory to save converted files. If left False it will save ouput
                        files in the same directory as input files.

    :return output_filelist: A list of all files created by this function
    """
    
    #enforce the list of band numbers and grab metadata from the MTL file
    band_nums = ["10", "11"]
    meta_path = os.path.abspath(meta_path)
    meta = grab_meta(meta_path)

    output_filelist = []

    #cycle through each band in the list for calculation, ensuring each is in the list of TIRS bands
    for band_num in band_nums:

        #scrape data from the given file path and attributes in the MTL file
        band_path = meta_path.replace("MTL.txt","B{0}.tif".format(band_num))
        Qcal = arcpy.Raster(band_path)
        
        #get rid of the zero values that show as the black background to avoid skewing values
        null_raster = arcpy.sa.SetNull(Qcal, Qcal, "VALUE = 0")

        #requires first converting to radiance
        Ml   = getattr(meta,"RADIANCE_MULT_BAND_{0}".format(band_num)) # multiplicative scaling factor
        Al   = getattr(meta,"RADIANCE_ADD_BAND_{0}".format(band_num))  # additive rescaling factor

        TOA_rad = (null_raster * Ml) + Al
        
        #now convert to at-sattelite brightness temperature
        K1   = getattr(meta,"K1_CONSTANT_BAND_{0}".format(band_num))  # thermal conversion constant 1
        K2   = getattr(meta,"K2_CONSTANT_BAND_{0}".format(band_num))  # thermal conversion constant 2

        #calculate brightness temperature at the satellite
        Bright_Temp = K2/(arcpy.sa.Ln((K1/TOA_rad) + 1))

        #save the data to the automated name if outdir is given or in the parent folder if not
        if outdir:
            outdir = os.path.abspath(outdir)
            outname = core.create_outname(outdir, band_path, "ASBTemp", "tif")
        else:
            folder = os.path.split(meta_path)[0]
            outname = core.create_outname(folder, band_path, "ASBTemp", "tif")
            
        Bright_Temp.save(outname)
        output_filelist.append(outname)

        print("Saved output at {0}".format(outname))
        del TOA_rad, null_raster
            
    return output_filelist
Beispiel #2
0
def toa_reflectance_8(band_nums, meta_path, outdir = False):

    """
    Converts Landsat 8 bands to Top-of-Atmosphere reflectance.

     To be performed on raw Landsat 8 level 1 data. See link below for details
     see here [http://landsat.usgs.gov/Landsat8_Using_Product.php]

     Inputs:
       band_nums   A list of desired band numbers such as [3,4,5]
       meta_path   The full filepath to the metadata file for those bands
       outdir      Output directory to save converted files. If left False it will save ouput
                       files in the same directory as input files.
    """

    outlist = []

    #enforce the list of band numbers and grab metadata from the MTL file
    band_nums = core.enf_list(band_nums)
    band_nums = map(str, band_nums)
    OLI_bands = ['1','2','3','4','5','6','7','8','9']
    meta_path = os.path.abspath(meta_path)
    meta = grab_meta(meta_path)

    #cycle through each band in the list for calculation, ensuring each is in the list of OLI bands
    for band_num in band_nums:
        if band_num in OLI_bands:

            #scrape data from the given file path and attributes in the MTL file
            band_path = meta_path.replace("MTL.txt","B{0}.tif".format(band_num))
            Qcal = arcpy.Raster(band_path)                        
            Mp   = getattr(meta,"REFLECTANCE_MULT_BAND_{0}".format(band_num)) # multiplicative scaling factor
            Ap   = getattr(meta,"REFLECTANCE_ADD_BAND_{0}".format(band_num))  # additive rescaling factor
            SEA  = getattr(meta,"SUN_ELEVATION")*(math.pi/180)       # sun elevation angle theta_se

            #get rid of the zero values that show as the black background to avoid skewing values
            null_raster = arcpy.sa.SetNull(Qcal, Qcal, "VALUE = 0")

            #calculate top-of-atmosphere reflectance
            TOA_ref = (((null_raster * Mp) + Ap)/(math.sin(SEA)))


            #save the data to the automated name if outdir is given or in the parent folder if not
            if outdir:
                outdir = os.path.abspath(outdir)
                outname = core.create_outname(outdir, band_path, "TOA_Ref", "tif")
            else:
                folder = os.path.split(meta_path)[0]
                outname = core.create_outname(folder, band_path, "TOA_Ref", "tif")
                
            TOA_ref.save(outname)
            outlist.append(outname)
            print("Saved output at {0}".format(outname))

        #if listed band is not an OLI sensor band, skip it and print message
        else:
            print("Can only perform reflectance conversion on OLI sensor bands")
            print("Skipping band {0}".format(band_num))

    return outlist
def atsat_bright_temp_457(meta_path, outdir = None):
    """
    Converts band 6 from Landsat 4 and 5 or bands 6 VCID 1 and 2 from Landsat 7
    to at satellite brightness temperature in Kelvins

    To be performed on raw Landsat 4, 5, or 7 level 1 data.

    :param meta_path:   The full filepath to the metadata file, labeled '_MTL.txt', which must
                        be in the same folder as band 6 or 6_VCID_1 and 6_VCID_2
    :param outdir:      Output directory to save converted files. If left False it will save ouput
                        files in the same directory as input files.

    :return output_filelist: A list of all files created by this function
    """

    output_filelist = []
    meta_path = os.path.abspath(meta_path)
    metadata = grab_meta(meta_path)
    spacecraft = getattr(metadata, "SPACECRAFT_ID")

    if "4" in spacecraft or "5" in spacecraft:
        band_nums = ["6"]
    elif "7" in spacecraft:
        band_nums = ["6_VCID_1", "6_VCID_2"]
    else:
      print("Enter the MTL file corresponding to a Landsat 4, 5, or 7 dataset")

    # These lists will be used to parse the meta data text file and locate relevant information
    # metadata format was changed August 29, 2012. This tool can process either the new or old format
    f = open(meta_path)
    MText = f.read()

    # the presence of a PRODUCT_CREATION_TIME category is used to identify old metadata
    # if this is not present, the meta data is considered new.
    # Band6length refers to the length of the Band 6 name string. In the new metadata this string is longer
    if "PRODUCT_CREATION_TIME" in MText:
        Meta = "oldMeta"
    else:
        Meta = "newMeta"

    # The tile name is located using the newMeta/oldMeta indixes and the date of capture is recorded
    if Meta == "newMeta":
        TileName  = getattr(metadata, "LANDSAT_SCENE_ID")
        year      = TileName[9:13]
        jday      = TileName[13:16]
        date      = getattr(metadata, "DATE_ACQUIRED")

    elif Meta == "oldMeta":
        TileName  = getattr(metadata, "BAND1_FILE_NAME")
        year      = TileName[13:17]
        jday      = TileName[17:20]
        date      = getattr(metadata, "ACQUISITION_DATE")

    # the spacecraft from which the imagery was capture is identified
    # this info determines the solar exoatmospheric irradiance (ESun) for each band

    # Calculating values for each band
    for band_num in band_nums:
        print("Processing Band {0}".format(band_num))

        pathname = meta_path.replace("MTL.txt", "B{0}.tif".format(band_num))
        Oraster = arcpy.Raster(pathname)

        # get rid of the zero values that show as the black background to avoid skewing values
        null_raster = arcpy.sa.SetNull(Oraster, Oraster, "VALUE = 0")

        # using the oldMeta/newMeta indixes to pull the min/max for radiance/Digital numbers
        if Meta == "newMeta":
            LMax    = getattr(metadata, "RADIANCE_MAXIMUM_BAND_{0}".format(band_num))
            LMin    = getattr(metadata, "RADIANCE_MINIMUM_BAND_{0}".format(band_num))
            QCalMax = getattr(metadata, "QUANTIZE_CAL_MAX_BAND_{0}".format(band_num))
            QCalMin = getattr(metadata, "QUANTIZE_CAL_MIN_BAND_{0}".format(band_num))

        elif Meta == "oldMeta":
            LMax    = getattr(metadata, "LMAX_BAND{0}".format(band_num))
            LMin    = getattr(metadata, "LMIN_BAND{0}".format(band_num))
            QCalMax = getattr(metadata, "QCALMAX_BAND{0}".format(band_num))
            QCalMin = getattr(metadata, "QCALMIN_BAND{0}".format(band_num))

        Radraster = (((LMax - LMin)/(QCalMax-QCalMin)) * (null_raster - QCalMin)) + LMin
        Oraster = 0

        # Calculating temperature for band 6 if present
        if "4" in spacecraft or "5" in spacecraft:
            Refraster  = 1260.56/(arcpy.sa.Ln((607.76/Radraster) + 1.0))

        if "7" in spacecraft:
            Refraster  = 1282.71/(arcpy.sa.Ln((666.09/Radraster) + 1.0))

        band_temp = "{0}_B{1}".format(TileName, band_num)

        # save the data to the automated name if outdir is given or in the parent folder if not
        if outdir:
            outdir = os.path.abspath(outdir)
            BandPath = core.create_outname(outdir, band_temp, "ASBTemp", "tif")
        else:
            folder = os.path.split(meta_path)[0]
            BandPath = core.create_outname(folder, band_temp, "ASBTemp", "tif")

        Refraster.save(BandPath)
        output_filelist.append(BandPath)

        del Refraster, Radraster, null_raster

        print("Temperature Calculated for Band {0}".format(band_num))

    f.close()
    return output_filelist
Beispiel #4
0
def toa_radiance_457(band_nums, meta_path, outdir = None):
    """
    Top of Atmosphere radiance (in Watts/(square meter x steradians x micrometers))
    conversion for Landsat 4, 5, and 7 data. To be performed on raw
    Landsat 4, 5, or 7 level 1 data.

    :param band_nums:   A list of desired band numbers such as [3, 4, 5]
    :param meta_path:   The full filepath to the metadata file for those bands
    :param outdir:      Output directory to save converted files.

    :return output_filelist:    List of filepaths created by this function.
    """

    output_filelist = []
    meta_path = os.path.abspath(meta_path)

    band_nums = core.enf_list(band_nums)
    band_nums = map(str, band_nums)

    #metadata format was changed August 29, 2012. This tool can process either the new or old format
    f = open(meta_path)
    MText = f.read()

    metadata = grab_meta(meta_path)

    #the presence of a PRODUCT_CREATION_TIME category is used to identify old metadata
    #if this is not present, the meta data is considered new.
    #Band6length refers to the length of the Band 6 name string. In the new metadata this string is longer
    if "PRODUCT_CREATION_TIME" in MText:
        Meta = "oldMeta"
        Band6length = 2
    else:
        Meta = "newMeta"
        Band6length = 8

    #The tilename is located using the newMeta/oldMeta indixes and the date of capture is recorded
    if Meta == "newMeta":
        TileName    = getattr(metadata, "LANDSAT_SCENE_ID")
        year        = TileName[9:13]
        jday        = TileName[13:16]
        date        = getattr(metadata, "DATE_ACQUIRED")
        
    elif Meta == "oldMeta":
        TileName    = getattr(metadata, "BAND1_FILE_NAME")
        year        = TileName[13:17]
        jday        = TileName[17:20]
        date        = getattr(metadata, "ACQUISITION_DATE")

    #the spacecraft from which the imagery was capture is identified
    #this info determines the solar exoatmospheric irradiance (ESun) for each band
    spacecraft = getattr(metadata, "SPACECRAFT_ID")

    if "7" in spacecraft:
        ESun = (1969.0, 1840.0, 1551.0, 1044.0, 255.700, 0., 82.07, 1368.00)
        TM_ETM_bands = ['1','2','3','4','5','7','8']
        
    elif "5" in spacecraft:
        ESun = (1957.0, 1826.0, 1554.0, 1036.0, 215.0, 0. ,80.67)
        TM_ETM_bands = ['1','2','3','4','5','7']
        
    elif "4" in spacecraft:
        ESun = (1957.0, 1825.0, 1557.0, 1033.0, 214.9, 0. ,80.72)
        TM_ETM_bands = ['1','2','3','4','5','7']
        
    else:
        arcpy.AddError("This tool only works for Landsat 4, 5, or 7")
        raise arcpy.ExecuteError()

    #Calculating values for each band
    for band_num in band_nums:
        if band_num in TM_ETM_bands:

            print("Processing Band {0}".format(band_num))
            pathname = meta_path.replace("MTL.txt", "B{0}.tif".format(band_num))
            Oraster = arcpy.Raster(pathname)

            null_raster = arcpy.sa.SetNull(Oraster, Oraster, "VALUE = 0")

            #using the oldMeta/newMeta indixes to pull the min/max for radiance/Digital numbers
            if Meta == "newMeta":
                LMax    = getattr(metadata, "RADIANCE_MAXIMUM_BAND_{0}".format(band_num))
                LMin    = getattr(metadata, "RADIANCE_MINIMUM_BAND_{0}".format(band_num))  
                QCalMax = getattr(metadata, "QUANTIZE_CAL_MAX_BAND_{0}".format(band_num))
                QCalMin = getattr(metadata, "QUANTIZE_CAL_MIN_BAND_{0}".format(band_num))
                
            elif Meta == "oldMeta":
                LMax    = getattr(metadata, "LMAX_BAND{0}".format(band_num))
                LMin    = getattr(metadata, "LMIN_BAND{0}".format(band_num))  
                QCalMax = getattr(metadata, "QCALMAX_BAND{0}".format(band_num))
                QCalMin = getattr(metadata, "QCALMIN_BAND{0}".format(band_num))

            Radraster = (((LMax - LMin)/(QCalMax-QCalMin)) * (null_raster - QCalMin)) + LMin
            Oraster = 0
            del null_raster

            band_rad = "{0}_B{1}".format(TileName, band_num)

            #create the output name and save the TOA radiance tiff
            if outdir is not None:
                outdir = os.path.abspath(outdir)
                outname = core.create_outname(outdir, band_rad, "TOA_Rad", "tif")
            else:
                folder = os.path.split(meta_path)[0]
                outname = core.create_outname(folder, band_rad, "TOA_Rad", "tif")
                
            Radraster.save(outname)
            output_filelist.append(outname)
            
            del Radraster

            print("toa radiance saved for Band {0}".format(band_num))

        #if listed band is not a TM/ETM+ sensor band, skip it and print message
        else:
            print("Can only perform reflectance conversion on TM/ETM+ sensor bands")
            print("Skipping band {0}".format(band_num))
         
    f.close()
    return output_filelist
Beispiel #5
0
def toa_radiance_8(band_nums, meta_path, outdir = None):
    """
    Top of Atmosphere radiance (in Watts/(square meter x steradians x micrometers))
    conversion for landsat 8 data. To be performed on raw Landsat 8
    level 1 data. See link below for details:
    see here http://landsat.usgs.gov/Landsat8_Using_Product.php

    :param band_nums:   A list of desired band numbers such as [3, 4, 5]
    :param meta_path:   The full filepath to the metadata file for those bands
    :param outdir:      Output directory to save converted files.

    :return output_filelist:    List of filepaths created by this function.
    """

    meta_path = os.path.abspath(meta_path)
    output_filelist = []

    #enforce list of band numbers and grab the metadata from the MTL file
    band_nums = core.enf_list(band_nums)
    band_nums = map(str, band_nums)
    meta = grab_meta(meta_path)
    
    OLI_bands = ['1','2','3','4','5','6','7','8','9']
    
    #loop through each band
    for band_num in band_nums:
        if band_num in OLI_bands:

            #create the band name
            band_path   = meta_path.replace("MTL.txt","B{0}.tif".format(band_num))
            Qcal        = arcpy.Raster(band_path)

            null_raster = arcpy.sa.SetNull(Qcal, Qcal, "VALUE = 0")

            #scrape the attribute data
            Ml   = getattr(meta,"RADIANCE_MULT_BAND_{0}".format(band_num)) # multiplicative scaling factor
            Al   = getattr(meta,"RADIANCE_ADD_BAND_{0}".format(band_num))  # additive rescaling factor

            #calculate Top-of-Atmosphere radiance
            TOA_rad = (null_raster * Ml) + Al
            del null_raster
            
            # create the output name and save the TOA radiance tiff
            if "\\" in meta_path:
                name = meta_path.split("\\")[-1]
            elif "//" in meta_path:
                name = meta_path.split("//")[-1]
                
            rad_name = name.replace("_MTL.txt", "_B{0}".format(band_num))

            if outdir is not None:
                outdir = os.path.abspath(outdir)
                outname = core.create_outname(outdir, rad_name, "TOA_Rad", "tif")
            else:
                folder = os.path.split(meta_path)[0]
                outname = core.create_outname(folder, rad_name, "TOA_Rad", "tif")
                
            TOA_rad.save(outname)
            output_filelist.append(outname)
            print("Saved toa_radiance at {0}".format(outname))

        #if listed band is not a OLI sensor band, skip it and print message
        else:
            print("Can only perform reflectance conversion on OLI sensor bands")
            print("Skipping band {0}".format(band_num))

    return output_filelist
Beispiel #6
0
def toa_reflectance_457(band_nums, meta_path, outdir=False):
    """
    This function is used to convert Landsat 4, 5, or 7 pixel values from
    digital numbers to Top-of-Atmosphere Reflectance.

    To be performed on raw Landsat 4, 5, or 7 data.

    Inputs:
        band_nums   A list of desired band numbers such as [3,4,5]
        meta_path   The full filepath to the metadata file for those bands
        outdir      Output directory to save converted files. If left False it will save ouput
                    files in the same directory as input files.
    """

    outlist = []

    band_nums = core.enf_list(band_nums)
    band_nums = map(str, band_nums)

    #metadata format was changed August 29, 2012. This tool can process either the new or old format
    f = open(meta_path)
    MText = f.read()

    meta_path = os.path.abspath(meta_path)
    metadata = grab_meta(meta_path)

    #the presence of a PRODUCT_CREATION_TIME category is used to identify old metadata
    #if this is not present, the meta data is considered new.
    #Band6length refers to the length of the Band 6 name string. In the new metadata this string is longer
    if "PRODUCT_CREATION_TIME" in MText:
        Meta = "oldMeta"
        Band6length = 2
    else:
        Meta = "newMeta"
        Band6length = 8

    #The tilename is located using the newMeta/oldMeta indixes and the date of capture is recorded
    if Meta == "newMeta":
        TileName = getattr(metadata, "LANDSAT_SCENE_ID")
        year = TileName[9:13]
        jday = TileName[13:16]
        date = getattr(metadata, "DATE_ACQUIRED")
    elif Meta == "oldMeta":
        TileName = getattr(metadata, "BAND1_FILE_NAME")
        year = TileName[13:17]
        jday = TileName[17:20]
        date = getattr(metadata, "ACQUISITION_DATE")

    #the spacecraft from which the imagery was capture is identified
    #this info determines the solar exoatmospheric irradiance (ESun) for each band
    spacecraft = getattr(metadata, "SPACECRAFT_ID")

    if "7" in spacecraft:
        ESun = (1969.0, 1840.0, 1551.0, 1044.0, 255.700, 0., 82.07, 1368.00)
        TM_ETM_bands = ['1', '2', '3', '4', '5', '7', '8']
    elif "5" in spacecraft:
        ESun = (1957.0, 1826.0, 1554.0, 1036.0, 215.0, 0., 80.67)
        TM_ETM_bands = ['1', '2', '3', '4', '5', '7']
    elif "4" in spacecraft:
        ESun = (1957.0, 1825.0, 1557.0, 1033.0, 214.9, 0., 80.72)
        TM_ETM_bands = ['1', '2', '3', '4', '5', '7']
    else:
        arcpy.AddError("This tool only works for Landsat 4, 5, or 7")
        raise arcpy.ExecuteError()

    #determing if year is leap year and setting the Days in year accordingly
    if float(year) % 4 == 0: DIY = 366.
    else: DIY = 365.

    #using the date to determing the distance from the sun
    theta = 2 * math.pi * float(jday) / DIY

    dSun2 = (1.00011 + 0.034221 * math.cos(theta) +
             0.001280 * math.sin(theta) + 0.000719 * math.cos(2 * theta) +
             0.000077 * math.sin(2 * theta))

    SZA = 90. - float(getattr(metadata, "SUN_ELEVATION"))

    #Calculating values for each band
    for band_num in band_nums:
        if band_num in TM_ETM_bands:

            print("Processing Band {0}".format(band_num))
            pathname = meta_path.replace("MTL.txt",
                                         "B{0}.tif".format(band_num))
            Oraster = arcpy.Raster(pathname)

            null_raster = arcpy.sa.SetNull(Oraster, Oraster, "VALUE = 0")

            #using the oldMeta/newMeta indixes to pull the min/max for radiance/Digital numbers
            if Meta == "newMeta":
                LMax = getattr(metadata,
                               "RADIANCE_MAXIMUM_BAND_{0}".format(band_num))
                LMin = getattr(metadata,
                               "RADIANCE_MINIMUM_BAND_{0}".format(band_num))
                QCalMax = getattr(metadata,
                                  "QUANTIZE_CAL_MAX_BAND_{0}".format(band_num))
                QCalMin = getattr(metadata,
                                  "QUANTIZE_CAL_MIN_BAND_{0}".format(band_num))
            elif Meta == "oldMeta":
                LMax = getattr(metadata, "LMAX_BAND{0}".format(band_num))
                LMin = getattr(metadata, "LMIN_BAND{0}".format(band_num))
                QCalMax = getattr(metadata, "QCALMAX_BAND{0}".format(band_num))
                QCalMin = getattr(metadata, "QCALMIN_BAND{0}".format(band_num))

            Radraster = (((LMax - LMin) / (QCalMax - QCalMin)) *
                         (null_raster - QCalMin)) + LMin
            Oraster = 0
            del null_raster

            #Calculating temperature for band 6 if present
            Refraster = (math.pi * Radraster * dSun2) / (
                ESun[int(band_num[0]) - 1] * math.cos(SZA * (math.pi / 180)))

            #construc output names for each band based on whether outdir is set (default is False)
            if outdir:
                outdir = os.path.abspath(outdir)
                BandPath = core.create_outname(outdir, pathname, "TOA_Ref",
                                               "tif")
            else:
                folder = os.path.split(meta_path)[0]
                BandPath = core.create_outname(folder, pathname, "TOA_Ref",
                                               "tif")

            Refraster.save(BandPath)
            outlist.append(BandPath)

            del Refraster, Radraster
            print("Reflectance Calculated for Band {0}".format(band_num))

        #if listed band is not a TM/ETM+ sensor band, skip it and print message
        else:
            print(
                "Can only perform reflectance conversion on TM/ETM+ sensor bands"
            )
            print("Skipping band {0}".format(band_num))

    f.close()
    return outlist
Beispiel #7
0
def toa_reflectance_8(band_nums, meta_path, outdir=False):
    """
    Converts Landsat 8 bands to Top-of-Atmosphere reflectance.

     To be performed on raw Landsat 8 level 1 data. See link below for details
     see here [http://landsat.usgs.gov/Landsat8_Using_Product.php]

     Inputs:
       band_nums   A list of desired band numbers such as [3,4,5]
       meta_path   The full filepath to the metadata file for those bands
       outdir      Output directory to save converted files. If left False it will save ouput
                       files in the same directory as input files.
    """

    outlist = []

    #enforce the list of band numbers and grab metadata from the MTL file
    band_nums = core.enf_list(band_nums)
    band_nums = map(str, band_nums)
    OLI_bands = ['1', '2', '3', '4', '5', '6', '7', '8', '9']
    meta_path = os.path.abspath(meta_path)
    meta = grab_meta(meta_path)

    #cycle through each band in the list for calculation, ensuring each is in the list of OLI bands
    for band_num in band_nums:
        if band_num in OLI_bands:

            #scrape data from the given file path and attributes in the MTL file
            band_path = meta_path.replace("MTL.txt",
                                          "B{0}.tif".format(band_num))
            Qcal = arcpy.Raster(band_path)
            Mp = getattr(meta, "REFLECTANCE_MULT_BAND_{0}".format(
                band_num))  # multiplicative scaling factor
            Ap = getattr(meta, "REFLECTANCE_ADD_BAND_{0}".format(
                band_num))  # additive rescaling factor
            SEA = getattr(meta, "SUN_ELEVATION") * (
                math.pi / 180)  # sun elevation angle theta_se

            #get rid of the zero values that show as the black background to avoid skewing values
            null_raster = arcpy.sa.SetNull(Qcal, Qcal, "VALUE = 0")

            #calculate top-of-atmosphere reflectance
            TOA_ref = (((null_raster * Mp) + Ap) / (math.sin(SEA)))

            #save the data to the automated name if outdir is given or in the parent folder if not
            if outdir:
                outdir = os.path.abspath(outdir)
                outname = core.create_outname(outdir, band_path, "TOA_Ref",
                                              "tif")
            else:
                folder = os.path.split(meta_path)[0]
                outname = core.create_outname(folder, band_path, "TOA_Ref",
                                              "tif")

            TOA_ref.save(outname)
            outlist.append(outname)
            print("Saved output at {0}".format(outname))

        #if listed band is not an OLI sensor band, skip it and print message
        else:
            print(
                "Can only perform reflectance conversion on OLI sensor bands")
            print("Skipping band {0}".format(band_num))

    return outlist
def surface_reflectance(meta_path, toa_folder, dem_path, dew_point, outdir = False, kt = 1.0):
        """
        This function will calculate surface reflectance for Landsat 4 TM, 5 TM, 7 ETM+, or 8 OLI data.
        
        *Note this function will calculate surface reflectance for Landsat 4, 5, and 7
         bands 1, 2, 3, 4, 5, and 7 or Landsat 8 bands 2, 3, 4, 5, 6, and 7. All 6 bands should be in the
         toa_folder and have "TOA_Ref" in their filenames as per the landsat.toa_reflectance convention.
         
        *The Landsat 8 Coastal Aerosol band (1) and Cirrus band (9) will not be calculated as they do not
         have a corresponding band in TM or ETM+.

        To be performed on Top-of-Atmosphere Reflectance data processed with the landsat.toa_reflectance_457
        or the landsat.toa_reflectance_8 function.

        Resources:
                DEM:
                -NASA Shuttle Radar Topography Mission (SRTM):
                        http://www2.jpl.nasa.gov/srtm/cbanddataproducts.html
                        *SRTM version 2 has a 30m resolution, but contains some gaps
                -NASA Advanced Spaceborne Thermal Emission and Reflection Radiometer (ASTER)
                 Global Digital Elevation Model (GDEM):
                        http://asterweb.jpl.nasa.gov/gdem.asp
                -USGS National Elevation Dataset (NED):
                        http://nationalmap.gov/elevation.html
                        *downloadable in 30 meter resolution through The National Map Viewer

                Dew Point:
                -NOAA Daily Observational Data: Global Summary of the Day (GSOD) - GIS Data Locator
                        http://gis.ncdc.noaa.gov/map/viewer/#app=clim&cfg=cdo&theme=daily&layers=0001&node=gis
                        *Select a weather station within the Landsat scene's extent, follow the link,
                         and enter the scene's acquisition date. This will output a text file, with
                         dew point under DEWP.
                        *More NOAA climatic data available at https://www.climate.gov/data/maps-and-data
                        
        Inputs:
                meta_path       The full filepath to the metadata file (ending in MTL.txt) for the dataset
                toa_folder      The filepath to the folder containing the TOA_Ref tiffs to be processed
                dem_path        The full filepath to a DEM tif that covers the desired Landsat scene
                                  *Note that the DEM should be resampled to the Landsat bands' resolution (30m)
                                   and pixel alignment. Also ensure there are no gaps in the dataset.
                dew_point       The number (e.g. 57.7) for the dew point at the time and place of scene acquisition
                outdir          Output directory to save converted files. If left False it will save
                                   output files in the toa_folder directory.
                kt              Unitless turbidity coefficient. Default set at 1.0 for clean air.
                                  *Set at 0.5 for extremeley turbid, dusty, or polluted air
        """

        meta_path = os.path.abspath(meta_path)
        toa_folder = os.path.abspath(toa_folder)
        dem_path = os.path.abspath(dem_path)
        outlist = []

        #define the list of constants for effective narrowband transmissivity for incoming solar radiation 
        constants_enbt1 = [[0.987, -0.00071, 0.000036, 0.0880, 0.0789],
                             [2.319, -0.00016, 0.000105, 0.0437, -1.2697],
                             [0.951, -0.00033, 0.000280, 0.0875, 0.1014],
                             [0.375, -0.00048, 0.005018, 0.1355, 0.6621],
                             [0.234, -0.00101, 0.004336, 0.0560, 0.7757],
                             [0.365, -0.00097, 0.004296, 0.0155, 0.6390]]

        #define the list of constants for effective narrowband transmissivity for shortwave radiation
        #reflected from the surface
        constants_enbt2 = [[0.987, -0.00071, 0.000036, 0.0880, 0.0789],
                             [2.319, -0.00016, 0.000105, 0.0437, -1.2697],
                             [0.951, -0.00033, 0.000280, 0.0875, 0.1014],
                             [0.375, -0.00048, 0.005018, 0.1355, 0.6621],
                             [0.234, -0.00101, 0.004336, 0.0560, 0.7757],
                             [0.365, -0.00097, 0.004296, 0.0155, 0.6390]]

        #enforce the list of band numbers, grab metadata from the MTL file, and define the band numbers needed from each sensor
        meta = grab_meta(meta_path)
        OLI_bands = ['2','3','4','5','6','7']
        TM_ETM_bands = ['1','2','3','4','5','7']

        #define the tile name for the landsat scene based on the metadata file's name

        #Open the metadata text file and read to set the scene's tilename
        f = open(meta_path)
        MText = f.read()

        if "PRODUCT_CREATION_TIME" in MText:
                tilename = getattr(meta, "BAND1_FILE_NAME")
        else:
                tilename = getattr(meta, "LANDSAT_SCENE_ID")

        #construct the list of TOA reflectance band tiffs and populate it based on the above definitions
        toa_list = []
        out_list = []
        n = 0
        for file in os.listdir(toa_folder):
                if ("TOA_Ref" in file) and (file[-4:] == ".tif" or file[-4:] == ".TIF"):
                        if "LC8" in meta_path:
                                tile = "{0}_B{1}".format(tilename, OLI_bands[n])
                                if tile in file:
                                        path = "{0}\\{1}".format(toa_folder, file)
                                        out_file = file.replace("TOA", "Surf")
                                        toa_list.append(path)
                                        out_list.append(out_file)
                                        n = n + 1
                                        if n > 5:
                                                break
                        elif ("LE7" in file) or ("LT5" in file) or ("LT4" in file):
                                tile = "{0}_B{1}".format(tilename, TM_ETM_bands[n])
                                if tile in file:
                                        path = "{0}\\{1}".format(toa_folder, file)
                                        out_file = file.replace("TOA", "Surf")
                                        toa_list.append(path)
                                        out_list.append(out_file)
                                        n = n + 1
                                        if n > 5:
                                                break

        #grab the corner lat/lon coordinates to calculate the approximate scene center lat/lon       
        ul_lat = getattr(meta, "CORNER_UL_LAT_PRODUCT")
        ul_lon = getattr(meta, "CORNER_UL_LON_PRODUCT")
        ur_lat = getattr(meta, "CORNER_UR_LAT_PRODUCT")
        ur_lon = getattr(meta, "CORNER_UR_LON_PRODUCT")
        ll_lat = getattr(meta, "CORNER_LL_LAT_PRODUCT")
        ll_lon = getattr(meta, "CORNER_LL_LON_PRODUCT")
        lr_lat = getattr(meta, "CORNER_LR_LAT_PRODUCT")
        lr_lon = getattr(meta, "CORNER_LR_LON_PRODUCT")

        u_lon_avg = np.mean([ul_lon, ur_lon])
        l_lon_avg = np.mean([ll_lon, lr_lon])
        l_lat_avg = np.mean([ul_lat, ll_lat])
        r_lat_avg = np.mean([ur_lat, lr_lat])
        
        center_lat = np.mean([l_lat_avg, r_lat_avg])
        center_lon = np.mean([u_lon_avg, l_lon_avg])

        #construct the datetime object from the date acquired and scene center time attributes      
        date = getattr(meta, "DATE_ACQUIRED")
        dl = date.split("-")
        time = getattr(meta, "SCENE_CENTER_TIME")
        tl = time.split(":")

        dt = datetime.datetime(int(dl[0]), int(dl[1]), int(dl[2]), int(tl[0]), int(tl[1]), int(tl[2][0:2]))

        #use the dnppy.solar module to calculate the solar characteristics at the scene center at the time of acquisition
        sc = solar.solar(center_lat, center_lon, dt, 0)
        sc.compute_all()

        #Cosine of Solar Zenith over horizontal surface
        declination = math.degrees(sc.get_declination())
        hour_angle = math.degrees(sc.get_hour_angle())
        lat = math.degrees(center_lat)

        cth = (math.sin(declination) * math.sin(lat)) + (math.cos(declination) * math.cos(center_lat) * math.cos(hour_angle))

        #Saturation Vapor Pressure
        svp = 0.6108 * math.exp((17.27 * dew_point) / (dew_point + 237.3))

        #Atmospheric Pressure
        DEM = arcpy.sa.Raster(dem_path)
        ap = 101.3 * ((( 293 - (0.0065 * DEM))/ 293) ** 5.26)
        
        #Water in Atmosphere
        wia = (0.14 * svp * ap) + 2.1

        #Effective Narrowband Transmittance for incoming solar radiation
        entisr_bands = []
        for i in xrange(6):
                c1 = constants_enbt1[i][0]
                c2 = constants_enbt1[i][1]
                c3 = constants_enbt1[i][2]
                c4 = constants_enbt1[i][3]
                c5 = constants_enbt1[i][4]
                enbt1 = c1 * ((arcpy.sa.Exp((c2 * ap)/(kt * cth))) - (((c3 * wia) + c4)/cth)) + c5
                entisr_bands.append(enbt1)

        #Effective Narrowband Transmittance for shortwave radiation reflected from surface
        entsrrs_bands = []
        
        #cos_n always 1 for sensor pointing straight nadir
        cos_n = 1
        
        for i in xrange(6):
                c1 = constants_enbt2[i][0]
                c2 = constants_enbt2[i][1]
                c3 = constants_enbt2[i][2]
                c4 = constants_enbt2[i][3]
                c5 = constants_enbt2[i][4]
                enbt2 = c1 * ((arcpy.sa.Exp((c2 * ap)/(kt * cos_n))) - (((c3 * wia) + c4))) + c5
                entsrrs_bands.append(enbt2)

        #Per Band Path Reflectance
        pr_bands = []
        pr_constants = [0.254, 0.149, 0.147, 0.311, 0.103, 0.036]
        for j in xrange(6):
                pr = pr_constants[j] * (1 - entisr_bands[j])
                pr_bands.append(pr)

        #Calculate and save At-Surface Reflectance band tiffs
        for k in xrange(6):
                if outdir:
                        outdir = os.path.abspath(outdir)
                        asr_path = "{0}\\{1}".format(outdir, out_list[k])
                else:
                        asr_path = "{0}\\{1}".format(toa_folder, out_list[k])
                refl_surf = (toa_list[k] - pr_bands[k])/(entisr_bands[k] * entsrrs_bands[k])
                refl_surf.save(asr_path)
                outlist.append(asr_path)

        return outlist
Beispiel #9
0
def atsat_bright_temp_457(meta_path, outdir=False):
    """
    Converts band 6 from Landsat 4 and 5 or bands 6 VCID 1 and 2 from Landsat 7
    to at satellite brightnes temperature in Kelvins

     To be performed on raw Landsat 4, 5, or 7 level 1 data.

     Inputs:
       meta_path   The full filepath to the metadata file, labeled '_MTL.txt', which must
                   be in the same folder as band 6 or 6_VCID_1 and 6_VCID_2
       outdir      Output directory to save converted files. If left False it will save ouput
                   files in the same directory as input files.
    """

    outlist = []
    meta_path = os.path.abspath(meta_path)
    metadata = grab_meta(meta_path)
    spacecraft = getattr(metadata, "SPACECRAFT_ID")

    if "4" in spacecraft or "5" in spacecraft:
        band_nums = ["6"]
    elif "7" in spacecraft:
        band_nums = ["6_VCID_1", "6_VCID_2"]
    else:
        print(
            "Enter the MTL file corresponding to a Landsat 4, 5, or 7 dataset")

    #These lists will be used to parse the meta data text file and locate relevant information
    #metadata format was changed August 29, 2012. This tool can process either the new or old format
    f = open(meta_path)
    MText = f.read()

    #the presence of a PRODUCT_CREATION_TIME category is used to identify old metadata
    #if this is not present, the meta data is considered new.
    #Band6length refers to the length of the Band 6 name string. In the new metadata this string is longer
    if "PRODUCT_CREATION_TIME" in MText:
        Meta = "oldMeta"
    else:
        Meta = "newMeta"

    #The tilename is located using the newMeta/oldMeta indixes and the date of capture is recorded
    if Meta == "newMeta":
        TileName = getattr(metadata, "LANDSAT_SCENE_ID")
        year = TileName[9:13]
        jday = TileName[13:16]
        date = getattr(metadata, "DATE_ACQUIRED")

    elif Meta == "oldMeta":
        TileName = getattr(metadata, "BAND1_FILE_NAME")
        year = TileName[13:17]
        jday = TileName[17:20]
        date = getattr(metadata, "ACQUISITION_DATE")

    #the spacecraft from which the imagery was capture is identified
    #this info determines the solar exoatmospheric irradiance (ESun) for each band

    #Calculating values for each band
    for band_num in band_nums:
        print("Processing Band {0}".format(band_num))

        pathname = meta_path.replace("MTL.txt", "B{0}.tif".format(band_num))
        Oraster = arcpy.Raster(pathname)

        #get rid of the zero values that show as the black background to avoid skewing values
        null_raster = arcpy.sa.SetNull(Oraster, Oraster, "VALUE = 0")

        #using the oldMeta/newMeta indixes to pull the min/max for radiance/Digital numbers
        if Meta == "newMeta":
            LMax = getattr(metadata,
                           "RADIANCE_MAXIMUM_BAND_{0}".format(band_num))
            LMin = getattr(metadata,
                           "RADIANCE_MINIMUM_BAND_{0}".format(band_num))
            QCalMax = getattr(metadata,
                              "QUANTIZE_CAL_MAX_BAND_{0}".format(band_num))
            QCalMin = getattr(metadata,
                              "QUANTIZE_CAL_MIN_BAND_{0}".format(band_num))

        elif Meta == "oldMeta":
            LMax = getattr(metadata, "LMAX_BAND{0}".format(band_num))
            LMin = getattr(metadata, "LMIN_BAND{0}".format(band_num))
            QCalMax = getattr(metadata, "QCALMAX_BAND{0}".format(band_num))
            QCalMin = getattr(metadata, "QCALMIN_BAND{0}".format(band_num))

        Radraster = (((LMax - LMin) / (QCalMax - QCalMin)) *
                     (null_raster - QCalMin)) + LMin
        Oraster = 0

        #Calculating temperature for band 6 if present
        if "4" in spacecraft or "5" in spacecraft:
            Refraster = 1260.56 / (arcpy.sa.Ln((607.76 / Radraster) + 1.0))

        if "7" in spacecraft:
            Refraster = 1282.71 / (arcpy.sa.Ln((666.09 / Radraster) + 1.0))

        band_temp = "{0}_B{1}".format(TileName, band_num)

        #save the data to the automated name if outdir is given or in the parent folder if not
        if outdir:
            outdir = os.path.abspath(outdir)
            BandPath = core.create_outname(outdir, band_temp, "ASBTemp", "tif")
        else:
            folder = os.path.split(meta_path)[0]
            BandPath = core.create_outname(folder, band_temp, "ASBTemp", "tif")

        Refraster.save(BandPath)
        outlist.append(BandPath)

        del Refraster, Radraster, null_raster

        print("Temperature Calculated for Band {0}".format(band_num))

    f.close()
    return outlist
Beispiel #10
0
def atsat_bright_temp_8(meta_path, outdir=False):
    """
    Converts Landsat 8 TIRS bands to at satellite brightnes temperature in Kelvins

     To be performed on raw Landsat 8 level 1 data. See link below for details
     see here http://landsat.usgs.gov/Landsat8_Using_Product.php

     Inputs:
       band_nums   A list of desired band numbers, which should be [10,11]
       meta_path   The full filepath to the metadata file for those bands
       outdir      Output directory to save converted files. If left False it will save ouput
                   files in the same directory as input files.
    """

    #enforce the list of band numbers and grab metadata from the MTL file
    band_nums = ["10", "11"]
    meta_path = os.path.abspath(meta_path)
    meta = grab_meta(meta_path)

    outlist = []

    #cycle through each band in the list for calculation, ensuring each is in the list of TIRS bands
    for band_num in band_nums:

        #scrape data from the given file path and attributes in the MTL file
        band_path = meta_path.replace("MTL.txt", "B{0}.tif".format(band_num))
        Qcal = arcpy.Raster(band_path)

        #get rid of the zero values that show as the black background to avoid skewing values
        null_raster = arcpy.sa.SetNull(Qcal, Qcal, "VALUE = 0")

        #requires first converting to radiance
        Ml = getattr(meta, "RADIANCE_MULT_BAND_{0}".format(
            band_num))  # multiplicative scaling factor
        Al = getattr(meta, "RADIANCE_ADD_BAND_{0}".format(
            band_num))  # additive rescaling factor

        TOA_rad = (null_raster * Ml) + Al

        #now convert to at-sattelite brightness temperature
        K1 = getattr(meta, "K1_CONSTANT_BAND_{0}".format(
            band_num))  # thermal conversion constant 1
        K2 = getattr(meta, "K2_CONSTANT_BAND_{0}".format(
            band_num))  # thermal conversion constant 2

        #calculate brightness temperature at the satellite
        Bright_Temp = K2 / (arcpy.sa.Ln((K1 / TOA_rad) + 1))

        #save the data to the automated name if outdir is given or in the parent folder if not
        if outdir:
            outdir = os.path.abspath(outdir)
            outname = core.create_outname(outdir, band_path, "ASBTemp", "tif")
        else:
            folder = os.path.split(meta_path)[0]
            outname = core.create_outname(folder, band_path, "ASBTemp", "tif")

        Bright_Temp.save(outname)
        outlist.append(outname)

        print("Saved output at {0}".format(outname))
        del TOA_rad, null_raster

    return outlist
Beispiel #11
0
def toa_reflectance_457(band_nums, meta_path, outdir = None):
    """
    This function is used to convert Landsat 4, 5, or 7 pixel values from
    digital numbers to Top-of-Atmosphere Reflectance. To be performed on raw
    Landsat 4, 5, or 7 data.

    :param band_nums:   A list of desired band numbers such as [3,4,5]
    :param meta_path:   The full filepath to the metadata file for those bands
    :param outdir:      Output directory to save converted files. If left False it will save ouput
                        files in the same directory as input files.

    :return output_filelist:    List of files created by this function
    """
   
    output_filelist = []

    band_nums = core.enf_list(band_nums)
    band_nums = map(str, band_nums)

    # metadata format was changed August 29, 2012. This tool can process either the new or old format
    f = open(meta_path)
    MText = f.read()

    meta_path = os.path.abspath(meta_path)
    metadata = grab_meta(meta_path)
    
    # the presence of a PRODUCT_CREATION_TIME category is used to identify old metadata
    # if this is not present, the meta data is considered new.
    # Band6length refers to the length of the Band 6 name string. In the new metadata this string is longer
    if "PRODUCT_CREATION_TIME" in MText:
        Meta = "oldMeta"
        Band6length = 2
    else:
        Meta = "newMeta"
        Band6length = 8

    # The tilename is located using the newMeta/oldMeta indixes and the date of capture is recorded
    if Meta == "newMeta":
        TileName = getattr(metadata, "LANDSAT_SCENE_ID")
        year = TileName[9:13]
        jday = TileName[13:16]
        date = getattr(metadata, "DATE_ACQUIRED")
    elif Meta == "oldMeta":
        TileName = getattr(metadata, "BAND1_FILE_NAME")
        year = TileName[13:17]
        jday = TileName[17:20]
        date = getattr(metadata, "ACQUISITION_DATE")

    # the spacecraft from which the imagery was capture is identified
    # this info determines the solar exoatmospheric irradiance (ESun) for each band
    spacecraft = getattr(metadata, "SPACECRAFT_ID")
    
    if "7" in spacecraft:
        ESun = (1969.0, 1840.0, 1551.0, 1044.0, 255.700, 0., 82.07, 1368.00)
        TM_ETM_bands = ['1','2','3','4','5','7','8']
    elif "5" in spacecraft:
         ESun = (1957.0, 1826.0, 1554.0, 1036.0, 215.0, 0. ,80.67)
         TM_ETM_bands = ['1','2','3','4','5','7']
    elif "4" in spacecraft:
        ESun = (1957.0, 1825.0, 1557.0, 1033.0, 214.9, 0. ,80.72)
        TM_ETM_bands = ['1','2','3','4','5','7']
    else:
        arcpy.AddError("This tool only works for Landsat 4, 5, or 7")
        raise arcpy.ExecuteError()

    # determing if year is leap year and setting the Days in year accordingly
    if float(year) % 4 == 0: DIY = 366.
    else: DIY=365.

    # using the date to determining the distance from the sun
    theta = 2 * math.pi * float(jday)/DIY

    dSun2 = (1.00011 + 0.034221 * math.cos(theta) + 0.001280 * math.sin(theta) +
           0.000719 * math.cos(2*theta)+ 0.000077 * math.sin(2 * theta))

    SZA = 90. - float(getattr(metadata, "SUN_ELEVATION"))
    
    # Calculating values for each band
    for band_num in band_nums:
        if band_num in TM_ETM_bands:

            print("Processing Band {0}".format(band_num))
            pathname = meta_path.replace("MTL.txt", "B{0}.tif".format(band_num))
            Oraster = arcpy.Raster(pathname)
         
            null_raster = arcpy.sa.SetNull(Oraster, Oraster, "VALUE = 0")

            # using the oldMeta/newMeta indices to pull the min/max for radiance/Digital numbers
            if Meta == "newMeta":
                LMax    = getattr(metadata, "RADIANCE_MAXIMUM_BAND_{0}".format(band_num))
                LMin    = getattr(metadata, "RADIANCE_MINIMUM_BAND_{0}".format(band_num))  
                QCalMax = getattr(metadata, "QUANTIZE_CAL_MAX_BAND_{0}".format(band_num))
                QCalMin = getattr(metadata, "QUANTIZE_CAL_MIN_BAND_{0}".format(band_num))
            elif Meta == "oldMeta":
                LMax    = getattr(metadata, "LMAX_BAND{0}".format(band_num))
                LMin    = getattr(metadata, "LMIN_BAND{0}".format(band_num))  
                QCalMax = getattr(metadata, "QCALMAX_BAND{0}".format(band_num))
                QCalMin = getattr(metadata, "QCALMIN_BAND{0}".format(band_num))
    
            Radraster = (((LMax - LMin)/(QCalMax-QCalMin)) * (null_raster - QCalMin)) + LMin
            Oraster = 0
            del null_raster
    
            # Calculating temperature for band 6 if present
            Refraster = (math.pi * Radraster * dSun2) / (ESun[int(band_num[0])-1] * math.cos(SZA*(math.pi/180)))

            # construc output names for each band based on whether outdir is set (default is False)
            if outdir is not None:
                outdir = os.path.abspath(outdir)
                BandPath = core.create_outname(outdir, pathname, "TOA_Ref", "tif")
            else:
                folder = os.path.split(meta_path)[0]
                BandPath = core.create_outname(folder, pathname, "TOA_Ref", "tif")

            Refraster.save(BandPath)
            output_filelist.append(BandPath)

            del Refraster, Radraster
            print("Reflectance Calculated for Band {0}".format(band_num))

        # if listed band is not a TM/ETM+ sensor band, skip it and print message
        else:
            print("Can only perform reflectance conversion on TM/ETM+ sensor bands")
            print("Skipping band {0}".format(band_num))
         
    f.close()
    return output_filelist
Beispiel #12
0
def toa_radiance_457(band_nums, meta_path, outdir=False):
    """
    Top of Atmosphere radiance (in Watts/(square meter * steradians * micrometers)) conversion
    for Landsat 4, 5, and 7 data. To be performed on raw Landsat 4, 5, or 7 level 1 data. 

     Inputs:
       band_nums   A list of desired band numbers such as [3, 4, 5]
       meta_path   The full filepath to the metadata file for those bands
       outdir      Output directory to save converted files.
    """

    outlist = []
    meta_path = os.path.abspath(meta_path)

    band_nums = core.enf_list(band_nums)
    band_nums = map(str, band_nums)

    #metadata format was changed August 29, 2012. This tool can process either the new or old format
    f = open(meta_path)
    MText = f.read()

    metadata = grab_meta(meta_path)

    #the presence of a PRODUCT_CREATION_TIME category is used to identify old metadata
    #if this is not present, the meta data is considered new.
    #Band6length refers to the length of the Band 6 name string. In the new metadata this string is longer
    if "PRODUCT_CREATION_TIME" in MText:
        Meta = "oldMeta"
        Band6length = 2
    else:
        Meta = "newMeta"
        Band6length = 8

    #The tilename is located using the newMeta/oldMeta indixes and the date of capture is recorded
    if Meta == "newMeta":
        TileName = getattr(metadata, "LANDSAT_SCENE_ID")
        year = TileName[9:13]
        jday = TileName[13:16]
        date = getattr(metadata, "DATE_ACQUIRED")

    elif Meta == "oldMeta":
        TileName = getattr(metadata, "BAND1_FILE_NAME")
        year = TileName[13:17]
        jday = TileName[17:20]
        date = getattr(metadata, "ACQUISITION_DATE")

    #the spacecraft from which the imagery was capture is identified
    #this info determines the solar exoatmospheric irradiance (ESun) for each band
    spacecraft = getattr(metadata, "SPACECRAFT_ID")

    if "7" in spacecraft:
        ESun = (1969.0, 1840.0, 1551.0, 1044.0, 255.700, 0., 82.07, 1368.00)
        TM_ETM_bands = ['1', '2', '3', '4', '5', '7', '8']

    elif "5" in spacecraft:
        ESun = (1957.0, 1826.0, 1554.0, 1036.0, 215.0, 0., 80.67)
        TM_ETM_bands = ['1', '2', '3', '4', '5', '7']

    elif "4" in spacecraft:
        ESun = (1957.0, 1825.0, 1557.0, 1033.0, 214.9, 0., 80.72)
        TM_ETM_bands = ['1', '2', '3', '4', '5', '7']

    else:
        arcpy.AddError("This tool only works for Landsat 4, 5, or 7")
        raise arcpy.ExecuteError()

    #Calculating values for each band
    for band_num in band_nums:
        if band_num in TM_ETM_bands:

            print("Processing Band {0}".format(band_num))
            pathname = meta_path.replace("MTL.txt",
                                         "B{0}.tif".format(band_num))
            Oraster = arcpy.Raster(pathname)

            null_raster = arcpy.sa.SetNull(Oraster, Oraster, "VALUE = 0")

            #using the oldMeta/newMeta indixes to pull the min/max for radiance/Digital numbers
            if Meta == "newMeta":
                LMax = getattr(metadata,
                               "RADIANCE_MAXIMUM_BAND_{0}".format(band_num))
                LMin = getattr(metadata,
                               "RADIANCE_MINIMUM_BAND_{0}".format(band_num))
                QCalMax = getattr(metadata,
                                  "QUANTIZE_CAL_MAX_BAND_{0}".format(band_num))
                QCalMin = getattr(metadata,
                                  "QUANTIZE_CAL_MIN_BAND_{0}".format(band_num))

            elif Meta == "oldMeta":
                LMax = getattr(metadata, "LMAX_BAND{0}".format(band_num))
                LMin = getattr(metadata, "LMIN_BAND{0}".format(band_num))
                QCalMax = getattr(metadata, "QCALMAX_BAND{0}".format(band_num))
                QCalMin = getattr(metadata, "QCALMIN_BAND{0}".format(band_num))

            Radraster = (((LMax - LMin) / (QCalMax - QCalMin)) *
                         (null_raster - QCalMin)) + LMin
            Oraster = 0
            del null_raster

            band_rad = "{0}_B{1}".format(TileName, band_num)

            #create the output name and save the TOA radiance tiff
            if outdir:
                outdir = os.path.abspath(outdir)
                outname = core.create_outname(outdir, band_rad, "TOA_Rad",
                                              "tif")
            else:
                folder = os.path.split(meta_path)[0]
                outname = core.create_outname(folder, band_rad, "TOA_Rad",
                                              "tif")

            Radraster.save(outname)
            outlist.append(outname)

            del Radraster

            print("toa radiance saved for Band {0}".format(band_num))

        #if listed band is not a TM/ETM+ sensor band, skip it and print message
        else:
            print(
                "Can only perform reflectance conversion on TM/ETM+ sensor bands"
            )
            print("Skipping band {0}".format(band_num))

    f.close()
    return outlist
Beispiel #13
0
def toa_radiance_8(band_nums, meta_path, outdir=False):
    """
    Top of Atmosphere radiance (in Watts/(square meter * steradians * micrometers)) conversion for landsat 8 data

    To be performed on raw Landsat 8 level 1 data. See link below for details
    see here http://landsat.usgs.gov/Landsat8_Using_Product.php

    Inputs:
    band_nums   A list of desired band numbers such as [3, 4, 5]
    meta_path   The full filepath to the metadata file for those bands
    outdir      Output directory to save converted files.
    """

    meta_path = os.path.abspath(meta_path)
    outlist = []

    #enforce list of band numbers and grab the metadata from the MTL file
    band_nums = core.enf_list(band_nums)
    band_nums = map(str, band_nums)
    meta = grab_meta(meta_path)

    OLI_bands = ['1', '2', '3', '4', '5', '6', '7', '8', '9']

    #loop through each band
    for band_num in band_nums:
        if band_num in OLI_bands:

            #create the band name
            band_path = meta_path.replace("MTL.txt",
                                          "B{0}.tif".format(band_num))
            Qcal = arcpy.Raster(band_path)

            null_raster = arcpy.sa.SetNull(Qcal, Qcal, "VALUE = 0")

            #scrape the attribute data
            Ml = getattr(meta, "RADIANCE_MULT_BAND_{0}".format(
                band_num))  # multiplicative scaling factor
            Al = getattr(meta, "RADIANCE_ADD_BAND_{0}".format(
                band_num))  # additive rescaling factor

            #calculate Top-of-Atmosphere radiance
            TOA_rad = (null_raster * Ml) + Al
            del null_raster

            #create the output name and save the TOA radiance tiff
            if "\\" in meta_path:
                name = meta_path.split("\\")[-1]
            elif "//" in meta_path:
                name = meta_path.split("//")[-1]

            rad_name = name.replace("_MTL.txt", "_B{0}".format(band_num))

            if outdir:
                outdir = os.path.abspath(outdir)
                outname = core.create_outname(outdir, rad_name, "TOA_Rad",
                                              "tif")
            else:
                folder = os.path.split(meta_path)[0]
                outname = core.create_outname(folder, rad_name, "TOA_Rad",
                                              "tif")

            TOA_rad.save(outname)
            outlist.append(outname)
            print("Saved toa_radiance at {0}".format(outname))

        #if listed band is not a OLI sensor band, skip it and print message
        else:
            print(
                "Can only perform reflectance conversion on OLI sensor bands")
            print("Skipping band {0}".format(band_num))

    return outlist