예제 #1
0
def get_atl03_classification(atl03filepath, atl08filepath, df, gt):
    # Read ATL03 metrics for class mapping
    atl03_ph_index_beg, atl03_segment_id = \
    readAtl03DataMapping(atl03filepath,gt)

    # Read ATL08 for class mapping
    atl08_classed_pc_indx, atl08_classed_pc_flag, atl08_segment_id = \
    readAtl08DataMapping(atl08filepath, gt)

    # Map ATL08 classifications to ATL03 Photons
    allph_classed = getAtl08Mapping(atl03_ph_index_beg, atl03_segment_id,
                                    atl08_classed_pc_indx,
                                    atl08_classed_pc_flag, atl08_segment_id)

    # Add classifications to ATL03 DF
    df = pd.concat(
        [df, pd.DataFrame(allph_classed, columns=['classification'])], axis=1)

    # Replace nan with -1 (unclassified)
    df.replace({'classification': np.nan}, -1)
    return df
def getAtlMeasuredSwath(atl03FilePath=False,
                        atl08FilePath=False,
                        outFilePath=False,
                        gtNum='gt1r',
                        trimInfo='auto',
                        createAtl03LasFile=False,
                        createAtl03KmlFile=False,
                        createAtl08KmlFile=False,
                        createAtl03CsvFile=False,
                        createAtl08CsvFile=False,
                        logFileID=False):
    # pklHeaderFile = None, LAS_DIR = None):

    # Initialize outputs
    atl03Data = []
    headerData = False
    rotationData = False

    # Initialize ATL08 data
    atl08Data = []
    atl08_lat = []
    atl08_lon = []
    atl08_maxCanopy = []
    atl08_teBestFit = []
    atl08_teMedian = []
    atl08_time = []
    atl08_easting = []
    atl08_northing = []
    atl08_crossTrack = []
    atl08_alongTrack = []
    atl08_classification = []
    atl08_intensity = []

    # pklHeader = False
    # if type(pklHeaderFile) != type(None):
    #     pklHeader = True
    #     if type(LAS_DIR) == type(None):
    #         raise ValueError('LAS_DIR == None, please input LAS_DIR argument')

    # Only execute code if input ATL03 .h5 file and output path declared
    if (atl03FilePath and outFilePath):

        # Start timer
        timeStart = runTime.time()

        # Get beam # and S/W
        beamNum = GtToBeamNum(atl03FilePath, gtNum)
        beamStrength = GtToBeamSW(atl03FilePath, gtNum)

        # Print message
        writeLog(
            '   Ground Track Number: %s (Beam #%s, Beam Strength: %s)\n' %
            (gtNum, beamNum, beamStrength), logFileID)

        # Get ATL03 file path/name
        atl03FilePath = os.path.normpath(os.path.abspath(atl03FilePath))
        atl03FileName = os.path.splitext(os.path.basename(atl03FilePath))[0]

        # Read ATL03 data from h5 file
        writeLog('   Reading ATL03 .h5 file: %s' % atl03FilePath, logFileID)
        lat_all = readAtl03H5(atl03FilePath, '/heights/lat_ph', gtNum)
        lon_all = readAtl03H5(atl03FilePath, '/heights/lon_ph', gtNum)
        z_all = readAtl03H5(atl03FilePath, '/heights/h_ph', gtNum)
        deltaTime_all = readAtl03H5(atl03FilePath, '/heights/delta_time',
                                    gtNum)
        signalConf_all = readAtl03H5(atl03FilePath, '/heights/signal_conf_ph',
                                     gtNum)
        zGeoidal = readAtl03H5(atl03FilePath, '/geophys_corr/geoid', gtNum)
        zGeoidal_deltaTime = readAtl03H5(atl03FilePath,
                                         '/geophys_corr/delta_time', gtNum)
        zGeoidal_all = interp_vals(zGeoidal_deltaTime,
                                   zGeoidal,
                                   deltaTime_all,
                                   removeThresh=True)
        zMsl_all = z_all - zGeoidal_all
        atl03_ph_index_beg, atl03_segment_id = readAtl03DataMapping(
            atl03FilePath, gtNum)

        badVars = []
        if (len(lat_all) == 0):
            badVar = 'Latitude (lat_ph)'
            badVars.append(badVar)
        # endIf

        if (len(lon_all) == 0):
            badVar = 'Longitude (lon_ph)'
            badVars.append(badVar)
        # endIf

        if (len(z_all) == 0):
            badVar = 'Height (h_ph)'
            badVars.append(badVar)
        # endIf

        if (len(deltaTime_all) == 0):
            badVar = 'Delta Time (delta_time)'
            badVars.append(badVar)
        # endIf

        if (len(signalConf_all) == 0):
            badVar = 'Signal Confidence (signal_conf_ph)'
            badVars.append(badVar)
        # endIf

        if (len(badVars) == 0):

            # Get time from delta time
            min_delta_time = np.min(deltaTime_all)
            time_all = deltaTime_all - min_delta_time

            # Get track direction
            if (np.abs(lat_all[-1]) >= np.abs(lat_all[0])):
                trackDirection = 'Ascending'
            else:
                trackDirection = 'Descending'
            # endIf

            writeLog('   Track Direction: %s' % trackDirection, logFileID)

            # Extract metadata from ATL03 file name
            atl03h5Info = getNameParts(atl03FileName)

            # Map ATL08 to ATL03 ground photons
            if (atl08FilePath):

                # Get ATL08 file path/name
                atl08FilePath = os.path.normpath(
                    os.path.abspath(atl08FilePath))
                atl08FileName = os.path.splitext(
                    os.path.basename(atl08FilePath))[0]
                atl08h5Info = getNameParts(atl08FileName)

                # Read ATL08 data from .h5 file
                writeLog('   Reading ATL08 .h5 file: %s' % atl08FilePath,
                         logFileID)
                atl08_lat = readAtl08H5(atl08FilePath,
                                        '/land_segments/latitude', gtNum)
                atl08_lon = readAtl08H5(atl08FilePath,
                                        '/land_segments/longitude', gtNum)
                atl08_maxCanopy = readAtl08H5(
                    atl08FilePath, '/land_segments/canopy/h_max_canopy_abs',
                    gtNum)
                atl08_teBestFit = readAtl08H5(
                    atl08FilePath, '/land_segments/terrain/h_te_best_fit',
                    gtNum)
                atl08_teMedian = readAtl08H5(
                    atl08FilePath, '/land_segments/terrain/h_te_median', gtNum)
                atl08_deltaTime = readAtl08H5(atl08FilePath,
                                              '/land_segments/delta_time',
                                              gtNum)
                atl08_zGeoidal = interp_vals(zGeoidal_deltaTime,
                                             zGeoidal,
                                             atl08_deltaTime,
                                             removeThresh=True)
                atl08_maxCanopyMsl = atl08_maxCanopy - atl08_zGeoidal
                atl08_teBestFitMsl = atl08_teBestFit - atl08_zGeoidal
                atl08_teMedianMsl = atl08_teMedian - atl08_zGeoidal
                atl08_classed_pc_indx, atl08_classed_pc_flag, atl08_segment_id = readAtl08DataMapping(
                    atl08FilePath, gtNum)
                atl08_signalConf = np.zeros(np.size(atl08_lat))
                atl08_classification = np.zeros(np.size(atl08_lat))
                atl08_intensity = np.zeros(np.size(atl08_lat))

                if ((len(atl08_lat) > 0) and (len(atl08_lon) > 0)):

                    # Get time from delta time
                    atl08_time = atl08_deltaTime - min_delta_time

                    # Do ATL08 to ATL03 mapping
                    writeLog('   Mapping ATL08 to ATL03 Ground Photons...',
                             logFileID)
                    try:
                        classification_all = getAtl08Mapping(
                            atl03_ph_index_beg, atl03_segment_id,
                            atl08_classed_pc_indx, atl08_classed_pc_flag,
                            atl08_segment_id)
                    except:
                        writeLog(
                            '   WARNING: Could not map ATL08 to ATL03 Ground Photons.',
                            logFileID)
                        classification_all = atl08_classification
                    # endTry

                    # Get length to trim data by
                    class_length = len(classification_all)
                    lat_length = len(lat_all)
                    data_length = np.min([class_length, lat_length])

                    # Trim ATL03 data down to size of classification array
                    atl03_lat = lat_all[0:data_length]
                    atl03_lon = lon_all[0:data_length]
                    atl03_z = z_all[0:data_length]
                    atl03_zMsl = zMsl_all[0:data_length]
                    atl03_time = time_all[0:data_length]
                    atl03_deltaTime = deltaTime_all[0:data_length]
                    atl03_signalConf = signalConf_all[0:data_length]
                    atl03_classification = classification_all[0:data_length]
                    atl03_intensity = np.zeros(np.size(atl03_lat))
                    dataIsMapped = True

                else:

                    writeLog(
                        '   WARNING: ATL08 file does not contain usable data.',
                        logFileID)

                    atl08FilePath = False

                    # Store data
                    atl03_lat = lat_all
                    atl03_lon = lon_all
                    atl03_z = z_all
                    atl03_zMsl = zMsl_all
                    atl03_time = time_all
                    atl03_deltaTime = deltaTime_all
                    atl03_signalConf = signalConf_all
                    atl03_classification = np.zeros(np.size(atl03_lat))
                    atl03_intensity = np.zeros(np.size(atl03_lat))
                    dataIsMapped = False

                # endIf

            else:

                # Message to screen
                writeLog('   Not Mapping ATL08 to ATL03 Ground Photons',
                         logFileID)

                # Store data
                atl03_lat = lat_all
                atl03_lon = lon_all
                atl03_z = z_all
                atl03_zMsl = zMsl_all
                atl03_time = time_all
                atl03_deltaTime = deltaTime_all
                atl03_signalConf = signalConf_all
                atl03_classification = np.zeros(np.size(atl03_lat))
                atl03_intensity = np.zeros(np.size(atl03_lat))
                dataIsMapped = False

            # endIf

            # Get trim options
            trimParts = trimInfo.split(',')
            trimMode = trimParts[0]
            trimType = 'None'
            if (('manual' in trimMode.lower()) and (len(trimParts) > 1)):
                trimType = trimParts[1]
                trimMin = float(trimParts[2])
                trimMax = float(trimParts[3])
            # endIf

            # If selected to manually trim data, do this first
            if ('manual' in trimMode.lower()):

                # Trim by lat or time
                if ('lonlat' in trimType.lower()):
                    lonMin, lonMax = float(trimParts[2]), float(trimParts[3])
                    latMin, latMax = float(trimParts[4]), float(trimParts[5])
                    writeLog(
                        '   Manual Trim Mode (Min Lon: %s, Max Lon: %s)' %
                        (lonMin, lonMax), logFileID)
                    writeLog(
                        '   Manual Trim Mode (Min Lat: %s, Max Lat: %s)' %
                        (latMin, latMax), logFileID)
                    atl03IndsToKeepLon = (atl03_lon >= lonMin) & (atl03_lon <=
                                                                  lonMax)
                    atl03IndsToKeepLat = (atl03_lat >= latMin) & (atl03_lat <=
                                                                  latMax)
                    atl03IndsToKeep = atl03IndsToKeepLon & atl03IndsToKeepLat

                    if (atl08FilePath):
                        atl08IndsToKeepLon = (atl08_lon >=
                                              lonMin) & (atl08_lon <= lonMax)
                        atl08IndsToKeepLat = (atl08_lat >=
                                              latMin) & (atl08_lat <= latMax)
                        atl08IndsToKeep = atl08IndsToKeepLon & atl08IndsToKeepLat

                elif ('lat' in trimType.lower()):
                    writeLog(
                        '   Manual Trim Mode (Min Lat: %s, Max Lat: %s)' %
                        (trimMin, trimMax), logFileID)
                    atl03IndsToKeep = (atl03_lat >= trimMin) & (atl03_lat <=
                                                                trimMax)

                    if (atl08FilePath):
                        atl08IndsToKeep = (atl08_lat >= trimMin) & (atl08_lat
                                                                    <= trimMax)
                    # endIf

                elif ('lon' in trimType.lower()):
                    writeLog(
                        '   Manual Trim Mode (Min Lon: %s, Max Lon: %s)' %
                        (trimMin, trimMax), logFileID)
                    atl03IndsToKeep = (atl03_lon >= trimMin) & (atl03_lon <=
                                                                trimMax)

                    if (atl08FilePath):
                        atl08IndsToKeep = (atl03_lon >= trimMin) & (atl03_lon
                                                                    <= trimMax)
                    # endIf

                elif ('time' in trimType.lower()):
                    writeLog(
                        '   Manual Trim Mode (Min Time: %s, Max Time: %s)' %
                        (trimMin, trimMax), logFileID)
                    atl03IndsToKeep = (atl03_time >= trimMin) & (atl03_time <=
                                                                 trimMax)

                    if (atl08FilePath):
                        atl08IndsToKeep = (atl08_time >=
                                           trimMin) & (atl08_time <= trimMax)
                    # endIf
                else:
                    writeLog(
                        '   Manual Trim Mode is Missing Args, Not Trimming Data',
                        logFileID)
                    atl03IndsToKeep = np.ones(np.shape(atl03_lat), dtype=bool)

                    if (atl08FilePath):
                        atl08IndsToKeep = np.ones(np.shape(atl08_lat),
                                                  dtype=bool)
                    # endIf
                # endif

                # Trim ATL03 data
                if atl03IndsToKeep.sum() == 0:
                    # no data left given manual constraints
                    return atl03Data, atl08Data, headerData, rotationData
                # endIf

                atl03_lat = atl03_lat[atl03IndsToKeep]
                atl03_lon = atl03_lon[atl03IndsToKeep]
                atl03_z = atl03_z[atl03IndsToKeep]
                atl03_zMsl = atl03_zMsl[atl03IndsToKeep]
                atl03_time = atl03_time[atl03IndsToKeep]
                atl03_deltaTime = atl03_deltaTime[atl03IndsToKeep]
                atl03_signalConf = atl03_signalConf[atl03IndsToKeep]
                atl03_classification = atl03_classification[atl03IndsToKeep]
                atl03_intensity = atl03_intensity[atl03IndsToKeep]

                # Trim ATL08 data
                if (atl08FilePath):
                    atl08_lat = atl08_lat[atl08IndsToKeep]
                    atl08_lon = atl08_lon[atl08IndsToKeep]
                    atl08_maxCanopy = atl08_maxCanopy[atl08IndsToKeep]
                    atl08_teBestFit = atl08_teBestFit[atl08IndsToKeep]
                    atl08_teMedian = atl08_teMedian[atl08IndsToKeep]
                    atl08_maxCanopyMsl = atl08_maxCanopyMsl[atl08IndsToKeep]
                    atl08_teBestFitMsl = atl08_teBestFitMsl[atl08IndsToKeep]
                    atl08_teMedianMsl = atl08_teMedianMsl[atl08IndsToKeep]
                    atl08_time = atl08_time[atl08IndsToKeep]
                    atl08_deltaTime = atl08_deltaTime[atl08IndsToKeep]
                    atl08_signalConf = atl08_signalConf[atl08IndsToKeep]
                    atl08_classification = atl08_classification[
                        atl08IndsToKeep]
                    atl08_intensity = atl08_intensity[atl08IndsToKeep]
                # endIf

            elif ('none' in trimMode.lower()):

                writeLog('   Trim Mode: None', logFileID)

            # endIf

            # Remove ATL08 points above 1e30
            if (atl08FilePath):
                indsBelowThresh = (atl08_maxCanopy <= 1e30) | (
                    atl08_teBestFit <= 1e30) | (atl08_teMedian <= 1e30)
                atl08_lat = atl08_lat[indsBelowThresh]
                atl08_lon = atl08_lon[indsBelowThresh]
                atl08_maxCanopy = atl08_maxCanopy[indsBelowThresh]
                atl08_teBestFit = atl08_teBestFit[indsBelowThresh]
                atl08_teMedian = atl08_teMedian[indsBelowThresh]
                atl08_maxCanopyMsl = atl08_maxCanopyMsl[indsBelowThresh]
                atl08_teBestFitMsl = atl08_teBestFitMsl[indsBelowThresh]
                atl08_teMedianMsl = atl08_teMedianMsl[indsBelowThresh]
                atl08_time = atl08_time[indsBelowThresh]
                atl08_deltaTime = atl08_deltaTime[indsBelowThresh]
                atl08_signalConf = atl08_signalConf[indsBelowThresh]
                atl08_classification = atl08_classification[indsBelowThresh]
                atl08_intensity = atl08_intensity[indsBelowThresh]
            # endIf

            # If selected to auto trim data, then trim if truth region exists
            if ('auto' in trimMode.lower()):

                # Message to user
                writeLog('   Trim Mode: Auto', logFileID)

                # Read kmlBounds.txt file to get min/max extents to auto trim
                kmlBoundsTextFile = 'kmlBounds.txt'
                kmlRegionName = False
                if (os.path.exists(kmlBoundsTextFile)):  # and not pklHeader:

                    # Message to user
                    writeLog('   Finding Reference Region...', logFileID)

                    try:

                        # Read kmlBounds.txt file and get contents
                        kmlInfo = readTruthRegionsTxtFile(kmlBoundsTextFile)

                        # Loop through kmlBounds.txt and find matching TRUTH area
                        maxCounter = len(kmlInfo.regionName)
                        counter = 0
                        while (not kmlRegionName):

                            latInFile = (
                                atl03_lat >= kmlInfo.latMin[counter]) & (
                                    atl03_lat <= kmlInfo.latMax[counter])
                            lonInFile = (
                                atl03_lon >= kmlInfo.lonMin[counter]) & (
                                    atl03_lon <= kmlInfo.lonMax[counter])
                            trackInRegion = any(latInFile & lonInFile)

                            if (trackInRegion):

                                # Get truth region info
                                kmlRegionName = kmlInfo.regionName[counter]
                                kmlLatMin = kmlInfo.latMin[counter]
                                kmlLatMax = kmlInfo.latMax[counter]
                                kmlLonMin = kmlInfo.lonMin[counter]
                                kmlLonMax = kmlInfo.lonMax[counter]

                                # Print truth region
                                writeLog(
                                    '   Reference File Region: %s' %
                                    kmlRegionName, logFileID)

                            # endIf

                            if (counter >= maxCounter):

                                # Send message to user
                                writeLog(
                                    '   No Reference File Region Found in kmlBounds.txt',
                                    logFileID)
                                break

                            # endIf

                            # Increment counter
                            counter += 1

                        # endWhile

                    except:
                        pass
                    # endTry
                # endIf

                if (kmlRegionName):

                    # Trim ATL03 data based on TRUTH region
                    writeLog(
                        '   Auto-Trimming Data Based on Reference Region...',
                        logFileID)
                    atl03IndsInRegion = (atl03_lat >= kmlLatMin) & (
                        atl03_lat <= kmlLatMax) & (atl03_lon >= kmlLonMin) & (
                            atl03_lon <= kmlLonMax)
                    atl03_lat = atl03_lat[atl03IndsInRegion]
                    atl03_lon = atl03_lon[atl03IndsInRegion]
                    atl03_z = atl03_z[atl03IndsInRegion]
                    atl03_zMsl = atl03_zMsl[atl03IndsInRegion]
                    atl03_time = atl03_time[atl03IndsInRegion]
                    atl03_deltaTime = atl03_deltaTime[atl03IndsInRegion]
                    atl03_signalConf = atl03_signalConf[atl03IndsInRegion]
                    atl03_classification = atl03_classification[
                        atl03IndsInRegion]
                    atl03_intensity = atl03_intensity[atl03IndsInRegion]

                    # Trim ATL08 data based on TRUTH region
                    if (atl08FilePath):
                        atl08IndsInRegion = (atl08_lat >= kmlLatMin) & (
                            atl08_lat <= kmlLatMax
                        ) & (atl08_lon >= kmlLonMin) & (atl08_lon <= kmlLonMax)
                        atl08_lat = atl08_lat[atl08IndsInRegion]
                        atl08_lon = atl08_lon[atl08IndsInRegion]
                        atl08_maxCanopy = atl08_maxCanopy[atl08IndsInRegion]
                        atl08_teBestFit = atl08_teBestFit[atl08IndsInRegion]
                        atl08_teMedian = atl08_teMedian[atl08IndsInRegion]
                        atl08_maxCanopyMsl = atl08_maxCanopyMsl[
                            atl08IndsInRegion]
                        atl08_teBestFitMsl = atl08_teBestFitMsl[
                            atl08IndsInRegion]
                        atl08_teMedianMsl = atl08_teMedianMsl[
                            atl08IndsInRegion]
                        atl08_time = atl08_time[atl08IndsInRegion]
                        atl08_deltaTime = atl08_deltaTime[atl08IndsInRegion]
                        atl08_signalConf = atl08_signalConf[atl08IndsInRegion]
                        atl08_classification = atl08_classification[
                            atl08IndsInRegion]
                        atl08_intensity = atl08_intensity[atl08IndsInRegion]
                    #endIf
                # endIf
            # endIf

            # Convert lat/lon coordinates to UTM
            writeLog('   Converting Lat/Lon to UTM...', logFileID)

            # Allow function to determine UTM zone for ATL03
            atl03_easting, atl03_northing, zone, hemi = getLatLon2UTM(
                atl03_lon, atl03_lat)

            # Allow function to determine UTM zone for ATL03
            if (atl08FilePath):
                atl08_easting, atl08_northing, atl08_zone, atl08_hemi = getLatLon2UTM(
                    atl08_lon, atl08_lat)
            # endIf

            # Print UTM zone
            writeLog('   UTM Zone: %s %s' % (zone, hemi), logFileID)

            # Transform MEASURED data to CT/AT plane
            writeLog('   Computing CT/AT Frame Rotation...', logFileID)
            desiredAngle = 90
            atl03_crossTrack, atl03_alongTrack, R_mat, xRotPt, yRotPt, phi = getCoordRotFwd(
                atl03_easting, atl03_northing, [], [], [], desiredAngle)

            if (atl08FilePath):
                atl08_crossTrack, atl08_alongTrack, _, _, _, _ = getCoordRotFwd(
                    atl08_easting, atl08_northing, R_mat, xRotPt, yRotPt, [])
            # endIf

            # Store rotation object
            rotationData = atlRotationStruct(R_mat, xRotPt, yRotPt,
                                             desiredAngle, phi)

            # Reassign class -1 to 0 (NOTE: this may need to change later)
            inds_eq_neg1 = atl03_classification == -1
            atl03_classification[inds_eq_neg1] = 0

            # Store data in class structure
            atl03Data = atl03Struct(atl03_lat, atl03_lon, \
                                    atl03_easting, atl03_northing, \
                                    atl03_crossTrack, atl03_alongTrack, \
                                    atl03_z, \
                                    atl03_zMsl,
                                    atl03_time, \
                                    atl03_deltaTime, \
                                    atl03_signalConf, atl03_classification, atl03_intensity, \
                                    gtNum, beamNum, beamStrength, zone, hemi, \
                                    atl03FilePath, atl03FileName, \
                                    trackDirection, \
                                    atl03h5Info, \
                                    dataIsMapped)

            # Store data in class structure
            if (atl08FilePath):
                atl08Data = atl08Struct(atl08_lat, atl08_lon, \
                                        atl08_easting, atl08_northing, \
                                        atl08_crossTrack, atl08_alongTrack, \
                                        atl08_maxCanopy, atl08_teBestFit, atl08_teMedian, \
                                        atl08_maxCanopyMsl, atl08_teBestFitMsl, atl08_teMedianMsl, \
                                        atl08_time, \
                                        atl08_deltaTime, \
                                        atl08_signalConf, atl08_classification, atl08_intensity, \
                                        gtNum, atl08_zone, atl08_hemi, \
                                        atl08FilePath, atl08FileName, \
                                        trackDirection, \
                                        atl08h5Info, \
                                        dataIsMapped)
            # endIf

            # Create output ATL03 .las file
            if (createAtl03LasFile):

                writeLog('   Writing ATL03 .las file...', logFileID)
                outName = atl03Data.atl03FileName + '_' + atl03Data.gtNum + '.las'
                outPath = os.path.normpath(outFilePath + '/' + outName)

                # If output directory does not exist, create it
                if (not os.path.exists(os.path.normpath(outFilePath))):
                    os.mkdir(os.path.normpath(outFilePath))
                # EndIf

                # Get projection
                if (atl03Data.zone == '3413' or atl03Data.zone == '3976'):

                    # NSIDC Polar Stereographic North/South cases (3413 = Arctic, 3976 = Antarctic)
                    lasProjection = atl03Data.hemi

                    # Write .las file
                    writeLas(np.ravel(atl03Data.easting),
                             np.ravel(atl03Data.northing),
                             np.ravel(atl03Data.z), lasProjection, outPath,
                             np.ravel(atl03Data.classification),
                             np.ravel(atl03Data.intensity),
                             np.ravel(atl03Data.signalConf))

                else:

                    # Write .las file for UTM projection case
                    writeLas(np.ravel(atl03Data.easting),
                             np.ravel(atl03Data.northing),
                             np.ravel(atl03Data.z), 'utm', outPath,
                             np.ravel(atl03Data.classification),
                             np.ravel(atl03Data.intensity),
                             np.ravel(atl03Data.signalConf), atl03Data.hemi,
                             atl03Data.zone)

                # endIf

            # endIf

            # Create output ATL03 .kml file
            if (createAtl03KmlFile):

                writeLog('   Writing ATL03 .kml file...', logFileID)
                outName = atl03Data.atl03FileName + '_' + atl03Data.gtNum + '.kml'
                outPath = os.path.normpath(outFilePath + '/' + outName)

                # If output directory does not exist, create it
                if (not os.path.exists(os.path.normpath(outFilePath))):
                    os.mkdir(os.path.normpath(outFilePath))
                # EndIf

                # Get array of input time values
                timeStep = 1  # seconds
                timeVals = np.arange(np.min(atl03Data.time),
                                     np.max(atl03Data.time) + 1, timeStep)

                # Get closest time values from IceSat MEASURED data
                timeIn, indsToUse = getClosest(atl03Data.time, timeVals)

                # Reduce lat/lon values to user-specified time scale
                lonsIn = atl03Data.lon[indsToUse]
                latsIn = atl03Data.lat[indsToUse]

                # Write .kml file
                writeKml(latsIn, lonsIn, timeIn, outPath)

            # endIf

            # Create output ATL08 .kml file
            if (createAtl08KmlFile):

                if (atl08FilePath):

                    writeLog('   Writing ATL08 .kml file...', logFileID)
                    outName = atl08Data.atl08FileName + '_' + atl08Data.gtNum + '.kml'
                    outPath = os.path.normpath(outFilePath + '/' + outName)

                    # If output directory does not exist, create it
                    if (not os.path.exists(os.path.normpath(outFilePath))):
                        os.mkdir(os.path.normpath(outFilePath))
                    # EndIf

                    # Get array of input time values
                    timeStep = 1  # seconds
                    timeVals = np.arange(np.min(atl08Data.time),
                                         np.max(atl08Data.time) + 1, timeStep)

                    # Get closest time values from IceSat MEASURED data
                    timeIn, indsToUse = getClosest(atl08Data.time, timeVals)

                    # Reduce lat/lon values to user-specified time scale
                    lonsIn = atl08Data.lon[indsToUse]
                    latsIn = atl08Data.lat[indsToUse]

                    # Write .kml file
                    writeKml(latsIn, lonsIn, timeIn, outPath)

                # endIf

            # endIf

            # Create output ATL03 .csv file
            if (createAtl03CsvFile):

                writeLog('   Writing ATL03 .csv file...', logFileID)
                outName = atl03Data.atl03FileName + '_' + atl03Data.gtNum + '.csv'
                outPath = os.path.normpath(outFilePath + '/' + outName)

                # If output directory does not exist, create it
                if (not os.path.exists(os.path.normpath(outFilePath))):
                    os.mkdir(os.path.normpath(outFilePath))
                # EndIf

                # Write .csv file
                if (atl03Data.zone == '3413' or atl03Data.zone == '3976'):

                    namelist = ['Time (sec)', 'Delta Time (sec)', \
                                'Latitude (deg)', 'Longitude (deg)', \
                                'Polar Stereo X (m)', 'Polar Stereo Y (m)', \
                                'Cross-Track (m)', 'Along-Track (m)', \
                                'Height (m HAE)', 'Height (m MSL)', \
                                'Classification', 'Signal Confidence']
                else:

                    namelist = ['Time (sec)', 'Delta Time (sec)', \
                                'Latitude (deg)', 'Longitude (deg)', \
                                'Easting (m)', 'Northing (m)', \
                                'Cross-Track (m)', 'Along-Track (m)', \
                                'Height (m HAE)', 'Height (m MSL)', \
                                'Classification', 'Signal Confidence']
                # endIf

                datalist = [atl03Data.time, atl03Data.deltaTime, \
                            atl03Data.lat, atl03Data.lon, \
                            atl03Data.easting, atl03Data.northing, \
                            atl03Data.crossTrack, atl03Data.alongTrack,\
                            atl03Data.z, atl03Data.zMsl, \
                            atl03Data.classification, atl03Data.signalConf]

                writeArrayToCSV(outPath, namelist, datalist)

            # endIf

            # Create output ATL08 .csv file
            if (createAtl08CsvFile):

                if (atl08FilePath):

                    writeLog('   Writing ATL08 .csv file...', logFileID)
                    outName = atl08Data.atl08FileName + '_' + atl08Data.gtNum + '.csv'
                    outPath = os.path.normpath(outFilePath + '/' + outName)

                    # If output directory does not exist, create it
                    if (not os.path.exists(os.path.normpath(outFilePath))):
                        os.mkdir(os.path.normpath(outFilePath))
                    # EndIf

                    # Write .csv file
                    if (atl03Data.zone == '3413' or atl03Data.zone == '3976'):

                        namelist = ['Time (sec)', 'Delta Time (sec)', \
                                    'Latitude (deg)', 'Longitude (deg)', \
                                    'Polar Stereo X (m)', 'Polar Stereo Y (m)', \
                                    'Cross-Track (m)', 'Along-Track (m)', \
                                    'Max Canopy (m)', \
                                    'Terrain Best Fit (m)', 'Terrain Median (m)']
                    else:

                        namelist = ['Time (sec)', 'Delta Time (sec)', \
                                    'Latitude (deg)', 'Longitude (deg)', \
                                    'Easting (m)', 'Northing (m)', \
                                    'Cross-Track (m)', 'Along-Track (m)', \
                                    'Max Canopy (m)', \
                                    'Terrain Best Fit (m)', 'Terrain Median (m)']
                    # endIf

                    datalist = [atl08Data.time, atl08Data.deltaTime, \
                                atl08Data.lat, atl08Data.lon, \
                                atl08Data.easting, atl08Data.northing, \
                                atl08Data.crossTrack, atl08Data.alongTrack,\
                                atl08Data.maxCanopy, \
                                atl08Data.teBestFit, atl08Data.teMedian]

                    writeArrayToCSV(outPath, namelist, datalist)

                # endIf

            # endIf

            # End timer
            timeEnd = runTime.time()
            timeElapsedTotal = timeEnd - timeStart
            timeElapsedMin = np.floor(timeElapsedTotal / 60)
            timeElapsedSec = timeElapsedTotal % 60

            # Print completion message
            writeLog('', logFileID)
            writeLog(
                '   Module Completed in %d min %d sec.' %
                (timeElapsedMin, timeElapsedSec), logFileID)
            writeLog('\n', logFileID)

        else:

            writeLog('\n', logFileID)
            writeLog('   *** Could not process data.', logFileID)
            writeLog('   *** ATL03 .h5 file missing these fields:', logFileID)
            for i in range(0, len(badVars)):
                writeLog('          %s) %s' % (i + 1, badVars[i]), logFileID)
            writeLog('\n', logFileID)

        # endIf

    else:

        # Message to user
        writeLog('Input correct ATL03 input .h5 file and/or output path.',
                 logFileID)

    # endIf

    # Return object
    return atl03Data, atl08Data, rotationData
예제 #3
0
def getAtlMeasuredSwath(atl03FilePath=False,
                        atl08FilePath=False,
                        outFilePath=False,
                        gtNum='gt1r',
                        trimInfo='auto',
                        createLasFile=False,
                        createKmlFile=False,
                        createCsvFile=False):

    # Initialize outputs
    atlMeasuredData = False
    headerData = False
    coordType = False
    rotationData = False

    # Only execute code if input ATL03 .h5 file and output path declared
    if (atl03FilePath and outFilePath):

        # Start timer
        timeStart = runTime.time()

        # Print message
        print('   Ground Track Number: %s' % gtNum)

        # Get ATL03 file path/name
        atl03FilePath = os.path.normpath(os.path.abspath(atl03FilePath))
        atl03FileName = os.path.splitext(os.path.basename(atl03FilePath))[0]

        # Read ATL03 data from h5 file
        print('   Reading ATL03 .h5 file: %s' % atl03FilePath)
        lat_all = readAtl03H5(atl03FilePath, 'lat_ph', gtNum)
        lon_all = readAtl03H5(atl03FilePath, 'lon_ph', gtNum)
        z_all = readAtl03H5(atl03FilePath, 'h_ph', gtNum)
        deltaTime_all = readAtl03H5(atl03FilePath, 'delta_time', gtNum)
        signalConf_all = readAtl03H5(atl03FilePath, 'signal_conf_ph', gtNum)
        atl03_ph_index_beg, atl03_segment_id = readAtl03DataMapping(
            atl03FilePath, gtNum)

        # Get time from delta time
        time_all = deltaTime_all - np.min(deltaTime_all)

        # Get track direction
        if (lat_all[-1] > lat_all[0]):
            trackDirection = 'Ascending'
        else:
            trackDirection = 'Descending'
        # endIf

        # Extract metadata from ATL03 file name
        atl03h5Info = getNameParts(atl03FileName)

        # Map ATL08 to ATL03 ground photons
        if (atl08FilePath):

            # Get ATL08 file path/name
            atl08FilePath = os.path.normpath(os.path.abspath(atl08FilePath))

            # Message to screen
            print('   Reading ATL08 .h5 file: %s' % atl08FilePath)
            atl08_classed_pc_indx, atl08_classed_pc_flag, atl08_segment_id = readAtl08DataMapping(
                atl08FilePath, gtNum)

            print('   Mapping ATL08 to ATL03 Ground Photons...')
            classification = getAtl08Mapping(atl03_ph_index_beg,
                                             atl03_segment_id,
                                             atl08_classed_pc_indx,
                                             atl08_classed_pc_flag,
                                             atl08_segment_id)

            # Get length to trim data by
            class_length = len(classification)
            lat_length = len(lat_all)
            data_length = np.min([class_length, lat_length])

            # Trim ATL03 data down to size of classification array
            lat = lat_all[0:data_length]
            lon = lon_all[0:data_length]
            z = z_all[0:data_length]
            time = time_all[0:data_length]
            signalConf = signalConf_all[0:data_length]
            classification = classification[0:data_length]
            dataIsMapped = True

        else:

            # Message to screen
            print('   Not Mapping ATL08 to ATL03 Ground Photons')

            # Store data
            lat = lat_all
            lon = lon_all
            z = z_all
            time = time_all
            signalConf = signalConf_all
            classification = np.zeros(np.size(lat_all))
            dataIsMapped = False

        # endIf

        # Get trim options
        trimParts = trimInfo.split(',')
        trimMode = trimParts[0]
        trimType = 'None'
        if (('manual' in trimMode.lower()) and (len(trimParts) > 1)):
            trimType = trimParts[1]
            trimMin = float(trimParts[2])
            trimMax = float(trimParts[3])
        # endIf

        # If selected to manually trim data, do this first
        if ('manual' in trimMode.lower()):

            # Trim by lat or time
            if ('lat' in trimType.lower()):
                print('   Manual Trim Mode (Min Lat: %s, Max Lat: %s)' %
                      (trimMin, trimMax))
                indsToKeep = (lat >= trimMin) & (lat <= trimMax)
            elif ('time' in trimType.lower()):
                print('   Manual Trim Mode (Min Time: %s, Max Time: %s)' %
                      (trimMin, trimMax))
                indsToKeep = (time >= trimMin) & (time <= trimMax)
            else:
                print('   Manual Trim Mode is Missing Args, Not Trimming Data')
                indsToKeep = np.ones(np.shape(lat), dtype=bool)
            # endif

            # Trim data
            lat = lat[indsToKeep]
            lon = lon[indsToKeep]
            z = z[indsToKeep]
            time = time[indsToKeep]
            signalConf = signalConf[indsToKeep]
            classification = classification[indsToKeep]

        # EndIf

        # Determine if ATL03 track goes over a lidar truth region
        kmlBoundsTextFile = 'kmlBounds.txt'
        kmlRegionName = False
        headerFilePath = False
        truthFilePath = False
        if (os.path.exists(kmlBoundsTextFile)):

            # Message to user
            print('   Finding Truth Region...')

            try:

                # Read kmlBounds.txt file and get contents
                kmlInfo = readTruthRegionsTxtFile(kmlBoundsTextFile)

                # Loop through kmlBounds.txt and find matching TRUTH area
                maxCounter = len(kmlInfo.regionName)
                counter = 0
                while (not kmlRegionName):
                    latInFile = (lat >= kmlInfo.latMin[counter]) & (
                        lat <= kmlInfo.latMax[counter])
                    lonInFile = (lon >= kmlInfo.lonMin[counter]) & (
                        lon <= kmlInfo.lonMax[counter])
                    trackInRegion = any(latInFile & lonInFile)
                    if (trackInRegion):

                        # Get truth region info
                        kmlRegionName = kmlInfo.regionName[counter]
                        headerFilePath = os.path.normpath(
                            kmlInfo.headerFilePath[counter])
                        truthFilePath = os.path.normpath(
                            kmlInfo.truthFilePath[counter])
                        kmlLatMin = kmlInfo.latMin[counter]
                        kmlLatMax = kmlInfo.latMax[counter]
                        kmlLonMin = kmlInfo.lonMin[counter]
                        kmlLonMax = kmlInfo.lonMax[counter]

                        # Print truth region
                        print('   Truth File Region: %s' % kmlRegionName)

                        # Read truth header .mat file
                        headerData = readHeaderMatFile(headerFilePath)
                        coordType = headerData.coordType

                    # endIf

                    # Increment counter
                    counter += 1

                    if (counter >= maxCounter):

                        # Send message to user
                        print('   No Truth File Region Found in kmlBounds.txt')
                        break

                    # endIf
                # endWhile

            except:

                # Could not read kmlBounds.txt file
                print(
                    '   Could not read truth header .mat file. Auto-assigning UTM zone.'
                )

        # endIf

        # If selected to auto trim data, then trim if truth region exists
        if ('auto' in trimMode.lower()):

            if (kmlRegionName):

                # Trim data based on TRUTH region
                print(
                    '   Auto Trim Mode (Trimming Data Based on Truth Region)...'
                )
                indsInRegion = (lat >= kmlLatMin) & (lat <= kmlLatMax) & (
                    lon >= kmlLonMin) & (lon <= kmlLonMax)
                lat = lat[indsInRegion]
                lon = lon[indsInRegion]
                z = z[indsInRegion]
                time = time[indsInRegion]
                signalConf = signalConf[indsInRegion]
                classification = classification[indsInRegion]

            # endIf
        # endIf

        # Convert lat/lon coordinates to UTM
        print('   Converting Lat/Lon to UTM...')
        if (kmlRegionName and coordType == 'UTM'):

            # Force UTM zone to match region header file
            zoneToUse = headerData.zone
            hemiToUse = headerData.hemi
            easting, northing, zone, hemi = getLatLon2UTM(
                lon, lat, zoneToUse, hemiToUse)

        else:

            # Allow function to determine UTM zone
            easting, northing, zone, hemi = getLatLon2UTM(lon, lat)

        # endIf

        # Print UTM zone
        print('   UTM Zone: %s' % zone)

        # Transform MEASURED data to CT/AT plane
        print('   Computing CT/AT Frame Rotation...')
        desiredAngle = 90
        crossTrack, alongTrack, R_mat, xRotPt, yRotPt, phi = getCoordRotFwd(
            easting, northing, [], [], [], desiredAngle)

        # Store rotation object
        rotationData = atlRotationStruct(R_mat, xRotPt, yRotPt, desiredAngle,
                                         phi)

        # Store data in class structure
        atlMeasuredData = atlMeasuredStruct(lat, lon, \
                                            easting, northing, \
                                            crossTrack, alongTrack, \
                                            z, time, \
                                            signalConf, classification, \
                                            gtNum, zone, hemi, \
                                            kmlRegionName, headerFilePath, truthFilePath, \
                                            atl03FilePath, atl03FileName, \
                                            atl08FilePath, atl03FileName, \
                                            trackDirection, \
                                            atl03h5Info, \
                                            dataIsMapped)

        # Create output .las file
        if (createLasFile):

            print('   Writing measured .las file...')
            outName = atlMeasuredData.atl03FileName + '_' + atlMeasuredData.gtNum + '_MEASURED.las'
            outPath = os.path.normpath(outFilePath + '/' + outName)

            # If output directory does not exist, create it
            if (not os.path.exists(os.path.normpath(outFilePath))):
                os.mkdir(os.path.normpath(outFilePath))
            # EndIf

            # Write .las file
            writeLas(np.ravel(atlMeasuredData.easting),
                     np.ravel(atlMeasuredData.northing),
                     np.ravel(atlMeasuredData.z), 'utm', outPath,
                     np.ravel(atlMeasuredData.classification),
                     np.ravel(atlMeasuredData.intensity), atlMeasuredData.hemi,
                     atlMeasuredData.zone)

        # endIf

        # Create output .kml file
        if (createKmlFile):

            print('   Writing measured .kml file...')
            outName = atlMeasuredData.atl03FileName + '_' + atlMeasuredData.gtNum + '_MEASURED.kml'
            outPath = os.path.normpath(outFilePath + '/' + outName)

            # If output directory does not exist, create it
            if (not os.path.exists(os.path.normpath(outFilePath))):
                os.mkdir(os.path.normpath(outFilePath))
            # EndIf

            # Get array of input time values
            timeStep = 1  # seconds
            timeVals = np.arange(np.min(atlMeasuredData.time),
                                 np.max(atlMeasuredData.time) + 1, timeStep)

            # Get closest time values from IceSat MEASURED data
            timeIn, indsToUse = getClosest(atlMeasuredData.time, timeVals)

            # Reduce lat/lon values to user-specified time scale
            lonsIn = atlMeasuredData.lon[indsToUse]
            latsIn = atlMeasuredData.lat[indsToUse]

            # Write .kml file
            writeKml(latsIn, lonsIn, timeIn, outPath)

        # endIf

        # Create output .csv file
        if (createCsvFile):

            print('   Writing measured .csv file...')
            outName = atlMeasuredData.atl03FileName + '_' + atlMeasuredData.gtNum + '_MEASURED.csv'
            outPath = os.path.normpath(outFilePath + '/' + outName)

            # If output directory does not exist, create it
            if (not os.path.exists(os.path.normpath(outFilePath))):
                os.mkdir(os.path.normpath(outFilePath))
            # EndIf

            # Write .csv file
            namelist = ['Time (sec)', 'Latitude (deg)', 'Longitude (deg)', \
                        'Easting (m)', 'Northing (m)', \
                        'Cross-Track (m)', 'Along-Track (m)', \
                        'Height (m)', \
                        'Classification', 'Signal Confidence']
            datalist = [atlMeasuredData.time, atlMeasuredData.lat, atlMeasuredData.lon, \
                        atlMeasuredData.easting, atlMeasuredData.northing, \
                        atlMeasuredData.crossTrack, atlMeasuredData.alongTrack,\
                        atlMeasuredData.z, \
                        atlMeasuredData.classification, atlMeasuredData.signalConf]
            writeArrayToCSV(outPath, namelist, datalist)

        # endIf

        # End timer
        timeEnd = runTime.time()
        timeElapsedTotal = timeEnd - timeStart
        timeElapsedMin = np.floor(timeElapsedTotal / 60)
        timeElapsedSec = timeElapsedTotal % 60

        # Print completion message
        print('   Module Completed in %d min %d sec.' %
              (timeElapsedMin, timeElapsedSec))
        print('\n')

    else:

        # Message to user
        print('Input correct ATL03 input .h5 file and/or output path.')

    # endIf

    # Return object
    return atlMeasuredData, headerData, rotationData