Skip to content
Snippets Groups Projects
modis2airs.py 3.23 KiB

# first stage of bringing MODIS radiances into terms of AIRS spatial
# footprints (after collocation)

import numpy
import sys

from flags import *
from pyhdf.SD import SD, SDC
from util import HdfWriter

# helper function for reading in MODIS radiances. returns a numpy
# array with dimensions:
#   - 16 (MODIS band, 20-25,27-36)
#   - 2030 or 2040 (MODIS along track index)
#   - 1354 (MODIS across track index)
def read_modis_radiances(filename):

    sd = SD(filename)
    sds = sd.select('EV_1KM_Emissive')
    scales = numpy.array(sds.radiance_scales).reshape((16, 1, 1))
    offsets = numpy.array(sds.radiance_offsets).reshape((16, 1, 1))
    raw = sds.get()
    bad_idxs = (raw >= 32768)
    rads = scales * (raw - offsets)
    rads[bad_idxs] = -9999.0
    return rads
    
# verify command line arguments
if len(sys.argv) != 4:
    print ('usage: %s <modis_file> <collocation_file> <output_file>' %
           sys.argv[0])
    sys.exit(1)
modis_file = sys.argv[1]
coll_file = sys.argv[2]
output_file = sys.argv[3]

# read in the MODIS radiances
in_rads = read_modis_radiances(modis_file)

# and the collocation data
coll_sd = SD(coll_file)
num_colls = coll_sd.select('Number_Of_MODIS_FOV').get()
modis_along_idxs = coll_sd.select('MODIS_Along_Track_IDX').get()
modis_across_idxs = coll_sd.select('MODIS_Across_Track_IDX').get()

# set up numpy arrays for output
n_arr = numpy.empty((16, 135, 90), numpy.int32)
rad_sum_arr = numpy.empty((16, 135, 90), numpy.float64)
rad_squared_sum_arr = numpy.empty((16, 135, 90), numpy.float64)
flags_arr = numpy.zeros((16, 135, 90), numpy.int8)

# loop over each AIRS pixel
for airs_row in range(135):
    for airs_col in range(90):

        # avoid excessive indexing in the code below
        n = n_arr[:,airs_row,airs_col]
        rads_sum = rad_sum_arr[:,airs_row,airs_col]
        rads_squared_sum = rad_squared_sum_arr[:,airs_row,airs_col]
        flags = flags_arr[:,airs_row,airs_col]

        # use the collocation data to pull out overlapping MODIS
        # radiances (skip this AIRS FOV if there are none)
        num = num_colls[airs_row,airs_col]
        if num == 0:
            n[:] = 0
            rads_sum[:] = 0.0
            rads_squared_sum[:] = 0.0
            continue
        along_idxs = modis_along_idxs[airs_row,airs_col,:num] - 1
        across_idxs = modis_across_idxs[airs_row,airs_col,:num] - 1
        rads = in_rads[:,along_idxs,across_idxs]

        # if there's any invalid data amongst the collocated MODIS
        # pixels, filter it out and set the INVALID flag for the
        # affected bands
        bad_idxs = (rads == -9999.0)
        flags[bad_idxs.any(axis=1)] |= INVALID

        # determine how many pixels are being used per band
        n[:] = num - bad_idxs.sum(axis=1)

        # get radiance sum and squared sum (bad measurements are set
        # to zero so they have no effect on the result)
        # FIXME: use masked arrays for this instead?
        rads[bad_idxs] = 0.0
        rads_sum[:] = rads.sum(axis=1)
        rads_squared_sum[:] = (rads * rads).sum(axis=1)

# write results to HDF
writer = HdfWriter(output_file)
writer.write('MODIS_N', n_arr)
writer.write('MODIS_Radiance_Sum', rad_sum_arr)
writer.write('MODIS_Radiance_Squared_Sum', rad_squared_sum_arr)
writer.write('MODIS_Flags', flags_arr)