Skip to content

ocm2 modules

ExportSubdatasets(path, hdf_file)

This function takes the folder path and the HDF file as input and exports individual layers to TIFF (named GeoTIFF)

Parameters:

Name Type Description Default
path str

Path to the folder containing the HDF file.

required
hdf_file str

Name of the HDF file.

required

Returns:

Type Description
opf_tif (str)

Path to the folder containing the GeoTiff files.

Source code in ocm2/ocm2.py
def ExportSubdatasets(path, hdf_file):

    """   
    This function takes the folder path and the HDF file as input and exports individual layers to TIFF (named GeoTIFF)

    Parameters:
        path (str): Path to the folder containing the HDF file.
        hdf_file (str): Name of the HDF file.

    Returns:
        opf_tif (str): Path to the folder containing the GeoTiff files.

    """
    opf_tif = os.path.join(path, 'GeoTiff')
    if os.path.exists(opf_tif):
        shutil.rmtree(opf_tif)
    os.makedirs(opf_tif)

    inp_hdf = os.path.join(path, hdf_file)
    hdf_ds = gdal.Open(inp_hdf, gdal.GA_ReadOnly)
    subdatasets = hdf_ds.GetSubDatasets()

    for i in range(0, len(subdatasets)):
        subdataset_name = subdatasets[i][0]
        band_ds = gdal.Open(subdataset_name, gdal.GA_ReadOnly)
        band_path = os.path.join(opf_tif, 'band{0}.TIF'.format(i))
        if band_ds.RasterCount > 1:
            for j in range(1,band_ds.RasterCount + 1):
                band = band_ds.GetRasterBand(j)
                band_array = band.ReadAsArray()
        else:
            band_array = band_ds.ReadAsArray()

        out_ds = gdal.GetDriverByName('GTiff').Create(band_path,
                                                      band_ds.RasterXSize,
                                                      band_ds.RasterYSize,
                                                      1,
                                                      gdal.GDT_Float64,
                                                      ['COMPRESS=LZW', 'TILED=YES'])


        out_ds.SetGeoTransform(band_ds.GetGeoTransform())
        out_ds.SetProjection(band_ds.GetProjection())
        out_ds.GetRasterBand(1).WriteArray(band_array)
        out_ds.GetRasterBand(1).SetNoDataValue(-32768)

    out_ds = None

    return opf_tif

Georeference(inpf, gtif, meta, opf_ref)

This function georeferences the GeoTiff files using the metadata of the HDF file.

Parameters:

Name Type Description Default
inpf str

Path to the folder containing the GeoTiff files.

required
gtif str

Name of the GeoTiff file.

required
meta dict

Dictionary containing the metadata of the HDF file.

required

Returns:

Type Description
opf_ref (str)

Path to the folder containing the georeferenced GeoTiff files.

Source code in ocm2/ocm2.py
def Georeference(inpf, gtif, meta, opf_ref):

    """
    This function georeferences the GeoTiff files using the metadata of the HDF file.

    Parameters:
        inpf (str): Path to the folder containing the GeoTiff files.
        gtif (str): Name of the GeoTiff file.
        meta (dict): Dictionary containing the metadata of the HDF file.

    Returns:
        opf_ref (str): Path to the folder containing the georeferenced GeoTiff files.

    """

    inp_file = os.path.join(inpf, gtif)
    band_tif = gdal.Open(inp_file)
    ext = GetExtent(band_tif)

    ext_pos = [(abs(val[0]), abs(val[1])) for val in ext]

    out_file = os.path.join(opf_ref, os.path.basename(gtif).split('.')[0] + '_georef.TIF')
    shutil.copy(inp_file, out_file)
    ds = gdal.Open(out_file, gdal.GA_Update)
    sr = osr.SpatialReference()
    sr.ImportFromEPSG(4326) 


    '''
    Enter the GCPs
    Format: [map x-coordinate(longitude)], [map y-coordinate (latitude)], [elevation],
    [image column index(x)], [image row index (y)]
    If map pixel is negative, multiply it with -1 to make positive since GDAL can't handle negative pixel position that well.

    '''

    gcps = [gdal.GCP(meta[0][0], meta[0][1], 0, ext_pos[0][0], ext_pos[0][1]), 
            gdal.GCP(meta[1][0], meta[1][1], 0, ext_pos[1][0], ext_pos[1][1]),
            gdal.GCP(meta[2][0], meta[2][1], 0, ext_pos[2][0], ext_pos[2][1]), 
            gdal.GCP(meta[3][0], meta[3][1], 0, ext_pos[3][0], ext_pos[3][1])]

    ds.SetGCPs(gcps, sr.ExportToWkt())
    ds = None

    return opf_ref

GetExtent(ds)

This function returns the extent of the raster.

Parameters:

Name Type Description Default
ds object

GDAL dataset object.

required

Returns:

Type Description
(xmin, ymax), (xmax, ymax), (xmax, ymin), (xmin, ymin) (tuple)

Extent of the raster.

Source code in ocm2/ocm2.py
def GetExtent(ds):

    """
    This function returns the extent of the raster. 

    Parameters:
        ds (object): GDAL dataset object.

    Returns:
        (xmin, ymax), (xmax, ymax), (xmax, ymin), (xmin, ymin) (tuple): Extent of the raster.

    """

    xmin, xpixel, _, ymax, _, ypixel = ds.GetGeoTransform()
    width, height = ds.RasterXSize, ds.RasterYSize
    xmax = xmin + width * xpixel
    ymin = ymax + height * ypixel

    return (xmin, ymax), (xmax, ymax), (xmax, ymin), (xmin, ymin)

calc_toa(rad, sun_elev, band_no)

This function calculates the top of atmosphere reflectance.

Parameters:

Name Type Description Default
rad numpy array

Array containing the radiance values.

required
sun_elev float

Sun elevation angle.

required
band_no int

Band number.

required

Returns:

Type Description
toa_reflectance (numpy array)

Array containing the top of atmosphere reflectance values.

Source code in ocm2/ocm2.py
def calc_toa(rad, sun_elev, band_no):

    """
    This function calculates the top of atmosphere reflectance.

    Parameters:
        rad (numpy array): Array containing the radiance values.
        sun_elev (float): Sun elevation angle.
        band_no (int): Band number.

    Returns:
        toa_reflectance (numpy array): Array containing the top of atmosphere reflectance values.

    """

    esol = [1.72815, 1.85211, 1.9721, 1.86697, 1.82781, 1.65765, 1.2897, 0.952073]
    toa_reflectance = (np.pi * 1 * rad * 10) / (esol[band_no] * 1000 * math.sin(math.radians(sun_elev)))
    return toa_reflectance

cloudmask_ocm(inpf, filelist)

This function creates the cloud mask based on Mishra et al. (2018).

Parameters:

Name Type Description Default
inpf str

Path to the folder containing the GeoTiff files.

required
filelist list

List containing the GeoTiff files.

required

Returns:

Type Description
cldmsk (numpy array)

Array containing the cloud mask.

Source code in ocm2/ocm2.py
def cloudmask_ocm(inpf, filelist):

    """
    This function creates the cloud mask based on Mishra et al. (2018).

    Parameters:
        inpf (str): Path to the folder containing the GeoTiff files.
        filelist (list): List containing the GeoTiff files.

    Returns:
        cldmsk (numpy array): Array containing the cloud mask.

    """

    toa_sum = sum_toa(filelist)
    toa_diff, toa_ratio, shape, profile = toa_other(filelist) 

    cldmsk = np.zeros(shape, dtype = 'float32')
    cldmsk = np.where(((toa_sum > 2.7) & (toa_ratio > 1.5) & (toa_diff < 0)), 1, 0)

    with (rasterio.open)((os.path.join(inpf, 'cloud_mask.TIF')), 'w', **profile) as (dst):
        dst.write(cldmsk)
    dst.close()

    return cldmsk

do_cldmsk(opf_ref)

This function calls the function that creates the cloud mask.

Parameters:

Name Type Description Default
opf_ref str

Path to the folder containing the output georeferenced GeoTiff files.

required

Returns:

Type Description

None

Source code in ocm2/ocm2.py
def do_cldmsk(opf_ref):

    """
    This function calls the function that creates the cloud mask.

    Parameters:
        opf_ref (str): Path to the folder containing the output georeferenced GeoTiff files.

    Returns:
        None

    """

    files = []

    original = os.listdir(opf_ref)
    gtif = list(filter(lambda x: x.endswith(("TIF", "tif", "img")), original))
    for band_name in gtif:
        if (int(''.join(list(filter(str.isdigit, band_name.split('.')[0].split('_')[0]))))) <= 7:
            filelist = list_files(opf_ref, band_name, files)

    cldmsk = cloudmask_ocm(opf_ref, filelist)

    return None

do_georef(opf_ref, meta, opf_georef)

This function calls the function that georeferences the top of atmosphere reflectance GeoTiff files.

Parameters:

Name Type Description Default
geo_ref str

Path to the folder containing the georeferenced GeoTiff files.

required
meta list

List containing the metadata of the HDF files.

required
opf_georef str

Path to the folder containing the output georeferenced GeoTiff files.

required

Returns:

Type Description
opf_georef (str)

Path to the folder containing the output georeferenced GeoTiff files.

Source code in ocm2/ocm2.py
def do_georef(opf_ref, meta, opf_georef):

    """
    This function calls the function that georeferences the top of atmosphere reflectance GeoTiff files.

    Parameters:
        geo_ref (str): Path to the folder containing the georeferenced GeoTiff files.
        meta (list): List containing the metadata of the HDF files.
        opf_georef (str): Path to the folder containing the output georeferenced GeoTiff files. 

    Returns:
        opf_georef (str): Path to the folder containing the output georeferenced GeoTiff files.

    """

    original = os.listdir(opf_ref)
    gtif = list(filter(lambda x: x.endswith(("TIF", "tif", "img")), original))
    for band_name in gtif:
        Georeference(opf_ref, band_name, meta, opf_georef)

    return opf_georef

do_ref(opf_tif, meta, opf_ref)

This function calls the function that creates the top of atmosphere reflectance GeoTiff files.

Parameters:

Name Type Description Default
opf_tif str

Path to the folder containing the GeoTiff files.

required
meta list

List containing the metadata of the GeoTiff files.

required
opf_ref str

Path to the folder containing the output reflectance GeoTiff files. Temporary folder.

required

Returns:

Type Description

None

Source code in ocm2/ocm2.py
def do_ref(opf_tif, meta, opf_ref):

    """
    This function calls the function that creates the top of atmosphere reflectance GeoTiff files.

    Parameters:
        opf_tif (str): Path to the folder containing the GeoTiff files.
        meta (list): List containing the metadata of the GeoTiff files.
        opf_ref (str): Path to the folder containing the output reflectance GeoTiff files. Temporary folder.

    Returns:
        None

    """

    original = os.listdir(opf_tif)
    gtif = list(filter(lambda x: x.endswith(("TIF", "tif", "img")), original))
    for band_name in gtif:
        if (int(''.join(list(filter(str.isdigit, band_name.split('.')[0].split('_')[0]))))) <= 7:
            toa_convert(opf_tif, band_name, opf_ref, meta[4])
        else:
            shutil.copy(os.path.join(opf_tif, band_name), os.path.join(opf_ref, band_name))

    return None

list_files(inpf, inp_name, files)

This function lists the GeoTiff files.

Parameters:

Name Type Description Default
inpf str

Path to the folder containing the GeoTiff files.

required
inp_name str

Name of the GeoTiff file.

required
files list

List containing the GeoTiff files. Empty list at the beginning.

required

Returns:

Type Description
files (list)

List containing the GeoTiff files.

Source code in ocm2/ocm2.py
def list_files(inpf, inp_name, files):

    """
    This function lists the GeoTiff files.

    Parameters:
        inpf (str): Path to the folder containing the GeoTiff files.
        inp_name (str): Name of the GeoTiff file.
        files (list): List containing the GeoTiff files. Empty list at the beginning.

    Returns:
        files (list): List containing the GeoTiff files.

    """

    files.append(os.path.join(inpf, inp_name))
    return files

metaInfo(path, hdf_file, input=None)

This function returns the metadata of the HDF file.

Parameters:

Name Type Description Default
path str

Path to the folder containing the HDF file.

required
hdf_file str

Name of the HDF file.

required

Returns: (ulx, uly), (urx, ury), (brx, bry), (blx, bly), (sun_elev) (tuple): Metadata of the HDF file.

Source code in ocm2/ocm2.py
def metaInfo(path, hdf_file, input = None):


    """
    This function returns the metadata of the HDF file.

    Parameters:
        path (str): Path to the folder containing the HDF file.
        hdf_file (str): Name of the HDF file.

    Returns: 
        (ulx,  uly), (urx, ury), (brx, bry), (blx, bly), (sun_elev) (tuple): Metadata of the HDF file.

    """

    inp = gdal.Open(os.path.join(path, hdf_file))
    meta = inp.GetMetadata()

    ulx, uly = float(meta['Upper Left Longitude']), float(meta['Upper Left Latitude'])
    urx, ury = float(meta['Upper Right Longitude']), float(meta['Upper Right Latitude'])
    blx, bly = float(meta['Lower Left Longitude']), float(meta['Lower Left Latitude'])
    brx, bry = float(meta['Lower Right Longitude']), float(meta['Lower Right Latitude'])

    sun_elev = float(meta['Sun Elevation Angle'])

    return (ulx,  uly), (urx, ury), (brx, bry), (blx, bly), (sun_elev)

run_ocm2(path, hdf_file)

This is the main function of the script. It calls all the other functions.

Parameters:

Name Type Description Default
path str

Path to the folder containing the HDF files.

required
hdf_file str

Name of the HDF file.

required

Returns:

Type Description
opf_georef (str)

Path to folder containing georeferenced ToA reflectance files.

Source code in ocm2/ocm2.py
def run_ocm2(path, hdf_file):

    """
    This is the main function of the script. It calls all the other functions. 

    Parameters:
        path (str): Path to the folder containing the HDF files.
        hdf_file (str): Name of the HDF file.

    Returns:
        opf_georef (str): Path to folder containing georeferenced ToA reflectance files.

    """

    meta = metaInfo(path, hdf_file)
    opf_tif = ExportSubdatasets(path, hdf_file)
    print('Done: Layers converted to GeoTIFF. Wait.')

    opf_ref = os.path.join(path, 'Reflectance')
    if os.path.exists(opf_ref):
        shutil.rmtree(opf_ref)
    os.makedirs(opf_ref)

    opf_georef = os.path.join(path, 'Georeferenced')
    if os.path.exists(opf_georef):
        shutil.rmtree(opf_georef)
    os.makedirs(opf_georef)

    do_ref(opf_tif, meta, opf_ref)
    print('Done: Reflectance conversion. Wait.')

    do_cldmsk(opf_ref)
    print('Done: Cloudmasking. Wait.')

    opf_georef = do_georef(opf_ref, meta, opf_georef)
    print('Done: Georeferncing')

    if os.path.exists(opf_tif):
        shutil.rmtree(opf_tif)

    if os.path.exists(opf_ref):
        shutil.rmtree(opf_ref)

    return opf_georef

sum_toa(filelist)

This function sums the top of atmosphere reflectance values.

Parameters:

Name Type Description Default
filelist list

List containing the GeoTiff files.

required

Returns:

Type Description
arr (numpy array)

Array containing the sum of the top of atmosphere reflectance values.

Source code in ocm2/ocm2.py
def sum_toa(filelist):

    """
    This function sums the top of atmosphere reflectance values.

    Parameters:
        filelist (list): List containing the GeoTiff files.

    Returns:
        arr (numpy array): Array containing the sum of the top of atmosphere reflectance values.

    """

    with rasterio.open(filelist[0]) as r:
        arr = r.read()
        profile = r.profile

    for f in filelist[1:]:
        with rasterio.open(f) as r:
            assert profile == r.profile, 'stopping, file {} and  {} do not have matching profiles'.format(filelist[0], f)
            arr = arr + r.read()

    return (arr)

toa_convert(inpf, inp_name, opf, sun_elev)

This function converts the radiance values to top of atmosphere reflectance values.

Parameters:

Name Type Description Default
inpf str

Path to the folder containing the GeoTiff files.

required
inp_name str

Name of the GeoTiff file.

required
opf str

Path to the folder containing the output GeoTiff files.

required
sun_elev float

Sun elevation angle.

required

Returns:

Type Description
opf (str)

Path to the folder containing the output GeoTiff files.

Source code in ocm2/ocm2.py
def toa_convert(inpf, inp_name, opf, sun_elev):

    """
    This function converts the radiance values to top of atmosphere reflectance values.

    Parameters:
        inpf (str): Path to the folder containing the GeoTiff files.
        inp_name (str): Name of the GeoTiff file.
        opf (str): Path to the folder containing the output GeoTiff files.
        sun_elev (float): Sun elevation angle.

    Returns:
        opf (str): Path to the folder containing the output GeoTiff files.

    """

    band_no = int(''.join(list(filter(str.isdigit, inp_name.split('.')[0].split('_')[0]))))
    with rasterio.open(os.path.join(inpf, inp_name)) as (r):
        rad = r.read(1).astype('float32')
        profile = r.profile

    toa = calc_toa(rad, sun_elev, band_no)
    toa[toa < 0] = 0.0
    toa[toa > 2] = 0.0   
    op_name = os.path.basename(inp_name).split('.')[0] + '.TIF'
    with (rasterio.open)((os.path.join(opf, op_name)), 'w', **profile) as (dataset):
        dataset.write(toa, 1)
    dataset.close()

    return opf

toa_other(filelist)

This function calculates the difference and ratio of the top of atmosphere reflectance values.

Parameters:

Name Type Description Default
filelist list

List containing the GeoTiff files.

required

Returns:

Type Description
toa_diff (numpy array)

Array containing the difference of the top of atmosphere reflectance values. toa_ratio (numpy array): Array containing the ratio of the top of atmosphere reflectance values. shape (tuple): Tuple containing the shape of the GeoTiff file. profile (dict): Dictionary containing the profile of the GeoTiff file.

Source code in ocm2/ocm2.py
def toa_other(filelist):

    """
    This function calculates the difference and ratio of the top of atmosphere reflectance values.

    Parameters:
        filelist (list): List containing the GeoTiff files.

    Returns:
        toa_diff (numpy array): Array containing the difference of the top of atmosphere reflectance values.
        toa_ratio (numpy array): Array containing the ratio of the top of atmosphere reflectance values.
        shape (tuple): Tuple containing the shape of the GeoTiff file.
        profile (dict): Dictionary containing the profile of the GeoTiff file.

    """

    one, two, seven = [filelist[check] for check in [0,1,6]]

    with rasterio.open(one) as r:
        band1 = r.read()
        profile = r.profile
    shape = band1.shape
    with rasterio.open(two) as r:
        band2 = r.read()
    with rasterio.open(seven) as r:
        band7 = r.read()


    band2[band2 == 0.0] = np.nan
    band7[band7 == 0.0] = np.nan

    toa_diff = band2 - band1
    toa_ratio = band2/band7 

    return (toa_diff, toa_ratio, shape, profile)

Last update: 2023-06-22