Beispiel #1
0
    def process(self, *args, **kwargs):
        """ Process all products """
        products = super(modisData, self).process(*args, **kwargs)
        if len(products) == 0:
            return

        bname = os.path.join(self.path, self.basename)

        for key, val in products.requested.items():
            start = datetime.datetime.now()

            # Check for asset availability
            assets = self._products[val[0]]['assets']
            missingassets = []
            availassets = []
            allsds = []

            # Default sensor for products
            sensor = 'MCD'

            for asset in assets:
                try:
                    sds = self.assets[asset].datafiles()
                except Exception:
                    missingassets.append(asset)
                else:
                    availassets.append(asset)
                    allsds.extend(sds)
            if not availassets:
                # some products aren't available for every day but this is trying every day
                VerboseOut(
                    'There are no available assets (%s) on %s for tile %s' % (
                        str(missingassets),
                        str(self.date),
                        str(self.id),
                    ), 5)
                continue

            meta = self.meta_dict()
            meta['AVAILABLE_ASSETS'] = ' '.join(availassets)

            if val[0] == "quality":
                fname = '%s_%s_%s.tif' % (bname, sensor, key)
                if os.path.lexists(fname):
                    os.remove(fname)
                os.symlink(allsds[0], fname)
                imgout = gippy.GeoImage(fname)

            # LAND VEGETATION INDICES PRODUCT
            if val[0] == "indices":
                VERSION = "2.0"
                meta['VERSION'] = VERSION
                sensor = 'MCD'
                fname = '%s_%s_%s' % (bname, sensor, key)

                refl = gippy.GeoImage(allsds)

                missing = 32767

                redimg = refl[0].Read()
                nirimg = refl[1].Read()
                bluimg = refl[2].Read()
                grnimg = refl[3].Read()
                mirimg = refl[5].Read()
                swrimg = refl[6].Read()  # formerly swir2

                redimg[redimg < 0.0] = 0.0
                nirimg[nirimg < 0.0] = 0.0
                bluimg[bluimg < 0.0] = 0.0
                grnimg[grnimg < 0.0] = 0.0
                mirimg[mirimg < 0.0] = 0.0
                swrimg[swrimg < 0.0] = 0.0

                redimg[redimg > 1.0] = 1.0
                nirimg[nirimg > 1.0] = 1.0
                bluimg[bluimg > 1.0] = 1.0
                grnimg[grnimg > 1.0] = 1.0
                mirimg[mirimg > 1.0] = 1.0
                swrimg[swrimg > 1.0] = 1.0

                # red, nir
                ndvi = missing + np.zeros_like(redimg)
                wg = np.where((redimg != missing) & (nirimg != missing)
                              & (redimg + nirimg != 0.0))
                ndvi[wg] = (nirimg[wg] - redimg[wg]) / (nirimg[wg] +
                                                        redimg[wg])

                # nir, mir
                lswi = missing + np.zeros_like(redimg)
                wg = np.where((nirimg != missing) & (mirimg != missing)
                              & (nirimg + mirimg != 0.0))
                lswi[wg] = (nirimg[wg] - mirimg[wg]) / (nirimg[wg] +
                                                        mirimg[wg])

                # blu, grn, red
                vari = missing + np.zeros_like(redimg)
                wg = np.where((grnimg != missing) & (redimg != missing)
                              & (bluimg != missing)
                              & (grnimg + redimg - bluimg != 0.0))
                vari[wg] = (grnimg[wg] - redimg[wg]) / (
                    grnimg[wg] + redimg[wg] - bluimg[wg])

                # blu, grn, red, nir
                brgt = missing + np.zeros_like(redimg)
                wg = np.where((nirimg != missing) & (redimg != missing)
                              & (bluimg != missing) & (grnimg != missing))
                brgt[wg] = 0.3 * bluimg[wg] + 0.3 * redimg[wg] + 0.1 * nirimg[
                    wg] + 0.3 * grnimg[wg]

                # red, mir, swr
                satvi = missing + np.zeros_like(redimg)
                # I think the following line has an error:
                # wg = np.where((redimg != missing)&(mirimg != missing)&(swrimg != missing)&(((mirimg + redimg + 0.5)*swrimg) != 0.0))
                wg = np.where((redimg != missing) & (mirimg != missing)
                              & (swrimg != missing)
                              & ((mirimg + redimg + 0.5) != 0.0))
                satvi[wg] = (((mirimg[wg] - redimg[wg]) /
                              (mirimg[wg] + redimg[wg] + 0.5)) *
                             1.5) - (swrimg[wg] / 2.0)

                print "writing", fname

                # create output gippy image
                imgout = gippy.GeoImage(fname, refl, gippy.GDT_Int16, 5)

                imgout.SetNoData(missing)
                imgout.SetOffset(0.0)
                imgout.SetGain(0.0001)

                imgout[0].Write(ndvi)
                imgout[1].Write(lswi)
                imgout[2].Write(vari)
                imgout[3].Write(brgt)
                imgout[4].Write(satvi)

                imgout.SetBandName('NDVI', 1)
                imgout.SetBandName('LSWI', 2)
                imgout.SetBandName('VARI', 3)
                imgout.SetBandName('BRGT', 4)
                imgout.SetBandName('SATVI', 5)

            ###################################################################
            # SNOW/ICE COVER PRODUCT
            if val[0] == "snow":
                VERSION = "1.0"
                meta['VERSION'] = VERSION
                fname = '%s_%s_%s' % (bname, sensor, key)

                if not missingassets:
                    availbands = [0, 1]
                    snowsds = [allsds[0], allsds[3], allsds[4], allsds[7]]
                elif missingassets[0] == 'MYD10A1':
                    availbands = [0]
                    snowsds = [allsds[0], allsds[3]]
                elif missingassets[0] == 'MOD10A1':
                    availbands = [1]
                    snowsds = [allsds[0], allsds[3]]
                else:
                    raise

                img = gippy.GeoImage(snowsds)

                # there are two snow bands
                for iband, band in enumerate(availbands):

                    # get the data values for both bands
                    cover = img[2 * iband].Read()
                    frac = img[2 * iband + 1].Read()

                    # check out frac
                    wbad1 = np.where((frac == 200) | (frac == 201)
                                     | (frac == 211) | (frac == 250)
                                     | (frac == 254) | (frac == 255))
                    wsurface1 = np.where((frac == 225) | (frac == 237)
                                         | (frac == 239))
                    wvalid1 = np.where((frac >= 0) & (frac <= 100))

                    nbad1 = len(wbad1[0])
                    nsurface1 = len(wsurface1[0])
                    nvalid1 = len(wvalid1[0])
                    assert nbad1 + nsurface1 + nvalid1 == frac.size, "frac contains invalid values"

                    # check out cover
                    wbad2 = np.where((cover == 0) | (cover == 1)
                                     | (cover == 11) | (cover == 50)
                                     | (cover == 254) | (cover == 255))
                    wsurface2 = np.where((cover == 25) | (cover == 37)
                                         | (cover == 39))
                    wvalid2 = np.where((cover == 100) | (cover == 200))

                    nbad2 = len(wbad2[0])
                    nsurface2 = len(wsurface2[0])
                    nvalid2 = len(wvalid2[0])
                    assert nbad2 + nsurface2 + nvalid2 == cover.size, "cover contains invalid values"

                    # assign output data here
                    coverout = np.zeros_like(cover, dtype=np.uint8)
                    fracout = np.zeros_like(frac, dtype=np.uint8)

                    fracout[wvalid1] = frac[wvalid1]
                    fracout[wsurface1] = 0
                    fracout[wbad1] = 127
                    coverout[wvalid2] = 100
                    coverout[wsurface2] = 0
                    coverout[wbad2] = 127

                    if len(availbands) == 2:
                        if iband == 0:
                            fracout1 = np.copy(fracout)
                            coverout1 = np.copy(coverout)
                        else:
                            # both the current and previous are valid
                            w = np.where((fracout != 127) & (fracout1 != 127))
                            fracout[w] = np.mean(np.array(
                                [fracout[w], fracout1[w]]),
                                                 axis=0).astype('uint8')

                            # the current is not valid but previous is valid
                            w = np.where((fracout == 127) & (fracout1 != 127))
                            fracout[w] = fracout1[w]

                            # both the current and previous are valid
                            w = np.where((coverout != 127)
                                         & (coverout1 != 127))
                            coverout[w] = np.mean(np.array(
                                [coverout[w], coverout1[w]]),
                                                  axis=0).astype('uint8')

                            # the current is not valid but previous is valid
                            w = np.where((coverout == 127)
                                         & (coverout1 != 127))
                            coverout[w] = coverout1[w]

                fracmissingcoverclear = np.sum((fracout == 127)
                                               & (coverout == 0))
                fracmissingcoversnow = np.sum((fracout == 127)
                                              & (coverout == 100))
                fracclearcovermissing = np.sum((fracout == 0)
                                               & (coverout == 127))
                fracclearcoversnow = np.sum((fracout == 0) & (coverout == 100))
                fracsnowcovermissing = np.sum((fracout > 0) & (fracout <= 100)
                                              & (coverout == 127))
                fracsnowcoverclear = np.sum((fracout > 0) & (fracout <= 100)
                                            & (coverout == 0))
                #fracmostlycoverclear = np.sum((fracout > 50) & (fracout <= 100) & (coverout == 0))
                totsnowfrac = int(0.01 * np.sum(fracout[fracout <= 100]))
                totsnowcover = int(0.01 * np.sum(coverout[coverout <= 100]))
                numvalidfrac = np.sum(fracout != 127)
                numvalidcover = np.sum(coverout != 127)

                if totsnowcover == 0 or totsnowfrac == 0:
                    print "no snow or ice: skipping", str(self.date), str(
                        self.id), str(missingassets)

                meta['FRACMISSINGCOVERCLEAR'] = fracmissingcoverclear
                meta['FRACMISSINGCOVERSNOW'] = fracmissingcoversnow
                meta['FRACCLEARCOVERMISSING'] = fracclearcovermissing
                meta['FRACCLEARCOVERSNOW'] = fracclearcoversnow
                meta['FRACSNOWCOVERMISSING'] = fracsnowcovermissing
                meta['FRACSNOWCOVERCLEAR'] = fracsnowcoverclear
                meta['FRACMOSTLYCOVERCLEAR'] = np.sum((fracout > 50)
                                                      & (fracout <= 100)
                                                      & (coverout == 0))
                meta['TOTSNOWFRAC'] = totsnowfrac
                meta['TOTSNOWCOVER'] = totsnowcover
                meta['NUMVALIDFRAC'] = numvalidfrac
                meta['NUMVALIDCOVER'] = numvalidcover

                # create output gippy image
                imgout = gippy.GeoImage(fname, img, gippy.GDT_Byte, 2)
                imgout.SetNoData(127)
                imgout.SetOffset(0.0)
                imgout.SetGain(1.0)
                imgout.SetBandName('Snow Cover', 1)
                imgout.SetBandName('Fractional Snow Cover', 2)

                imgout[0].Write(coverout)
                imgout[1].Write(fracout)

                VerboseOut('Completed writing %s' % fname)

            ###################################################################
            # TEMPERATURE PRODUCT (DAILY)
            if val[0] == "temp":
                VERSION = "1.1"
                meta['VERSION'] = VERSION
                sensor = 'MOD-MYD'
                fname = '%s_%s_%s' % (bname, sensor, key)

                if not missingassets:
                    availbands = [0, 1, 2, 3]
                    tempsds = [allsds[0], allsds[4], allsds[12], allsds[16]]
                    qcsds = [allsds[1], allsds[5], allsds[13], allsds[17]]
                    hoursds = [allsds[2], allsds[6], allsds[14], allsds[18]]
                elif missingassets[0] == 'MYD11A1':
                    availbands = [0, 1]
                    tempsds = [allsds[0], allsds[4]]
                    qcsds = [allsds[1], allsds[5]]
                    hoursds = [allsds[2], allsds[6]]
                elif missingassets[0] == 'MOD11A1':
                    availbands = [2, 3]
                    tempsds = [allsds[0], allsds[4]]
                    qcsds = [allsds[1], allsds[5]]
                    hoursds = [allsds[2], allsds[6]]
                else:
                    raise

                tempbands = gippy.GeoImage(tempsds)
                qcbands = gippy.GeoImage(qcsds)
                hourbands = gippy.GeoImage(hoursds)

                imgout = gippy.GeoImage(fname, tempbands, gippy.GDT_UInt16, 5)
                imgout.SetNoData(65535)
                imgout.SetGain(0.02)

                # there are four temperature bands
                for iband, band in enumerate(availbands):
                    # get meta name template info
                    basename = tempbands[iband].Basename()
                    platform = self.Asset._sensors[basename[:3]]['description']

                    if basename.find('daytime'):
                        dayornight = 'day'
                    elif basename.find('nighttime'):
                        dayornight = 'night'
                    else:
                        raise Exception(
                            '%s appears to be an invalid MODIS temperature project'
                            % basename)

                    qc = qcbands[iband].Read()

                    # first two bits are 10 or 11
                    newmaskbad = binmask(qc, 2)
                    # first two bits are 00 or 01
                    newmaskgood = ~binmask(qc, 2)
                    # first two bits are 00
                    newmaskbest = ~binmask(qc, 1) & ~binmask(qc, 2)

                    if iband == 0:
                        bestmask = np.zeros_like(qc, dtype='uint16')

                    bestmask += (math.pow(2, band) *
                                 newmaskbest).astype('uint16')

                    numbad = np.sum(newmaskbad)
                    #fracbad = np.sum(newmaskbad) / float(newmaskbad.size)

                    numgood = np.sum(newmaskgood)
                    #fracgood = np.sum(newmaskgood) / float(newmaskgood.size)
                    assert numgood == qc.size - numbad

                    numbest = np.sum(newmaskbest)
                    #fracbest = np.sum(newmaskbest) / float(newmaskbest.size)

                    metaname = "NUMBAD_%s_%s" % (dayornight, platform)
                    metaname = metaname.upper()
                    # print "metaname", metaname
                    meta[metaname] = str(numbad)

                    metaname = "NUMGOOD_%s_%s" % (dayornight, platform)
                    metaname = metaname.upper()
                    # print "metaname", metaname
                    meta[metaname] = str(numgood)

                    metaname = "NUMBEST_%s_%s" % (dayornight, platform)
                    metaname = metaname.upper()
                    # print "metaname", metaname
                    meta[metaname] = str(numbest)

                    # overpass time
                    hournodatavalue = hourbands[iband].NoDataValue()
                    hour = hourbands[iband].Read()
                    hour = hour[hour != hournodatavalue]
                    try:
                        #hourmin = hour.min()
                        hourmean = hour.mean()
                        #hourmax = hour.max()
                        # print "hour.min(), hour.mean(), hour.max()", hour.min(), hour.mean(), hour.max()
                    except:
                        hourmean = 0

                    metaname = "MEANOVERPASSTIME_%s_%s" % (dayornight,
                                                           platform)
                    metaname = metaname.upper()
                    meta[metaname] = str(hourmean)

                    tempbands[iband].Process(imgout[band])

                imgout[4].SetGain(1.0)
                imgout[4].Write(bestmask)
                imgout.SetBandName('Temperature Daytime Terra', 1)
                imgout.SetBandName('Temperature Nighttime Terra', 2)
                imgout.SetBandName('Temperature Daytime Aqua', 3)
                imgout.SetBandName('Temperature Nighttime Aqua', 4)
                imgout.SetBandName('Temperature Best Quality', 5)

            ###################################################################
            # OBSERVATION TIME PRODUCT (DAILY)
            if val[0] == "obstime":
                VERSION = "1"
                meta['VERSION'] = VERSION
                fname = '%s_%s_%s' % (bname, 'MOD-MYD', key)

                if not missingassets:
                    availbands = [0, 1, 2, 3]
                    hoursds = [allsds[2], allsds[6], allsds[14], allsds[18]]
                elif missingassets[0] == 'MYD11A1':
                    availbands = [0, 1]
                    hoursds = [allsds[2], allsds[6]]
                elif missingassets[0] == 'MOD11A1':
                    availbands = [2, 3]
                    hoursds = [allsds[2], allsds[6]]
                else:
                    raise

                hourbands = gippy.GeoImage(hoursds)

                imgout = gippy.GeoImage(fname, hourbands, gippy.GDT_Byte, 4)
                imgout.SetNoData(0)
                imgout.SetGain(0.1)

                # there are four temperature bands
                for iband, band in enumerate(availbands):
                    # get meta name template info
                    basename = hourbands[iband].Basename()
                    platform = self.Asset._sensors[basename[:3]]['description']

                    if basename.find('daytime'):
                        dayornight = 'day'
                    elif basename.find('nighttime'):
                        dayornight = 'night'
                    else:
                        raise Exception(
                            '%s appears to be an invalid MODIS temperature project'
                            % basename)

                    hourbands[iband].Process(imgout[band])

                imgout.SetBandName('Observation Time Daytime Terra', 1)
                imgout.SetBandName('Observation Time Nighttime Terra', 2)
                imgout.SetBandName('Observation Time Daytime Aqua', 3)
                imgout.SetBandName('Observation Time Nighttime Aqua', 4)

            ###################################################################
            # NDVI (8-day) - Terra only
            if val[0] == "ndvi8":
                VERSION = "1.0"
                meta['VERSION'] = VERSION
                sensor = 'MOD'
                fname = '%s_%s_%s' % (bname, sensor, key)

                refl = gippy.GeoImage(allsds)
                refl.SetBandName("RED", 1)
                refl.SetBandName("NIR", 2)
                refl.SetNoData(-28762)

                fouts = dict(Indices(refl, {'ndvi': fname}, meta))
                imgout = gippy.GeoImage(fouts['ndvi'])

            # TEMPERATURE PRODUCT (8-day) - Terra only

            if val[0] == "temp8td":
                sensor = 'MOD'
                fname = '%s_%s_%s.tif' % (bname, sensor, key)
                if os.path.lexists(fname):
                    os.remove(fname)
                os.symlink(allsds[0], fname)
                imgout = gippy.GeoImage(fname)

            if val[0] == "temp8tn":
                sensor = 'MOD'
                fname = '%s_%s_%s.tif' % (bname, sensor, key)
                if os.path.lexists(fname):
                    os.remove(fname)
                os.symlink(allsds[4], fname)
                imgout = gippy.GeoImage(fname)

            # set metadata
            meta = {k: str(v) for k, v in meta.iteritems()}
            imgout.SetMeta(meta)

            # add product to inventory
            self.AddFile(sensor, key, imgout.Filename())
            VerboseOut(
                ' -> %s: processed in %s' %
                (os.path.basename(fname), datetime.datetime.now() - start), 1)
Beispiel #2
0
            # Process Indices
            indices0 = dict(groups['Index'], **groups['Tillage'])
            if len(indices0) > 0:
                start = datetime.now()
                indices = {}
                indices_toa = {}
                for key, val in indices0.items():
                    if 'toa' in val:
                        indices_toa[key] = val
                    else:
                        indices[key] = val
                # Run TOA
                if len(indices_toa) > 0:
                    fnames = [os.path.join(self.path, self.basename + '_' + key) for key in indices_toa]
                    prodout = Indices(reflimg, dict(zip([p[0] for p in indices_toa.values()], fnames)), md)
                    prodout = dict(zip(indices_toa.keys(), prodout.values()))
                    [self.AddFile(sensor, key, fname) for key, fname in prodout.items()]
                # Run atmospherically corrected
                if len(indices) > 0:
                    fnames = [os.path.join(self.path, self.basename + '_' + key) for key in indices]
                    for col in visbands:
                        img[col] = ((img[col] - atm6s.results[col][1]) / atm6s.results[col][0]) * (1.0 / atm6s.results[col][2])
                    prodout = Indices(img, dict(zip([p[0] for p in indices.values()], fnames)), md)
                    prodout = dict(zip(indices.keys(), prodout.values()))
                    [self.AddFile(sensor, key, fname) for key, fname in prodout.items()]
                VerboseOut(' -> %s: processed %s in %s' % (self.basename, indices0.keys(), datetime.now() - start), 1)
            img = None
            # cleanup directory
            try:
                if settings().REPOS[self.Repository.name.lower()]['extract']:
    def process(self, *args, **kwargs):
        """Produce requested products."""
        products = super(modisData, self).process(*args, **kwargs)
        if len(products) == 0:
            return

        bname = os.path.join(self.path, self.basename)

        # example products.requested:
        # {'temp8tn': ['temp8tn'], 'clouds': ['clouds'], . . . }
        # key is only used once far below, and val is only used for val[0].
        for key, val in products.requested.items():
            # TODO replace val[0] below with this more meaningful name
            prod_type = val[0]
            if prod_type in self._productgroups['Index']:
                continue  # indices handled differently below
            start = datetime.datetime.now()
            asset, version, missingassets, availassets, allsds = \
                self.asset_check(prod_type)

            if not availassets:
                # some products aren't available for every day but this is trying every day
                VerboseOut(
                    'There are no available assets (%s) on %s for tile %s' % (
                        str(missingassets),
                        str(self.date),
                        str(self.id),
                    ), 5)
                continue

            meta = {
                'AVAILABLE_ASSETS': ' '.join(availassets)
            }  # TODO obselete?
            a_fnames = [self.assets[at].filename for at in availassets]

            sensor = self._products[prod_type]['sensor']
            fname = self.temp_product_filename(
                sensor, prod_type)  # moved to archive at end of loop

            if val[0] == "landcover":
                os.symlink(allsds[0], fname)
                imgout = gippy.GeoImage(fname)

            if val[0] == "quality":
                if version != 6:
                    raise Exception('product version not supported')
                os.symlink(allsds[0], fname)
                imgout = gippy.GeoImage(fname)

            # LAND VEGETATION INDICES PRODUCT
            # now with QC layer!
            if val[0] == "indices":
                depr_msg = (
                    "'indices' is deprecated, and may be removed in"
                    " the future.  See the Index product group instead.")
                utils.verbose_out(depr_msg, 2, stream=sys.stderr)
                VERSION = "2.0"
                meta['VERSION'] = VERSION
                refl = gippy.GeoImage(allsds)
                missing = 32767

                if version == 6:
                    redimg = refl[7].Read()
                    nirimg = refl[8].Read()
                    bluimg = refl[9].Read()
                    grnimg = refl[10].Read()
                    mirimg = refl[11].Read()
                    swrimg = refl[12].Read()  # swir1, formerly swir2
                    redqcimg = refl[0].Read()
                    nirqcimg = refl[1].Read()
                    bluqcimg = refl[2].Read()
                    grnqcimg = refl[3].Read()
                    mirqcimg = refl[4].Read()
                    swrqcimg = refl[5].Read()
                else:
                    raise Exception('product version not supported')

                # wherever the value is too small, set it to a minimum of 0
                redimg[redimg < 0.0] = 0.0
                nirimg[nirimg < 0.0] = 0.0
                bluimg[bluimg < 0.0] = 0.0
                grnimg[grnimg < 0.0] = 0.0
                mirimg[mirimg < 0.0] = 0.0
                swrimg[swrimg < 0.0] = 0.0

                # wherever the value is too saturated, set it to a max of 1.0
                redimg[(redimg != missing) & (redimg > 1.0)] = 1.0
                nirimg[(nirimg != missing) & (nirimg > 1.0)] = 1.0
                bluimg[(bluimg != missing) & (bluimg > 1.0)] = 1.0
                grnimg[(grnimg != missing) & (grnimg > 1.0)] = 1.0
                mirimg[(mirimg != missing) & (mirimg > 1.0)] = 1.0
                swrimg[(swrimg != missing) & (swrimg > 1.0)] = 1.0

                # red, nir
                # first setup a blank array with everything set to missing
                ndvi = missing + np.zeros_like(redimg)
                # compute the ndvi only where neither input is missing, AND
                # no divide-by-zero error will occur
                wg = np.where((redimg != missing) & (nirimg != missing)
                              & (redimg + nirimg != 0.0))
                ndvi[wg] = (nirimg[wg] - redimg[wg]) / (nirimg[wg] +
                                                        redimg[wg])

                # nir, mir
                lswi = missing + np.zeros_like(redimg)
                wg = np.where((nirimg != missing) & (mirimg != missing)
                              & (nirimg + mirimg != 0.0))
                lswi[wg] = (nirimg[wg] - mirimg[wg]) / (nirimg[wg] +
                                                        mirimg[wg])

                # blu, grn, red
                vari = missing + np.zeros_like(redimg)
                wg = np.where((grnimg != missing) & (redimg != missing)
                              & (bluimg != missing)
                              & (grnimg + redimg - bluimg != 0.0))
                vari[wg] = (grnimg[wg] - redimg[wg]) / (
                    grnimg[wg] + redimg[wg] - bluimg[wg])

                # blu, grn, red, nir
                brgt = missing + np.zeros_like(redimg)
                wg = np.where((nirimg != missing) & (redimg != missing)
                              & (bluimg != missing) & (grnimg != missing))
                brgt[wg] = (0.3 * bluimg[wg] + 0.3 * redimg[wg] +
                            0.1 * nirimg[wg] + 0.3 * grnimg[wg])

                # red, mir, swr
                satvi = missing + np.zeros_like(redimg)
                wg = np.where((redimg != missing) & (mirimg != missing)
                              & (swrimg != missing)
                              & ((mirimg + redimg + 0.5) != 0.0))
                satvi[wg] = (((mirimg[wg] - redimg[wg]) /
                              (mirimg[wg] + redimg[wg] + 0.5)) *
                             1.5) - (swrimg[wg] / 2.0)

                # blu, red, nir
                evi = missing + np.zeros_like(redimg)
                wg = np.where(
                    (bluimg != missing) & (redimg != missing)
                    & (nirimg != missing)
                    & (nirimg + 6.0 * redimg - 7.5 * bluimg + 1.0 != 0.0))
                evi[wg] = (
                    (2.5 * (nirimg[wg] - redimg[wg])) /
                    (nirimg[wg] + 6.0 * redimg[wg] - 7.5 * bluimg[wg] + 1.0))

                qc = np.ones_like(
                    redimg
                )  # mark as poor if all are not missing and not all are good
                w0 = np.where((redqcimg == 0) & (nirqcimg == 0)
                              & (bluqcimg == 0) & (grnqcimg == 0)
                              & (mirqcimg == 0) & (swrqcimg == 0))
                w255 = np.where((redqcimg == 255) | (nirqcimg == 255)
                                | (bluqcimg == 255) | (grnqcimg == 255)
                                | (mirqcimg == 255) | (swrqcimg == 255))
                qc[w0] = 0  # mark as good if they are all good
                qc[w255] = missing  # mark as missing if any are missing

                # create output gippy image
                print("writing", fname)
                imgout = gippy.GeoImage(fname, refl, gippy.GDT_Int16, 7)
                del refl

                imgout.SetNoData(missing)
                imgout.SetOffset(0.0)
                imgout.SetGain(0.0001)
                imgout[6].SetGain(1.0)

                imgout[0].Write(ndvi)
                imgout[1].Write(lswi)
                imgout[2].Write(vari)
                imgout[3].Write(brgt)
                imgout[4].Write(satvi)
                imgout[5].Write(evi)
                imgout[6].Write(qc)

                imgout.SetBandName('NDVI', 1)
                imgout.SetBandName('LSWI', 2)
                imgout.SetBandName('VARI', 3)
                imgout.SetBandName('BRGT', 4)
                imgout.SetBandName('SATVI', 5)
                imgout.SetBandName('EVI', 6)
                imgout.SetBandName('QC', 7)

            if val[0] == "clouds":
                # cloud mask product
                meta['VERSION'] = '1.0'
                img = gippy.GeoImage(allsds)

                data = img[0].Read()
                clouds = np.zeros_like(data)

                # See table 3 in the user guide:
                # https://nsidc.org/sites/nsidc.org/files/files/
                #   MODIS-snow-user-guide-C6.pdf
                nodata = 127
                for v in [200, 201, 211, 254, 255]:
                    clouds[data == v] = nodata
                clouds[data == 237] = 0
                clouds[data == 239] = 0
                clouds[data == 250] = 1

                # create output gippy image
                imgout = gippy.GeoImage(fname, img, gippy.GDT_Byte, 1)
                del img
                imgout.SetNoData(nodata)
                imgout.SetOffset(0.0)
                imgout.SetGain(1.0)
                imgout.SetBandName('Cloud Cover', 1)
                imgout[0].Write(clouds)

            if val[0] in ('snow', 'fsnow'):
                # (fsnow was removed entirely due to being a big copypasta
                # of the snow block; what follows is snow)
                raise NotImplementedError("not compatible with collection 6; "
                                          "use NDSI instead")
                VERSION = "1.0"
                meta['VERSION'] = VERSION

                if not missingassets:
                    availbands = [0, 1]
                    snowsds = [allsds[0], allsds[3], allsds[4], allsds[7]]
                elif missingassets[0] == 'MYD10A1':
                    availbands = [0]
                    snowsds = [allsds[0], allsds[3]]
                elif missingassets[0] == 'MOD10A1':
                    availbands = [1]
                    snowsds = [allsds[0], allsds[3]]
                else:
                    raise IOError("Missing both MOD10A1 and MYD10A1; can't "
                                  "continue")

                img = gippy.GeoImage(snowsds)

                # there are two snow bands
                for iband, band in enumerate(availbands):

                    # get the data values for both bands
                    # for both MOD10A1 and MYD10A1, bands 0 & 3 are --v
                    cover = img[2 * iband].Read()  # Snow_Cover_Daily_Tile
                    frac = img[2 * iband + 1].Read()  # Fractional_Snow_Cover

                    # check out frac
                    # meanings of special values, see C5 user guide, table 4:
                    # https://modis-snow-ice.gsfc.nasa.gov/uploads/sug_c5.pdf
                    wbad1 = np.where((frac == 200) | (frac == 201)
                                     | (frac == 211) | (frac == 250)
                                     | (frac == 254) | (frac == 255))
                    wsurface1 = np.where((frac == 225) | (frac == 237)
                                         | (frac == 239))
                    wvalid1 = np.where((frac >= 0) & (frac <= 100))

                    nbad1 = len(wbad1[0])
                    nsurface1 = len(wsurface1[0])
                    nvalid1 = len(wvalid1[0])
                    assert nbad1 + nsurface1 + nvalid1 == frac.size, "frac contains invalid values"

                    # check out cover
                    # meanings of special values, see C5 user guide, table 3:
                    # https://modis-snow-ice.gsfc.nasa.gov/uploads/sug_c5.pdf
                    wbad2 = np.where((cover == 0) | (cover == 1)
                                     | (cover == 11) | (cover == 50)
                                     | (cover == 254) | (cover == 255))
                    wsurface2 = np.where((cover == 25) | (cover == 37)
                                         | (cover == 39))
                    wvalid2 = np.where((cover == 100) | (cover == 200))

                    nbad2 = len(wbad2[0])
                    nsurface2 = len(wsurface2[0])
                    nvalid2 = len(wvalid2[0])
                    assert nbad2 + nsurface2 + nvalid2 == cover.size, "cover contains invalid values"

                    # assign output data here
                    coverout = np.zeros_like(cover, dtype=np.uint8)
                    fracout = np.zeros_like(frac, dtype=np.uint8)

                    fracout[wvalid1] = frac[wvalid1]
                    fracout[wsurface1] = 0
                    fracout[wbad1] = 127
                    coverout[wvalid2] = 100
                    coverout[wsurface2] = 0
                    coverout[wbad2] = 127

                    if len(availbands) == 2:
                        if iband == 0:
                            fracout1 = np.copy(fracout)
                            coverout1 = np.copy(coverout)
                        else:
                            # both the current and previous are valid
                            w = np.where((fracout != 127) & (fracout1 != 127))
                            fracout[w] = np.mean(np.array(
                                [fracout[w], fracout1[w]]),
                                                 axis=0).astype('uint8')

                            # the current is not valid but previous is valid
                            w = np.where((fracout == 127) & (fracout1 != 127))
                            fracout[w] = fracout1[w]

                            # both the current and previous are valid
                            w = np.where((coverout != 127)
                                         & (coverout1 != 127))
                            coverout[w] = np.mean(np.array(
                                [coverout[w], coverout1[w]]),
                                                  axis=0).astype('uint8')

                            # the current is not valid but previous is valid
                            w = np.where((coverout == 127)
                                         & (coverout1 != 127))
                            coverout[w] = coverout1[w]

                fracmissingcoverclear = np.sum((fracout == 127)
                                               & (coverout == 0))
                fracmissingcoversnow = np.sum((fracout == 127)
                                              & (coverout == 100))
                fracclearcovermissing = np.sum((fracout == 0)
                                               & (coverout == 127))
                fracclearcoversnow = np.sum((fracout == 0) & (coverout == 100))
                fracsnowcovermissing = np.sum((fracout > 0) & (fracout <= 100)
                                              & (coverout == 127))
                fracsnowcoverclear = np.sum((fracout > 0) & (fracout <= 100)
                                            & (coverout == 0))
                # fracmostlycoverclear = np.sum((fracout > 50) & (fracout <= 100) & (coverout == 0))
                totsnowfrac = int(0.01 * np.sum(fracout[fracout <= 100]))
                totsnowcover = int(0.01 * np.sum(coverout[coverout <= 100]))
                numvalidfrac = np.sum(fracout != 127)
                numvalidcover = np.sum(coverout != 127)

                if totsnowcover == 0 or totsnowfrac == 0:
                    print("no snow or ice: skipping", str(self.date),
                          str(self.id), str(missingassets))

                meta['FRACMISSINGCOVERCLEAR'] = fracmissingcoverclear
                meta['FRACMISSINGCOVERSNOW'] = fracmissingcoversnow
                meta['FRACCLEARCOVERMISSING'] = fracclearcovermissing
                meta['FRACCLEARCOVERSNOW'] = fracclearcoversnow
                meta['FRACSNOWCOVERMISSING'] = fracsnowcovermissing
                meta['FRACSNOWCOVERCLEAR'] = fracsnowcoverclear
                meta['FRACMOSTLYCOVERCLEAR'] = np.sum((fracout > 50)
                                                      & (fracout <= 100)
                                                      & (coverout == 0))
                meta['TOTSNOWFRAC'] = totsnowfrac
                meta['TOTSNOWCOVER'] = totsnowcover
                meta['NUMVALIDFRAC'] = numvalidfrac
                meta['NUMVALIDCOVER'] = numvalidcover

                # create output gippy image
                imgout = gippy.GeoImage(fname, img, gippy.GDT_Byte, 2)
                del img
                imgout.SetNoData(127)
                imgout.SetOffset(0.0)
                imgout.SetGain(1.0)
                imgout.SetBandName('Snow Cover', 1)
                imgout.SetBandName('Fractional Snow Cover', 2)

                imgout[0].Write(coverout)
                imgout[1].Write(fracout)

            ###################################################################
            # TEMPERATURE PRODUCT (DAILY)
            if val[0] == "temp":
                VERSION = "1.1"
                meta['VERSION'] = VERSION

                if not missingassets:
                    availbands = [0, 1, 2, 3]
                    tempsds = [allsds[0], allsds[4], allsds[12], allsds[16]]
                    qcsds = [allsds[1], allsds[5], allsds[13], allsds[17]]
                    hoursds = [allsds[2], allsds[6], allsds[14], allsds[18]]
                elif missingassets[0] == 'MYD11A1':
                    availbands = [0, 1]
                    tempsds = [allsds[0], allsds[4]]
                    qcsds = [allsds[1], allsds[5]]
                    hoursds = [allsds[2], allsds[6]]
                elif missingassets[0] == 'MOD11A1':
                    availbands = [2, 3]
                    tempsds = [allsds[0], allsds[4]]
                    qcsds = [allsds[1], allsds[5]]
                    hoursds = [allsds[2], allsds[6]]
                else:
                    raise IOError("Missing both MOD11A1 and MYD11A1; can't "
                                  "continue")

                tempbands = gippy.GeoImage(tempsds)
                qcbands = gippy.GeoImage(qcsds)
                hourbands = gippy.GeoImage(hoursds)

                imgout = gippy.GeoImage(fname, tempbands, gippy.GDT_UInt16, 5)
                imgout.SetNoData(65535)
                imgout.SetGain(0.02)

                # there are four temperature bands
                for iband, band in enumerate(availbands):
                    # get meta name template info
                    basename = tempbands[iband].Basename()
                    platform = self.Asset._sensors[basename[:3]]['description']

                    if basename.find('daytime'):
                        dayornight = 'day'
                    elif basename.find('nighttime'):
                        dayornight = 'night'
                    else:
                        raise Exception(
                            '%s appears to be an invalid MODIS temperature project'
                            % basename)

                    qc = qcbands[iband].Read()

                    # first two bits are 10 or 11
                    newmaskbad = binmask(qc, 2)
                    # first two bits are 00 or 01
                    newmaskgood = ~binmask(qc, 2)
                    # first two bits are 00
                    newmaskbest = ~binmask(qc, 1) & ~binmask(qc, 2)

                    if iband == 0:
                        bestmask = np.zeros_like(qc, dtype='uint16')

                    bestmask += (math.pow(2, band) *
                                 newmaskbest).astype('uint16')

                    numbad = np.sum(newmaskbad)
                    # fracbad = np.sum(newmaskbad) / float(newmaskbad.size)

                    numgood = np.sum(newmaskgood)
                    # fracgood = np.sum(newmaskgood) / float(newmaskgood.size)
                    assert numgood == qc.size - numbad

                    numbest = np.sum(newmaskbest)
                    # fracbest = np.sum(newmaskbest) / float(newmaskbest.size)

                    metaname = "NUMBAD_%s_%s" % (dayornight, platform)
                    metaname = metaname.upper()
                    # print "metaname", metaname
                    meta[metaname] = str(numbad)

                    metaname = "NUMGOOD_%s_%s" % (dayornight, platform)
                    metaname = metaname.upper()
                    # print "metaname", metaname
                    meta[metaname] = str(numgood)

                    metaname = "NUMBEST_%s_%s" % (dayornight, platform)
                    metaname = metaname.upper()
                    # print "metaname", metaname
                    meta[metaname] = str(numbest)

                    # overpass time
                    hournodatavalue = hourbands[iband].NoDataValue()
                    hour = hourbands[iband].Read()
                    hour = hour[hour != hournodatavalue]
                    hourmean = 0
                    with utils.error_handler(
                            "Couldn't compute hour mean for " + fname,
                            continuable=True):
                        hourmean = hour.mean()

                    metaname = "MEANOVERPASSTIME_%s_%s" % (dayornight,
                                                           platform)
                    metaname = metaname.upper()
                    meta[metaname] = str(hourmean)

                    tempbands[iband].Process(imgout[band])

                imgout[4].SetGain(1.0)
                imgout[4].Write(bestmask)
                imgout.SetBandName('Temperature Daytime Terra', 1)
                imgout.SetBandName('Temperature Nighttime Terra', 2)
                imgout.SetBandName('Temperature Daytime Aqua', 3)
                imgout.SetBandName('Temperature Nighttime Aqua', 4)
                imgout.SetBandName('Temperature Best Quality', 5)
                del tempbands
                del qcbands
                del hourbands

            ###################################################################
            # OBSERVATION TIME PRODUCT (DAILY)
            if val[0] == "obstime":
                VERSION = "1"
                meta['VERSION'] = VERSION

                if not missingassets:
                    availbands = [0, 1, 2, 3]
                    hoursds = [allsds[2], allsds[6], allsds[14], allsds[18]]
                elif missingassets[0] == 'MYD11A1':
                    availbands = [0, 1]
                    hoursds = [allsds[2], allsds[6]]
                elif missingassets[0] == 'MOD11A1':
                    availbands = [2, 3]
                    hoursds = [allsds[2], allsds[6]]
                else:
                    raise IOError("Missing both MOD11A1 and MYD11A1; can't "
                                  "continue")

                hourbands = gippy.GeoImage(hoursds)

                imgout = gippy.GeoImage(fname, hourbands, gippy.GDT_Byte, 4)
                imgout.SetNoData(0)
                imgout.SetGain(0.1)

                # there are four temperature bands
                for iband, band in enumerate(availbands):
                    # get meta name template info
                    basename = hourbands[iband].Basename()
                    platform = self.Asset._sensors[basename[:3]]['description']

                    if basename.find('daytime'):
                        dayornight = 'day'
                    elif basename.find('nighttime'):
                        dayornight = 'night'
                    else:
                        raise Exception(
                            '%s appears to be an invalid MODIS temperature project'
                            % basename)

                    hourbands[iband].Process(imgout[band])

                imgout.SetBandName('Observation Time Daytime Terra', 1)
                imgout.SetBandName('Observation Time Nighttime Terra', 2)
                imgout.SetBandName('Observation Time Daytime Aqua', 3)
                imgout.SetBandName('Observation Time Nighttime Aqua', 4)
                del hourbands

            ###################################################################
            # NDVI (8-day) - Terra only
            if val[0] == "ndvi8":
                VERSION = "1.0"
                meta['VERSION'] = VERSION

                refl = gippy.GeoImage(allsds)
                refl.SetBandName("RED", 1)
                refl.SetBandName("NIR", 2)
                refl.SetNoData(-28762)

                fouts = dict(Indices(refl, {'ndvi': fname}, meta))
                imgout = gippy.GeoImage(fouts['ndvi'])
                del refl

            # TEMPERATURE PRODUCT (8-day) - Terra only

            if val[0] == "temp8td":
                os.symlink(allsds[0], fname)
                imgout = gippy.GeoImage(fname)

            if val[0] == "temp8tn":
                os.symlink(allsds[4], fname)
                imgout = gippy.GeoImage(fname)

            # set metadata
            imgout.SetMeta(self.prep_meta(a_fnames, meta))

            # add product to inventory
            archive_fp = self.archive_temp_path(fname)
            self.AddFile(sensor, key, archive_fp)
            del imgout  # to cover for GDAL's internal problems
            utils.verbose_out(' -> {}: processed in {}'.format(
                os.path.basename(fname),
                datetime.datetime.now() - start),
                              level=1)

        # process some index products (not all, see above)
        requested_ipt = products.groups()['Index'].keys()
        if requested_ipt:
            model_pt = requested_ipt[0]  # all should be similar
            asset, version, _, availassets, allsds = self.asset_check(model_pt)
            if asset is None:
                raise IOError('Found no assets for {}'.format(requested_ipt))
            if version < 6:
                raise IOError('index products require MCD43A4 version 6,'
                              ' but found {}'.format(version))
            img = gippy.GeoImage(allsds[7:])  # don't need the QC bands

            # GIPPY uses expected band names to find data:
            """
            index (ie img[i])
            |  band num
            |   |   wavelength  name
            0   1   620 - 670   RED
            1   2   841 - 876   NIR
            2   3   459 - 479   BLUE
            3   4   545 - 565   GREEN
            4   5   1230 - 1250 CIRRUS (not used by gippy)
            5   6   1628 - 1652 SWIR1
            6   7   2105 - 2155 SWIR2
            """
            # SetBandName goes by band number, not index
            [
                img.SetBandName(name, i)
                for (name, i) in [('RED', 1), ('NIR',
                                               2), ('BLUE',
                                                    3), ('GREEN',
                                                         4), ('SWIR1',
                                                              6), ('SWIR2', 7)]
            ]

            sensor = self._products[model_pt]['sensor']
            prod_spec = {
                pt: self.temp_product_filename(sensor, pt)
                for pt in requested_ipt
            }

            a_fnames = [self.assets[at].filename for at in availassets]
            pt_to_temp_fps = Indices(
                img, prod_spec, self.prep_meta(a_fnames, {'VERSION': '1.0'}))

            for pt, temp_fp in pt_to_temp_fps.items():
                archived_fp = self.archive_temp_path(temp_fp)
                self.AddFile(sensor, pt, archived_fp)
Beispiel #4
0
 start = datetime.now()
 indices = {}
 indices_toa = {}
 for key, val in indices0.items():
     if 'toa' in val:
         indices_toa[key] = val
     else:
         indices[key] = val
 # Run TOA
 if len(indices_toa) > 0:
     fnames = [
         os.path.join(self.path, self.basename + '_' + key)
         for key in indices_toa
     ]
     prodout = Indices(
         reflimg,
         dict(zip([p[0] for p in indices_toa.values()],
                  fnames)), md)
     prodout = dict(zip(indices_toa.keys(), prodout.values()))
     [
         self.AddFile(sensor, key, fname)
         for key, fname in prodout.items()
     ]
 # Run atmospherically corrected
 if len(indices) > 0:
     fnames = [
         os.path.join(self.path, self.basename + '_' + key)
         for key in indices
     ]
     for col in visbands:
         img[col] = ((img[col] - atm6s.results[col][1]) /
                     atm6s.results[col][0]) * (