def findGranuleDir(safedir):
    """
    Search the given .SAFE directory, and find the main XML file at the GRANULE level.
    
    Note that this currently only works for the new-format zip files, with one 
    tile per zipfile. The old ones are being removed from service, so we won't 
    cope with them. 
    
    """
    granuleDirPattern = "{}/GRANULE/L1C_*".format(safedir)
    granuleDirList = glob.glob(granuleDirPattern)
    if len(granuleDirList) == 0:
        raise fmaskerrors.FmaskFileError("Unable to find GRANULE sub-directory {}".format(granuleDirPattern))
    elif len(granuleDirList) > 1:
        dirstring = ','.join(granuleDirList)
        msg = "Found multiple GRANULE sub-directories: {}".format(dirstring)
        raise fmaskerrors.FmaskFileError(msg)
    
    granuleDir = granuleDirList[0]
    return granuleDir
def findGranuleXml(granuleDir):
    """
    Find the granule-level XML file, given the granule dir
    """
    xmlfile = "{}/MTD_TL.xml".format(granuleDir)
    if not os.path.exists(xmlfile):
        # Might be old-format zipfile, so search for *.xml
        xmlfilePattern = "{}/*.xml".format(granuleDir)
        xmlfileList = glob.glob(xmlfilePattern)
        if len(xmlfileList) == 1:
            xmlfile = xmlfileList[0]
        else:
            raise fmaskerrors.FmaskFileError("Unable to find XML file {}".format(xmlfile))
    return xmlfile
Beispiel #3
0
def makeStackAndAngles(cmdargs):
    """
    Make an intermediate stack of all the TOA reflectance bands. Also make an image
    of the angles. Fill in the names of these in the cmdargs object. 
        
    """
    if cmdargs.granuledir is None and cmdargs.safedir is not None:
        cmdargs.granuledir = findGranuleDir(cmdargs.safedir)

    # Find the other commands we need, even under Windoze
    gdalmergeCmd = find_executable("gdal_merge.py")
    if gdalmergeCmd is None:
        msg = "Unable to find gdal_merge.py command. Check installation of GDAL package. "
        raise fmaskerrors.FmaskInstallationError(msg)

    # Make the angles file
    (fd, anglesfile) = tempfile.mkstemp(dir=cmdargs.tempdir,
                                        prefix="angles_tmp_",
                                        suffix=".img")
    os.close(fd)
    xmlfile = findGranuleXml(cmdargs.granuledir)
    if cmdargs.verbose:
        print("Making angles image")
    sentinel2makeAnglesImage.makeAngles(xmlfile, anglesfile)
    cmdargs.anglesfile = anglesfile

    # Make a stack of the reflectance bands. Not that we do an explicit resample to the
    # output pixel size, to avoid picking up the overview layers with the ESA jpg files.
    # According to @vincentschut, these are shifted slightly, and should be avoided.
    bandList = [
        'B01', 'B02', 'B03', 'B04', 'B05', 'B06', 'B07', 'B08', 'B8A', 'B09',
        'B10', 'B11', 'B12'
    ]
    imgDir = "{}/IMG_DATA".format(cmdargs.granuledir)
    resampledBands = []
    for band in bandList:
        (fd, tmpBand) = tempfile.mkstemp(dir=cmdargs.tempdir,
                                         prefix="tmp_{}_".format(band),
                                         suffix=".vrt")
        os.close(fd)
        inBandImgList = glob.glob("{}/*_{}.jp2".format(imgDir, band))
        if len(inBandImgList) != 1:
            raise fmaskerrors.FmaskFileError(
                "Cannot find input band {}".format(band))
        inBandImg = inBandImgList[0]

        # Now make a resampled copy to the desired pixel size, using the right resample method
        resampleMethod = chooseResampleMethod(cmdargs.pixsize, inBandImg)
        subprocess.check_call([
            GDALWARPCMD, '-q', '-tr',
            str(cmdargs.pixsize),
            str(cmdargs.pixsize), '-co', 'TILED=YES', '-of', 'VRT', '-r',
            resampleMethod, inBandImg, tmpBand
        ])

        resampledBands.append(tmpBand)

    # Now make a stack of these
    if cmdargs.verbose:
        print("Making stack of all bands, at {}m pixel size".format(
            cmdargs.pixsize))
    (fd, tmpStack) = tempfile.mkstemp(dir=cmdargs.tempdir,
                                      prefix="tmp_allbands_",
                                      suffix=".img")
    os.close(fd)
    cmdargs.toa = tmpStack
    # ensure we are launching python rather than relying on the OS to do the right thing (ie Windows)
    subprocess.check_call(
        [sys.executable, gdalmergeCmd, '-q', '-of', DEFAULTDRIVERNAME] +
        CMDLINECREATIONOPTIONS + ['-separate', '-o', cmdargs.toa] +
        resampledBands)

    for fn in resampledBands:
        os.remove(fn)

    return resampledBands
Beispiel #4
0
def makeStacksAndAngles(cmdargs):
    """
    Find the name of the MTL file.
    Make an intermediate stacks of all the TOA reflectance and thermal bands.
    Also make an image of the angles, saturation and TOA reflectance. 
    Fill in the names of these in the cmdargs object. 

    """
    # find MTL file
    wldpath = os.path.join(cmdargs.scenedir, '*_MTL.txt')
    mtlList = glob.glob(wldpath)
    if len(mtlList) != 1:
        raise fmaskerrors.FmaskFileError("Cannot find a *_MTL.txt file in specified dir")

    cmdargs.mtl = mtlList[0]

    gdalmergeCmd = find_executable("gdal_merge.py")
    if gdalmergeCmd is None:
        msg = "Unable to find gdal_merge.py command. Check installation of GDAL package. "
        raise fmaskerrors.FmaskInstallationError(msg)

    # we need to find the 'SPACECRAFT_ID' to work out the wildcards to use
    mtlInfo = config.readMTLFile(cmdargs.mtl)
    landsat = mtlInfo['SPACECRAFT_ID'][-1]
    
    if landsat == '4' or landsat == '5':
        refWildcard = 'L*_B[1,2,3,4,5,7].TIF'
        thermalWildcard = 'L*_B6.TIF'
    elif landsat == '7':
        refWildcard = 'L*_B[1,2,3,4,5,7].TIF'
        thermalWildcard = 'L*_B6_VCID_?.TIF'
    elif landsat == '8':
        refWildcard = 'LC*_B[1-7,9].TIF'
        thermalWildcard = 'LC*_B1[0,1].TIF'
    else:
        raise SystemExit('Unsupported Landsat sensor')

    wldpath = os.path.join(cmdargs.scenedir, refWildcard)
    refFiles = sorted(glob.glob(wldpath))
    if len(refFiles) == 0:
        raise fmaskerrors.FmaskFileError("Cannot find expected reflectance files for sensor")

    wldpath = os.path.join(cmdargs.scenedir, thermalWildcard)
    thermalFiles = sorted(glob.glob(wldpath))
    if len(thermalFiles) == 0:
        raise fmaskerrors.FmaskFileError("Cannot find expected thermal files for sensor")

    if cmdargs.verbose:
        print("Making stack of all reflectance bands")
    (fd, tmpRefStack) = tempfile.mkstemp(dir=cmdargs.tempdir, prefix="tmp_allrefbands_",
        suffix=".img")
    os.close(fd)

    # use sys.executable so Windows works
    subprocess.check_call([sys.executable, gdalmergeCmd, '-q', '-of', DEFAULTDRIVERNAME] +
            CMDLINECREATIONOPTIONS + ['-separate', '-o', tmpRefStack] + refFiles)

    # stash so we can delete later
    cmdargs.refstack = tmpRefStack

    if cmdargs.verbose:
        print("Making stack of all thermal bands")
    (fd, tmpThermStack) = tempfile.mkstemp(dir=cmdargs.tempdir, prefix="tmp_allthermalbands_",
        suffix=".img")
    os.close(fd)

    subprocess.check_call([sys.executable, gdalmergeCmd, '-q', '-of', DEFAULTDRIVERNAME] +
        CMDLINECREATIONOPTIONS + ['-separate', '-o', tmpThermStack] + thermalFiles)

    cmdargs.thermal = tmpThermStack

    # now the angles
    if cmdargs.verbose:
        print("Creating angles file")
    (fd, anglesfile) = tempfile.mkstemp(dir=cmdargs.tempdir, prefix="angles_tmp_", 
        suffix=".img")
    os.close(fd)
    usgsLandsatMakeAnglesImage.makeAngles(cmdargs.mtl, tmpRefStack, anglesfile)
    cmdargs.anglesfile = anglesfile

    # saturation
    if cmdargs.verbose:
        print("Creating saturation file")
    (fd, saturationfile) = tempfile.mkstemp(dir=cmdargs.tempdir, prefix="saturation_tmp_", 
        suffix=".img")
    os.close(fd)
    usgsLandsatSaturationMask.makeSaturationMask(cmdargs.mtl, tmpRefStack, saturationfile)
    cmdargs.saturation = saturationfile

    # TOA
    if cmdargs.verbose:
        print("Creating TOA file")
    (fs, toafile) = tempfile.mkstemp(dir=cmdargs.tempdir, prefix="toa_tmp_", 
        suffix=".img")
    os.close(fd)
    landsatTOA.makeTOAReflectance(tmpRefStack, cmdargs.mtl, anglesfile, toafile)
    cmdargs.toa = toafile