Пример #1
0
class UAVSAR_HDF5_SLC(Sensor):
    """
    A class representing a Level1Product meta data.
    Level1Product(hdf5=h5filename) will parse the hdf5
    file and produce an object with attributes for metadata.
    """
    parameter_list = (HDF5, FREQUENCY, POLARIZATION) + Sensor.parameter_list

    logging_name = 'isce.Sensor.UAVSAR_HDF5_SLC'
    family = 'uavsar_hdf5_slc'

    def __init__(self,
                 family='',
                 name=''):  # , frequency='frequencyA', polarization='HH'):
        super(UAVSAR_HDF5_SLC,
              self).__init__(family if family else self.__class__.family,
                             name=name)
        self.frame = Frame()
        self.frame.configure()
        # Some extra processing parameters unique to UAVSAR HDF5 SLC (currently)
        self.dopplerRangeTime = []
        self.dopplerAzimuthTime = []
        self.azimuthRefTime = None
        self.rangeRefTime = None
        self.rangeFirstTime = None
        self.rangeLastTime = None
        #self.frequency = frequency
        #self.polarization = polarization

        self.lookMap = {'right': -1, 'left': 1}
        return

    def __getstate__(self):
        d = dict(self.__dict__)
        del d['logger']
        return d

    def __setstate__(self, d):
        self.__dict__.update(d)
        self.logger = logging.getLogger('isce.Sensor.UAVSAR_HDF5_SLC')
        return

    def getFrame(self):
        return self.frame

    def parse(self):
        try:
            fp = h5py.File(self.hdf5, 'r')
        except Exception as strerr:
            self.logger.error("IOError: %s" % strerr)
            return None

        self.populateMetadata(fp)
        fp.close()

    def populateMetadata(self, file):
        """
            Populate our Metadata objects
        """

        self._populatePlatform(file)
        self._populateInstrument(file)
        self._populateFrame(file)
        self._populateOrbit(file)

    def _populatePlatform(self, file):
        platform = self.frame.getInstrument().getPlatform()

        platform.setMission(
            file['/science/LSAR/identification'].get('missionId')[(
            )].decode('utf-8'))
        platform.setPointingDirection(
            self.lookMap[file['/science/LSAR/identification'].get(
                'lookDirection')[()].decode('utf-8')])
        platform.setPlanet(Planet(pname="Earth"))

        # We are not using this value anywhere. Let's fix it for now.
        platform.setAntennaLength(12.0)

    def _populateInstrument(self, file):
        instrument = self.frame.getInstrument()

        rangePixelSize = file['/science/LSAR/SLC/swaths/' + self.frequency +
                              '/slantRangeSpacing'][()]
        wvl = SPEED_OF_LIGHT / file['/science/LSAR/SLC/swaths/' +
                                    self.frequency +
                                    '/processedCenterFrequency'][()]
        instrument.setRadarWavelength(wvl)
        instrument.setPulseRepetitionFrequency(
            1.0 / file['/science/LSAR/SLC/swaths/zeroDopplerTimeSpacing'][()])
        rangePixelSize = file['/science/LSAR/SLC/swaths/' + self.frequency +
                              '/slantRangeSpacing'][()]
        instrument.setRangePixelSize(rangePixelSize)

        # Chrip slope and length only are used in the split spectrum workflow to compute the bandwidth.
        # Therefore fixing it to 1.0 won't breack anything
        Chirp_slope = 1.0
        rangeBandwidth = file['/science/LSAR/SLC/swaths/' + self.frequency +
                              '/processedRangeBandwidth'][()]
        Chirp_length = rangeBandwidth / Chirp_slope
        instrument.setPulseLength(Chirp_length)
        instrument.setChirpSlope(Chirp_slope)
        rangeSamplingFrequency = SPEED_OF_LIGHT / 2. / rangePixelSize
        instrument.setRangeSamplingRate(rangeSamplingFrequency)

        incangle = 0.0
        instrument.setIncidenceAngle(incangle)

    def _populateFrame(self, file):

        slantRange = file['/science/LSAR/SLC/swaths/' + self.frequency +
                          '/slantRange'][0]
        self.frame.setStartingRange(slantRange)

        referenceUTC = file['/science/LSAR/SLC/swaths/zeroDopplerTime'].attrs[
            'units'].decode('utf-8')
        referenceUTC = referenceUTC.replace('seconds since ', '')
        referenceUTC = datetime.datetime.strptime(referenceUTC,
                                                  '%Y-%m-%d %H:%M:%S')

        relStart = file['/science/LSAR/SLC/swaths/zeroDopplerTime'][0]
        relEnd = file['/science/LSAR/SLC/swaths/zeroDopplerTime'][-1]
        relMid = 0.5 * (relStart + relEnd)

        sensingStart = self._combineDateTime(referenceUTC, relStart)
        sensingStop = self._combineDateTime(referenceUTC, relEnd)
        sensingMid = self._combineDateTime(referenceUTC, relMid)

        self.frame.setPassDirection(
            file['/science/LSAR/identification'].get('orbitPassDirection')[(
            )].decode('utf-8'))
        self.frame.setOrbitNumber(
            file['/science/LSAR/identification'].get('trackNumber')[()])
        self.frame.setProcessingFacility('JPL')
        self.frame.setProcessingSoftwareVersion(
            file['/science/LSAR/SLC/metadata/processingInformation/algorithms']
            .get('ISCEVersion')[()].decode('utf-8'))
        self.frame.setPolarization(self.polarization)
        self.frame.setNumberOfLines(
            file['/science/LSAR/SLC/swaths/' + self.frequency + '/' +
                 self.polarization].shape[0])
        self.frame.setNumberOfSamples(
            file['/science/LSAR/SLC/swaths/' + self.frequency + '/' +
                 self.polarization].shape[1])
        self.frame.setSensingStart(sensingStart)
        self.frame.setSensingMid(sensingMid)
        self.frame.setSensingStop(sensingStop)

        rangePixelSize = self.frame.instrument.rangePixelSize
        farRange = slantRange + (self.frame.getNumberOfSamples() -
                                 1) * rangePixelSize
        self.frame.setFarRange(farRange)

    def _populateOrbit(self, file):
        orbit = self.frame.getOrbit()

        orbit.setReferenceFrame('ECR')
        orbit.setOrbitSource('Header')

        referenceUTC = file['/science/LSAR/SLC/swaths/zeroDopplerTime'].attrs[
            'units'].decode('utf-8')
        referenceUTC = referenceUTC.replace('seconds since ', '')
        t0 = datetime.datetime.strptime(referenceUTC, '%Y-%m-%d %H:%M:%S')
        t = file['/science/LSAR/SLC/metadata/orbit/time']
        position = file['/science/LSAR/SLC/metadata/orbit/position']
        velocity = file['/science/LSAR/SLC/metadata/orbit/velocity']

        for i in range(len(position)):
            vec = StateVector()
            dt = t0 + datetime.timedelta(seconds=t[i])
            vec.setTime(dt)
            vec.setPosition([position[i, 0], position[i, 1], position[i, 2]])
            vec.setVelocity([velocity[i, 0], velocity[i, 1], velocity[i, 2]])
            orbit.addStateVector(vec)

    def extractImage(self):

        import numpy as np
        import h5py

        self.parse()

        fid = h5py.File(self.hdf5, 'r')
        ds = fid['/science/LSAR/SLC/swaths/' + self.frequency + '/' +
                 self.polarization]
        nLines = ds.shape[0]

        with open(self.output, 'wb') as fout:
            for ii in range(nLines):
                ds[ii, :].astype(np.complex64).tofile(fout)

        fid.close()

        slcImage = isceobj.createSlcImage()
        slcImage.setFilename(self.output)
        slcImage.setXmin(0)
        slcImage.setXmax(self.frame.getNumberOfSamples())
        slcImage.setWidth(self.frame.getNumberOfSamples())
        slcImage.setAccessMode('r')
        slcImage.renderHdr()
        self.frame.setImage(slcImage)

    def _parseNanoSecondTimeStamp(self, timestamp):
        """
            Parse a date-time string with nanosecond precision and return a datetime object
        """
        dateTime, nanoSeconds = timestamp.decode('utf-8').split('.')
        microsec = float(nanoSeconds) * 1e-3
        dt = datetime.datetime.strptime(dateTime, '%Y-%m-%d %H:%M:%S')
        dt = dt + datetime.timedelta(microseconds=microsec)
        return dt

    def _combineDateTime(self, dobj, secsstr):
        '''Takes the date from dobj and time from secs to spit out a date time object.
        '''
        sec = float(secsstr)
        dt = datetime.timedelta(seconds=sec)
        return dobj + dt

    def extractDoppler(self):
        """
        Return the doppler centroid as defined in the HDF5 file.
        """

        import h5py
        from scipy.interpolate import UnivariateSpline
        import numpy as np

        h5 = h5py.File(self.hdf5, 'r')

        # extract the 2D LUT of Doppler and choose only one range line as the data duplicates for other range lines
        dop = h5['/science/LSAR/SLC/metadata/processingInformation/parameters/'
                 + self.frequency + '/dopplerCentroid'][0, :]
        rng = h5[
            '/science/LSAR/SLC/metadata/processingInformation/parameters/slantRange']

        # extract the slant range of the image grid
        imgRng = h5['/science/LSAR/SLC/swaths/' + self.frequency +
                    '/slantRange']

        # use only part of the slant range that closely covers image ranges and ignore the rest
        ind0 = np.argmin(np.abs(rng - imgRng[0])) - 1
        ind0 = np.max([0, ind0])
        ind1 = np.argmin(np.abs(rng - imgRng[-1])) + 1
        ind1 = np.min([ind1, rng.shape[0]])

        dop = dop[ind0:ind1]
        rng = rng[ind0:ind1]

        f = UnivariateSpline(rng, dop)
        imgDop = f(imgRng)

        dr = imgRng[1] - imgRng[0]
        pix = (imgRng - imgRng[0]) / dr
        fit = np.polyfit(pix, imgDop, 41)

        self.frame._dopplerVsPixel = list(fit[::-1])

        ####insarApp style (doesn't get used for stripmapApp). A fixed Doppler at the middle of the scene
        quadratic = {}
        quadratic['a'] = imgDop[int(
            imgDop.shape[0] /
            2)] / self.frame.getInstrument().getPulseRepetitionFrequency()
        quadratic['b'] = 0.
        quadratic['c'] = 0.

        return quadratic
Пример #2
0
class Track(object):
    """A class to represent a collection of temporally continuous radar frame
    objects"""

    logging_name = "isce.Scene.Track"

    @logged
    def __init__(self):
        # These are attributes representing the starting time and stopping
        # time of the track
        # As well as the early and late times (range times) of the track
        self._startTime = datetime.datetime(year=datetime.MAXYEAR,
                                            month=1,
                                            day=1)
        self._stopTime = datetime.datetime(year=datetime.MINYEAR,
                                           month=1,
                                           day=1)
        # Hopefully this number is large
        # enough, Python doesn't appear to have a MAX_FLT variable
        self._nearRange = float_info.max
        self._farRange = 0.0
        self._frames = []
        self._frame = Frame()
        self._lastFile = ''
        return None

    def combineFrames(self, output, frames):
        attitudeOk = True
        for frame in frames:
            self.addFrame(frame)
            if hasattr(frame, '_attitude'):
                att = frame.getAttitude()
                if not att:
                    attitudeOk = False
        self.createInstrument()
        self.createTrack(output)
        self.createOrbit()
        if attitudeOk:
            self.createAttitude()
        return self._frame

    def createAuxFile(self, fileList, output):
        import struct
        from operator import itemgetter
        import os
        import array
        import copy
        dateIndx = []
        cnt = 0
        #first sort the files from earlier to latest. use the first element
        for name in fileList:
            with open(name, 'rb') as fp:
                date = fp.read(16)
            day, musec = struct.unpack('<dd', date)
            dateIndx.append([day, musec, name])
            cnt += 1
        sortedDate = sorted(dateIndx, key=itemgetter(0, 1))

        #we need to make sure that there are not duplicate points in the orbit since some frames overlap
        allL = array.array('d')
        allL1 = array.array('d')
        name = sortedDate[0][2]
        size = os.path.getsize(name) // 8
        with open(name, 'rb') as fp1:
            allL.fromfile(fp1, size)
        lastDay = allL[-2]
        lastMusec = allL[-1]
        for j in range(1, len(sortedDate)):
            name = sortedDate[j][2]
            size = os.path.getsize(name) // 8
            with open(name, 'rb') as fp1:
                allL1.fromfile(fp1, size)
            indxFound = None
            avgPRI = 0
            cnt = 0
            for i in range(len(allL1) // 2):
                if i > 0:
                    avgPRI += allL1[2 * i + 1] - allL1[2 * i - 1]
                    cnt += 1
                if allL1[2 * i] >= lastDay and allL1[2 * i + 1] > lastMusec:
                    avgPRI //= (cnt - 1)
                    if (
                            allL1[2 * i + 1] - lastMusec
                    ) > avgPRI / 2:  # make sure that the distance in pulse is atleast 1/2 PRI
                        indxFound = 2 * i
                    else:  #if not take the next
                        indxFound = 2 * (i + 1)
                        pass
                    break
            if not indxFound is None:
                allL.extend(allL1[indxFound:])
                lastDay = allL[-2]
                lastMusec = allL[-1]
                pass
            pass
        with open(output, 'wb') as fp:
            allL.tofile(fp)
        return

    # Add an additional Frame object to the track
    @type_check(Frame)
    def addFrame(self, frame):
        self.logger.info("Adding Frame to Track")
        self._updateTrackTimes(frame)
        self._frames.append(frame)
        return None

    def createOrbit(self):
        orbitAll = Orbit()
        for i in range(len(self._frames)):
            orbit = self._frames[i].getOrbit()
            #remember that everything is by reference, so the changes applied to orbitAll will be made to the Orbit
            #object in self.frame
            for sv in orbit._stateVectors:
                orbitAll.addStateVector(sv)
            # sort the orbit state vecotrs according to time
            orbitAll._stateVectors.sort(key=lambda sv: sv.time)
        self.removeDuplicateVectors(orbitAll._stateVectors)
        self._frame.setOrbit(orbitAll)

    def removeDuplicateVectors(self, stateVectors):
        i1 = 0
        #remove duplicate state vectors
        while True:
            if i1 >= len(stateVectors) - 1:
                break
            if stateVectors[i1].time == stateVectors[i1 + 1].time:
                stateVectors.pop(i1 + 1)
            #since is sorted by time if is not equal we can pass to the next
            else:
                i1 += 1

    def createAttitude(self):
        attitudeAll = Attitude()
        for i in range(len(self._frames)):
            attitude = self._frames[i].getAttitude()
            #remember that everything is by reference, so the changes applied to attitudeAll will be made to the Attitude object in self.frame
            for sv in attitude._stateVectors:
                attitudeAll.addStateVector(sv)
            # sort the attitude state vecotrs according to time
            attitudeAll._stateVectors.sort(key=lambda sv: sv.time)
        self.removeDuplicateVectors(attitudeAll._stateVectors)
        self._frame.setAttitude(attitudeAll)

    def createInstrument(self):
        # the platform is already part of the instrument
        ins = self._frames[0].getInstrument()
        self._frame.setInstrument(ins)

    # sometime the startLine computed below from the sensingStart is not
    #precise and the image are missaligned.
    #for each pair do an exact mach by comparing the lines around lineStart
    #file1,2 input files, startLine1 is the estimated start line in the first file
    #line1 = last line used in the first file
    #width = width of the files
    #frameNum1,2 number of the frames in the sequence of frames to stitch
    #returns a more accurate line1
    def findOverlapLine(self, file1, file2, line1, width, frameNum1,
                        frameNum2):
        import numpy as np
        import array
        fin2 = open(file2, 'rb')
        arr2 = array.array('b')
        #read full line at the beginning of second file
        arr2.fromfile(fin2, width)
        buf2 = np.array(arr2, dtype=np.int8)
        numTries = 30
        # start around line1 and try numTries around line1
        # see searchlist to see which lines it searches
        searchNumLines = 2
        #make a sliding window that search for the searchSize samples inside buf2
        searchSize = 500
        max = 0
        indx = None
        fin1 = open(file1, 'rb')
        for i in range(numTries):
            # example line1 = 0,searchNumLine = 2 and i = 0 search = [-2,-1,0,1], i = 1, serach =  [-4,-3,2,3]
            search = list(
                range(line1 - (i + 1) * searchNumLines,
                      line1 - i * searchNumLines))
            search.extend(
                list(
                    range(line1 + i * searchNumLines,
                          line1 + (i + 1) * searchNumLines)))
            for k in search:
                arr1 = array.array('b')
                #seek to the line k and read +- searchSize/2 samples from the middle of the line
                fin1.seek(k * width + (width - searchSize) // 2, 0)
                arr1.fromfile(fin1, searchSize)
                buf1 = np.array(arr1, dtype=np.int8)
                found = False
                for i in np.arange(width - searchSize):
                    lenSame = len(
                        np.nonzero(buf1 == buf2[i:i + searchSize])[0])
                    if lenSame > max:
                        max = lenSame
                        indx = k
                        if (lenSame == searchSize):
                            found = True
                            break
                if (found):
                    break
            if (found):
                break
        if not found:
            self.logger.warning(
                "Cannot find perfect overlap between frame %d and frame %d. Using acquisition time to find overlap position."
                % (frameNum1, frameNum2))
        fin1.close()
        fin2.close()
        print('Match found: ', indx)
        return indx

    def reAdjustStartLine(self, sortedList, width):
        """ Computed the adjusted starting lines based on matching in overlapping regions """
        from operator import itemgetter
        import os

        #first one always starts from zero
        startLine = [sortedList[0][0]]
        outputs = [sortedList[0][1]]
        for i in range(1, len(sortedList)):
            # endLine of the first file. we use all the lines of the first file up to endLine
            endLine = sortedList[i][0] - sortedList[i - 1][0]
            indx = self.findOverlapLine(sortedList[i - 1][1], sortedList[i][1],
                                        endLine, width, i - 1, i)
            #if indx is not None than indx is the new start line
            #otherwise we use startLine  computed from acquisition time
            if (indx is not None) and (indx + sortedList[i - 1][0] !=
                                       sortedList[i][0]):
                startLine.append(indx + sortedList[i - 1][0])
                outputs.append(sortedList[i][1])
                self.logger.info(
                    "Changing starting line for frame %d from %d to %d" %
                    (i, endLine, indx))
            else:
                startLine.append(sortedList[i][0])
                outputs.append(sortedList[i][1])

        return startLine, outputs

    # Create the actual Track data by concatenating data from
    # all of the Frames objects together
    def createTrack(self, output):
        import os
        from operator import itemgetter
        from isceobj import Constants as CN
        from ctypes import cdll, c_char_p, c_int, c_ubyte, byref
        lib = cdll.LoadLibrary(os.path.dirname(__file__) + '/concatenate.so')
        # Perhaps we should check to see if Xmin is 0, if it is not, strip off the header
        self.logger.info(
            "Adjusting Sampling Window Start Times for all Frames")
        # Iterate over each frame object, and calculate the number of samples with which to pad it on the left and right
        outputs = []
        totalWidth = 0
        auxList = []
        for frame in self._frames:
            # Calculate the amount of padding
            thisNearRange = frame.getStartingRange()
            thisFarRange = frame.getFarRange()
            left_pad = int(
                round((thisNearRange - self._nearRange) *
                      frame.getInstrument().getRangeSamplingRate() /
                      (CN.SPEED_OF_LIGHT / 2.0))) * 2
            right_pad = int(
                round((self._farRange - thisFarRange) *
                      frame.getInstrument().getRangeSamplingRate() /
                      (CN.SPEED_OF_LIGHT / 2.0))) * 2
            width = frame.getImage().getXmax()
            if width - int(width) != 0:
                raise ValueError("frame Xmax is not an integer")
            else:
                width = int(width)

            input = frame.getImage().getFilename()
            #            tempOutput = os.path.basename(os.tmpnam()) # Some temporary filename
            with tempfile.NamedTemporaryFile(dir='.') as f:
                tempOutput = f.name

            pad_value = int(frame.getInstrument().getInPhaseValue())

            if totalWidth < left_pad + width + right_pad:
                totalWidth = left_pad + width + right_pad
            # Resample this frame with swst_resample
            input_c = c_char_p(bytes(input, 'utf-8'))
            output_c = c_char_p(bytes(tempOutput, 'utf-8'))
            width_c = c_int(width)
            left_pad_c = c_int(left_pad)
            right_pad_c = c_int(right_pad)
            pad_value_c = c_ubyte(pad_value)
            lib.swst_resample(input_c, output_c, byref(width_c),
                              byref(left_pad_c), byref(right_pad_c),
                              byref(pad_value_c))
            outputs.append(tempOutput)
            auxList.append(frame.auxFile)

        #this step construct the aux file withe the pulsetime info for the all set of frames
        self.createAuxFile(auxList, output + '.aux')
        # This assumes that all of the frames to be concatenated are sampled at the same PRI
        prf = self._frames[0].getInstrument().getPulseRepetitionFrequency()
        # Calculate the starting output line of each scene
        i = 0
        lineSort = []
        # the listSort has 2 elements: a line start number which is the position of that specific frame
        # computed from acquisition time and the  corresponding file name
        for frame in self._frames:
            startLine = int(
                round(
                    DTU.timeDeltaToSeconds(frame.getSensingStart() -
                                           self._startTime) * prf))
            lineSort.append([startLine, outputs[i]])
            i += 1

        sortedList = sorted(
            lineSort,
            key=itemgetter(0))  # sort by line number i.e. acquisition time
        startLines, outputs = self.reAdjustStartLine(sortedList, totalWidth)

        self.logger.info("Concatenating Frames along Track")
        # this is a hack since the length of the file could be actually different from the one computed using start and stop time. it only matters the last frame added
        import os

        fileSize = os.path.getsize(outputs[-1])

        numLines = fileSize // totalWidth + startLines[-1]
        totalLines_c = c_int(numLines)
        # Next, call frame_concatenate
        width_c = c_int(
            totalWidth
        )  # Width of each frame (with the padding added in swst_resample)
        numberOfFrames_c = c_int(len(self._frames))
        inputs_c = (c_char_p * len(outputs))(
        )  # These are the inputs to frame_concatenate, but the outputs from swst_resample
        for kk in range(len(outputs)):
            inputs_c[kk] = bytes(outputs[kk], 'utf-8')
        output_c = c_char_p(bytes(output, 'utf-8'))
        startLines_c = (c_int * len(startLines))()
        startLines_c[:] = startLines
        lib.frame_concatenate(output_c, byref(width_c), byref(totalLines_c),
                              byref(numberOfFrames_c), inputs_c, startLines_c)

        # Clean up the temporary output files from swst_resample
        for file in outputs:
            os.unlink(file)

        orbitNum = self._frames[0].getOrbitNumber()
        first_line_utc = self._startTime
        last_line_utc = self._stopTime
        centerTime = DTU.timeDeltaToSeconds(last_line_utc -
                                            first_line_utc) / 2.0
        center_line_utc = first_line_utc + datetime.timedelta(
            microseconds=int(centerTime * 1e6))
        procFac = self._frames[0].getProcessingFacility()
        procSys = self._frames[0].getProcessingSystem()
        procSoft = self._frames[0].getProcessingSoftwareVersion()
        pol = self._frames[0].getPolarization()
        xmin = self._frames[0].getImage().getXmin()

        self._frame.setOrbitNumber(orbitNum)
        self._frame.setSensingStart(first_line_utc)
        self._frame.setSensingMid(center_line_utc)
        self._frame.setSensingStop(last_line_utc)
        self._frame.setStartingRange(self._nearRange)
        self._frame.setFarRange(self._farRange)
        self._frame.setProcessingFacility(procFac)
        self._frame.setProcessingSystem(procSys)
        self._frame.setProcessingSoftwareVersion(procSoft)
        self._frame.setPolarization(pol)
        self._frame.setNumberOfLines(numLines)
        self._frame.setNumberOfSamples(width)
        # add image to frame
        rawImage = isceobj.createRawImage()
        rawImage.setByteOrder('l')
        rawImage.setFilename(output)
        rawImage.setAccessMode('r')
        rawImage.setWidth(totalWidth)
        rawImage.setXmax(totalWidth)
        rawImage.setXmin(xmin)
        self._frame.setImage(rawImage)

    # Extract the early, late, start and stop times from a Frame object
    # And use this information to update
    def _updateTrackTimes(self, frame):

        if (frame.getSensingStart() < self._startTime):
            self._startTime = frame.getSensingStart()
        if (frame.getSensingStop() > self._stopTime):
            self._stopTime = frame.getSensingStop()
        if (frame.getStartingRange() < self._nearRange):
            self._nearRange = frame.getStartingRange()
        if (frame.getFarRange() > self._farRange):
            self._farRange = frame.getFarRange()
            pass
        pass

    pass
Пример #3
0
class ERS(Component):

    #Parsers.CEOS.CEOSFormat.ceosTypes['text'] =
    #    {'typeCode': 63, 'subtypeCode': [18,18,18]}
    #Parsers.CEOS.CEOSFormat.ceosTypes['leaderFile'] =
    #    {'typeCode': 192, 'subtypeCode': [63,18,18]}
    #Parsers.CEOS.CEOSFormat.ceosTypes['dataSetSummary'] =
    #    {'typeCode': 10, 'subtypeCode': [10,31,20]}
    #Parsers.CEOS.CEOSFormat.ceosTypes['platformPositionData'] =
    #    {'typeCode': 30, 'subtypeCode': [10,31,20]}
    #Parsers.CEOS.CEOSFormat.ceosTypes['facilityData'] =
    #    {'typeCode': 200, 'subtypeCode': [10,31,50]}
    #Parsers.CEOS.CEOSFormat.ceosTypes['datafileDescriptor'] =
    #    {'typeCode': 192, 'subtypeCode':[63,18,18]}
    #Parsers.CEOS.CEOSFormat.ceosTypes['signalData'] =
    #    {'typeCode': 10, 'subtypeCode': [50,31,20]}
    #Parsers.CEOS.CEOSFormat.ceosTypes['nullFileDescriptor'] =
    #    {'typeCode': 192, 'subtypeCode': [192,63,18]}

    logging_name = 'isce.sensor.ers'

    def __init__(self):
        Component.__init__(self)
        self._leaderFile = None
        self._imageFileList = ''
        self._leaderFileList = ''
        self._imageFile = None
        self._orbitDir = None # Use this for Delft Orbit files
        self._orbitFile = None # Use this for PDS Orbit files for now
        self._orbitType = None
        self.frameList = []
        self.output = None

        self.descriptionOfVariables = {}
        self.dictionaryOfVariables = {
            'ORBIT_TYPE': ['self._orbitType','str','mandatory'],
            'ORBIT_DIRECTORY': ['self._orbitDir','str','optional'],
            'ORBIT_FILE': ['self._orbitFile','str','optional'],
            'LEADERFILE': ['self._leaderFileList','str','mandatory'],
            'IMAGEFILE': ['self._imageFileList','str','mandatory'],
            'OUTPUT': ['self.output','str','optional']}


        self.frame = Frame()
        self.frame.configure()

        # Constants are from
        # J. J. Mohr and S. N. Madsen. Geometric calibration of ERS satellite
        # SAR images. IEEE T. Geosci. Remote, 39(4):842-850, Apr. 2001.
        self.constants = {'polarization': 'VV',
                          'antennaLength': 10,
                          'lookDirection': 'RIGHT',
                          'chirpPulseBandwidth': 15.50829e6,
                          'rangeSamplingRate': 18.962468e6,
                          'delayTime':6.622e-6,
                          'iBias': 15.5,
                          'qBias': 15.5}
        return None

    def getFrame(self):
        return self.frame

    def parse(self):
        self.leaderFile = LeaderFile(file=self._leaderFile)
        self.leaderFile.parse()

        self.imageFile = ImageFile(self)
        self.imageFile.parse()

        self.populateMetadata()

    def populateMetadata(self):
        """
        Create the appropriate metadata objects from our CEOSFormat metadata
        """

        self._populatePlatform()
        self._populateInstrument()
        self._populateFrame()
        if (self._orbitType == 'ODR'):
            self._populateDelftOrbits()
        elif (self._orbitType == 'PRC'):
            self._populatePRCOrbits()
        elif (self._orbitType == 'PDS'):
            self._populatePDSOrbits()
        else:
            self._populateHeaderOrbit()

    def _populatePlatform(self):
        """
        Populate the platform object with metadata
        """

        platform = self.frame.getInstrument().getPlatform()

        platform.setMission(self.leaderFile.sceneHeaderRecord.metadata[
            'Sensor platform mission identifier'])
        platform.setAntennaLength(self.constants['antennaLength'])
        platform.setPointingDirection(-1)
        platform.setPlanet(Planet('Earth'))

    def _populateInstrument(self):
        """Populate the instrument object with metadata"""
        instrument = self.frame.getInstrument()
        pri = self.imageFile.firstPri
        rangeSamplingRate = self.constants['rangeSamplingRate']
        #rangeSamplingRate = self.leaderFile.sceneHeaderRecord.metadata[
        #    'Range sampling rate']*1e6
        rangePixelSize = Const.c/(2.0*rangeSamplingRate)
        pulseInterval = 4.0/rangeSamplingRate*(pri+2.0)
        prf = 1.0/pulseInterval

        instrument.setRadarWavelength(
            self.leaderFile.sceneHeaderRecord.metadata['Radar wavelength'])
        instrument.setIncidenceAngle(
            self.leaderFile.sceneHeaderRecord.metadata[
            'Incidence angle at scene centre'])
        instrument.setPulseRepetitionFrequency(prf)
        instrument.setRangeSamplingRate(rangeSamplingRate)
        instrument.setRangePixelSize(rangePixelSize)
        instrument.setPulseLength(self.leaderFile.sceneHeaderRecord.metadata[
            'Range pulse length']*1e-6)
        instrument.setChirpSlope(self.constants['chirpPulseBandwidth']/
            (self.leaderFile.sceneHeaderRecord.metadata['Range pulse length']*
             1e-6))
        instrument.setInPhaseValue(self.constants['iBias'])
        instrument.setQuadratureValue(self.constants['qBias'])

    def _populateFrame(self):
        """Populate the scene object with metadata"""
        rangeSamplingRate = self.constants['rangeSamplingRate']
        #rangeSamplingRate = self.leaderFile.sceneHeaderRecord.metadata[
        #    'Range sampling rate']*1e6
        rangePixelSize = Const.c/(2.0*rangeSamplingRate)
        pulseInterval = 1.0/self.frame.getInstrument().getPulseRepetitionFrequency()
        frame = self._decodeSceneReferenceNumber(
            self.leaderFile.sceneHeaderRecord.metadata[
            'Scene reference number'])
        startingRange = (9*pulseInterval + self.imageFile.minSwst*4/rangeSamplingRate-self.constants['delayTime'])*Const.c/2.0
        farRange = startingRange + self.imageFile.width*rangePixelSize
        # Use the Scene center time to get the date, then use the ICU on board time from the image for the rest
        centerLineTime = datetime.datetime.strptime(self.leaderFile.sceneHeaderRecord.metadata['Scene centre time'],"%Y%m%d%H%M%S%f")
        first_line_utc = datetime.datetime(year=centerLineTime.year, month=centerLineTime.month, day=centerLineTime.day)
        if(self.leaderFile.sceneHeaderRecord.metadata['Processing facility identifier'] in ('CRDC_SARDPF','GTS - ERS')):
            first_line_utc = first_line_utc + datetime.timedelta(milliseconds=self.imageFile.startTime)
        else:
            deltaSeconds = (self.imageFile.startTime - self.leaderFile.sceneHeaderRecord.metadata['Satellite encoded binary time code'])* 1/256.0
            # Sometimes, the ICU on board clock is corrupt, if the time suggested by the on board clock is more than
            # 5 days from the satellite clock time, assume its bogus and use the low-precision scene centre time
            if (math.fabs(deltaSeconds) > 5*86400):
                        self.logger.warn("ICU on board time appears to be corrupt, resorting to low precision clock")
                        first_line_utc = centerLineTime - datetime.timedelta(microseconds=pulseInterval*(self.imageFile.length/2.0)*1e6)
            else:
                satelliteClockTime = datetime.datetime.strptime(self.leaderFile.sceneHeaderRecord.metadata['Satellite clock time'],"%Y%m%d%H%M%S%f")
                first_line_utc = satelliteClockTime + datetime.timedelta(microseconds=int(deltaSeconds*1e6))
        mid_line_utc = first_line_utc + datetime.timedelta(microseconds=pulseInterval*(self.imageFile.length/2.0)*1e6)
        last_line_utc = first_line_utc + datetime.timedelta(microseconds=pulseInterval*self.imageFile.length*1e6)
        self.logger.debug("Frame UTC start, mid, end times:  %s %s %s" % (first_line_utc,mid_line_utc,last_line_utc))

        self.frame.setFrameNumber(frame)
        self.frame.setOrbitNumber(self.leaderFile.sceneHeaderRecord.metadata['Orbit number'])
        self.frame.setStartingRange(startingRange)
        self.frame.setFarRange(farRange)
        self.frame.setProcessingFacility(self.leaderFile.sceneHeaderRecord.metadata['Processing facility identifier'])
        self.frame.setProcessingSystem(self.leaderFile.sceneHeaderRecord.metadata['Processing system identifier'])
        self.frame.setProcessingSoftwareVersion(self.leaderFile.sceneHeaderRecord.metadata['Processing version identifier'])
        self.frame.setPolarization(self.constants['polarization'])
        self.frame.setNumberOfLines(self.imageFile.length)
        self.frame.setNumberOfSamples(self.imageFile.width)
        self.frame.setSensingStart(first_line_utc)
        self.frame.setSensingMid(mid_line_utc)
        self.frame.setSensingStop(last_line_utc)

    def _populateHeaderOrbit(self):
        """Populate an orbit object with the header orbits"""
        self.logger.info("Using Header Orbits")
        orbit = self.frame.getOrbit()

        orbit.setOrbitSource('Header')
        orbit.setOrbitQuality('Unknown')
        t0 = datetime.datetime(year=self.leaderFile.platformPositionRecord.metadata['Year of data point'],
                               month=self.leaderFile.platformPositionRecord.metadata['Month of data point'],
                               day=self.leaderFile.platformPositionRecord.metadata['Day of data point'])
        t0 = t0 + datetime.timedelta(microseconds=self.leaderFile.platformPositionRecord.metadata['Seconds of day']*1e6)
        for i in range(self.leaderFile.platformPositionRecord.metadata['Number of data points']):
            vec = StateVector()
            deltaT = self.leaderFile.platformPositionRecord.metadata['Time interval between DATA points']
            t = t0 + datetime.timedelta(microseconds=i*deltaT*1e6)
            vec.setTime(t)
            dataPoints = self.leaderFile.platformPositionRecord.metadata['Positional Data Points'][i]
            vec.setPosition([dataPoints['Position vector X'], dataPoints['Position vector Y'], dataPoints['Position vector Z']])
            vec.setVelocity([dataPoints['Velocity vector X'], dataPoints['Velocity vector Y'], dataPoints['Velocity vector Z']])
            orbit.addStateVector(vec)

    def _populateDelftOrbits(self):
        """Populate an orbit object with the Delft orbits"""
        from isceobj.Orbit.ODR import ODR, Arclist
        self.logger.info("Using Delft Orbits")
        arclist = Arclist(os.path.join(self._orbitDir,'arclist'))
        arclist.parse()
        orbitFile = arclist.getOrbitFile(self.frame.getSensingStart())
        odr = ODR(file=os.path.join(self._orbitDir,orbitFile))
        #jng it seem that for this tipe of orbit points are separated by 60 sec. In ODR at least 9 state vectors are needed to compute the velocities. add
        # extra time before and after to allow interpolation, but do not do it for all data points. too slow
        startTimePreInterp = self.frame.getSensingStart() - datetime.timedelta(minutes=60)
        stopTimePreInterp = self.frame.getSensingStop() + datetime.timedelta(minutes=60)
        odr.parseHeader(startTimePreInterp,stopTimePreInterp)
        startTime = self.frame.getSensingStart() - datetime.timedelta(minutes=5)
        stopTime = self.frame.getSensingStop() + datetime.timedelta(minutes=5)
        self.logger.debug("Extracting orbits between %s and %s" % (startTime,stopTime))
        orbit = odr.trimOrbit(startTime,stopTime)
        self.frame.setOrbit(orbit)

    def _populatePRCOrbits(self):
        """Populate an orbit object the D-PAF PRC orbits"""
        from isceobj.Orbit.PRC import PRC, Arclist
        self.logger.info("Using PRC Orbits")
        arclist = Arclist(os.path.join(self._orbitDir,'arclist'))
        arclist.parse()
        orbitFile = arclist.getOrbitFile(self.frame.getSensingStart())
        self.logger.debug("Using file %s" % (orbitFile))
        prc = PRC(file=os.path.join(self._orbitDir,orbitFile))
        prc.parse()
        startTime = self.frame.getSensingStart() - datetime.timedelta(minutes=5)
        stopTime = self.frame.getSensingStop() + datetime.timedelta(minutes=5)
        self.logger.debug("Extracting orbits between %s and %s" % (startTime,stopTime))
        fullOrbit = prc.getOrbit()
        orbit = fullOrbit.trimOrbit(startTime,stopTime)
        self.frame.setOrbit(orbit)

    def _populatePDSOrbits(self):
        """
        Populate an orbit object using the ERS-2 PDS format
        """
        from isceobj.Orbit.PDS import PDS
        self.logger.info("Using PDS Orbits")
        pds = PDS(file=self._orbitFile)
        pds.parse()
        startTime = self.frame.getSensingStart() - datetime.timedelta(minutes=5)
        stopTime = self.frame.getSensingStop() + datetime.timedelta(minutes=5)
        self.logger.debug("Extracting orbits between %s and %s" % (startTime,stopTime))
        fullOrbit = pds.getOrbit()
        orbit = fullOrbit.trimOrbit(startTime,stopTime)
        self.frame.setOrbit(orbit)

    def extractImage(self):
        import array
        import math
        # just in case there was only one image and it was passed as a str instead of a list with only one element
        if(isinstance(self._imageFileList,str)):
            self._imageFileList = [self._imageFileList]
            self._leaderFileList = [self._leaderFileList]
        if(len(self._imageFileList) != len(self._leaderFileList)):
            self.logger.error("Number of leader files different from number of image files.")
            raise Exception

        self.frameList = []

        for i in range(len(self._imageFileList)):
            appendStr = "_" + str(i)
            #if only one file don't change the name
            if(len(self._imageFileList) == 1):
                appendStr = ''

            self.frame = Frame()
            self.frame.configure()

            self._leaderFile = self._leaderFileList[i]
            self._imageFile = self._imageFileList[i]
            self.leaderFile = LeaderFile(file=self._leaderFile)
            self.leaderFile.parse()

            self.imageFile = ImageFile(self)

            try:
                outputNow = self.output + appendStr
                out = open(outputNow,'wb')
            except IOError as strerr:
                self.logger.error("IOError: %s" % strerr)
                return

            self.imageFile.extractImage(output=out)
            out.close()

            rawImage = isceobj.createRawImage()
            rawImage.setByteOrder('l')
            rawImage.setAccessMode('read')
            rawImage.setFilename(outputNow)
            rawImage.setWidth(self.imageFile.width)
            rawImage.setXmin(0)
            rawImage.setXmax(self.imageFile.width)
            self.frame.setImage(rawImage)
            self.populateMetadata()
            self.frameList.append(self.frame)
            #jng Howard Z at this point adjusts the sampling starting time for imagery generated from CRDC_SARDPF facility.
            # for now create the orbit aux file based in starting time and prf
            prf = self.frame.getInstrument().getPulseRepetitionFrequency()
            senStart = self.frame.getSensingStart()
            numPulses = int(math.ceil(DTU.timeDeltaToSeconds(self.frame.getSensingStop()-senStart)*prf))
            # the aux files has two entries per line. day of the year and microseconds in the day
            musec0 = (senStart.hour*3600 + senStart.minute*60 + senStart.second)*10**6 + senStart.microsecond
            maxMusec = (24*3600)*10**6#use it to check if we went across  a day. very rare
            day0 = (datetime.datetime(senStart.year,senStart.month,senStart.day) - datetime.datetime(senStart.year,1,1)).days + 1
            outputArray  = array.array('d',[0]*2*numPulses)
            self.frame.auxFile = outputNow + '.aux'
            fp = open(self.frame.auxFile,'wb')
            j = -1
            for i1 in range(numPulses):
                j += 1
                musec = round((j/prf)*10**6) + musec0
                if musec >= maxMusec:
                    day0 += 1
                    musec0 = musec%maxMusec
                    musec = musec0
                    j = 0
                outputArray[2*i1] = day0
                outputArray[2*i1+1] = musec

            outputArray.tofile(fp)
            fp.close()

        tk = Track()
        if(len(self._imageFileList) > 1):
            self.frame = tk.combineFrames(self.output,self.frameList)

            for i in range(len(self._imageFileList)):
                try:
                    os.remove(self.output + "_" + str(i))
                except OSError:
                    print("Error. Cannot remove temporary file",self.output + "_" + str(i))
                    raise OSError



    def _decodeSceneReferenceNumber(self,referenceNumber):
        frameNumber = referenceNumber.split('=')
        if (len(frameNumber) > 2):
            frameNumber = frameNumber[2].strip()
        else:
            frameNumber = frameNumber[0]

        return frameNumber
Пример #4
0
class Risat1_SLC(Sensor):
    """
        Code to read CEOSFormat leader files for Risat-1 SAR data.
    """
    family = "risat1"
    logging_name = 'isce.sensor.Risat1'
    parameter_list = (IMAGEFILE, LEADERFILE, METAFILE,
                      DATATYPE) + Sensor.parameter_list

    @logged
    def __init__(self, name=''):
        super().__init__(family=self.__class__.family, name=name)
        self.imageFile = None
        self.leaderFile = None

        #####Specific doppler functions for RISAT1
        self.doppler_coeff = None
        self.azfmrate_coeff = None
        self.lineDirection = None
        self.pixelDirection = None

        self.frame = Frame()
        self.frame.configure()

        self.constants = {
            'antennaLength': 6,
        }

        self.TxPolMap = {
            1: 'V',
            2: 'H',
            3: 'L',
            4: 'R',
        }

        self.RxPolMap = {
            1: 'V',
            2: 'H',
        }

    def getFrame(self):
        return self.frame

    def parse(self):
        self.leaderFile = LeaderFile(self, file=self._leaderFile)
        self.leaderFile.parse()

        self.imageFile = ImageFile(self, file=self._imageFile)
        self.imageFile.parse()

        self.populateMetadata()

    def populateMetadata(self):
        """
            Create the appropriate metadata objects from our CEOSFormat metadata
        """
        frame = self._decodeSceneReferenceNumber(
            self.leaderFile.sceneHeaderRecord.
            metadata['Scene reference number'])
        try:
            rangePixelSize = Const.c / (2 * self.leaderFile.sceneHeaderRecord.
                                        metadata['Range sampling rate'])
        except ZeroDivisionError:
            rangePixelSize = 0

        print(
            'Average terrain height: ', 1000 * self.leaderFile.
            sceneHeaderRecord.metadata['Average terrain height in km'])

        ins = self.frame.getInstrument()
        platform = ins.getPlatform()
        platform.setMission(self.leaderFile.sceneHeaderRecord.
                            metadata['Sensor platform mission identifier'])
        platform.setAntennaLength(self.constants['antennaLength'])
        platform.setPlanet(Planet(pname='Earth'))

        ins.setRadarWavelength(
            self.leaderFile.sceneHeaderRecord.metadata['Radar wavelength'])
        ins.setIncidenceAngle(self.leaderFile.sceneHeaderRecord.
                              metadata['Incidence angle at scene centre'])
        self.frame.getInstrument().setPulseRepetitionFrequency(
            self.leaderFile.sceneHeaderRecord.
            metadata['Pulse Repetition Frequency'])
        ins.setRangePixelSize(rangePixelSize)
        ins.setRangeSamplingRate(
            self.leaderFile.sceneHeaderRecord.metadata['Range sampling rate'])
        ins.setPulseLength(
            self.leaderFile.sceneHeaderRecord.metadata['Range pulse length'])

        chirpPulseBandwidth = self.leaderFile.processingRecord.metadata[
            'Pulse bandwidth code'] * 1e4
        ins.setChirpSlope(
            chirpPulseBandwidth /
            self.leaderFile.sceneHeaderRecord.metadata['Range pulse length'])
        ins.setInPhaseValue(0.0)
        ins.setQuadratureValue(0.0)

        self.lineDirection = self.leaderFile.sceneHeaderRecord.metadata[
            'Time direction indicator along line direction'].strip()
        self.pixelDirection = self.leaderFile.sceneHeaderRecord.metadata[
            'Time direction indicator along pixel direction'].strip()

        ######RISAT-1 sensor orientation convention is opposite to ours
        lookSide = self.leaderFile.processingRecord.metadata[
            'Sensor orientation']
        if lookSide == 'RIGHT':
            platform.setPointingDirection(1)
        elif lookSide == 'LEFT':
            platform.setPointingDirection(-1)
        else:
            raise Exception('Unknown look side')

        print('Leader file look side: ', lookSide)

        self.frame.setFrameNumber(frame)
        self.frame.setOrbitNumber(
            self.leaderFile.sceneHeaderRecord.metadata['Orbit number'])
        self.frame.setProcessingFacility(
            self.leaderFile.sceneHeaderRecord.
            metadata['Processing facility identifier'])
        self.frame.setProcessingSystem(
            self.leaderFile.sceneHeaderRecord.
            metadata['Processing system identifier'])
        self.frame.setProcessingSoftwareVersion(
            self.leaderFile.sceneHeaderRecord.
            metadata['Processing version identifier'])
        self.frame.setNumberOfLines(
            self.imageFile.imageFDR.metadata['Number of lines per data set'])
        self.frame.setNumberOfSamples(
            self.imageFile.imageFDR.
            metadata['Number of pixels per line per SAR channel'])

        ######

        self.frame.getOrbit().setOrbitSource('Header')
        self.frame.getOrbit().setOrbitQuality(
            self.leaderFile.platformPositionRecord.
            metadata['Orbital elements designator'])
        t0 = datetime.datetime(year=2000 +
                               self.leaderFile.platformPositionRecord.
                               metadata['Year of data point'],
                               month=self.leaderFile.platformPositionRecord.
                               metadata['Month of data point'],
                               day=self.leaderFile.platformPositionRecord.
                               metadata['Day of data point'])
        t0 = t0 + datetime.timedelta(
            seconds=self.leaderFile.platformPositionRecord.
            metadata['Seconds of day'])

        #####Read in orbit in inertial coordinates
        orb = Orbit()
        deltaT = self.leaderFile.platformPositionRecord.metadata[
            'Time interval between DATA points']
        numPts = self.leaderFile.platformPositionRecord.metadata[
            'Number of data points']

        for i in range(numPts):
            vec = StateVector()
            t = t0 + datetime.timedelta(seconds=i * deltaT)
            vec.setTime(t)

            dataPoints = self.leaderFile.platformPositionRecord.metadata[
                'Positional Data Points'][i]
            pos = [
                dataPoints['Position vector X'],
                dataPoints['Position vector Y'],
                dataPoints['Position vector Z']
            ]
            vel = [
                dataPoints['Velocity vector X'],
                dataPoints['Velocity vector Y'],
                dataPoints['Velocity vector Z']
            ]
            vec.setPosition(pos)
            vec.setVelocity(vel)
            orb.addStateVector(vec)

        #####Convert orbits from ECI to ECR frame
        t0 = orb._stateVectors[0]._time
        ang = self.leaderFile.platformPositionRecord.metadata[
            'Greenwich mean hour angle']

        cOrb = ECI2ECR(orb, GAST=ang, epoch=t0)
        iOrb = cOrb.convert()

        #####Extend the orbits by a few points
        #####Expect large azimuth shifts - absolutely needed
        #####Since CEOS contains state vectors that barely covers scene extent
        planet = self.frame.instrument.platform.planet
        orbExt = OrbitExtender()
        orbExt.configure()
        orbExt._newPoints = 4
        newOrb = orbExt.extendOrbit(iOrb)

        orb = self.frame.getOrbit()

        for sv in newOrb:
            orb.addStateVector(sv)

        self.doppler_coeff = [
            self.leaderFile.sceneHeaderRecord.
            metadata['Cross track Doppler frequency centroid constant term'],
            self.leaderFile.sceneHeaderRecord.
            metadata['Cross track Doppler frequency centroid linear term'],
            self.leaderFile.sceneHeaderRecord.
            metadata['Cross track Doppler frequency centroid quadratic term']
        ]

        self.azfmrate_coeff = [
            self.leaderFile.sceneHeaderRecord.
            metadata['Cross track Doppler frequency rate constant term'],
            self.leaderFile.sceneHeaderRecord.
            metadata['Cross track Doppler frequency rate linear term'],
            self.leaderFile.sceneHeaderRecord.
            metadata['Cross track Doppler frequency rate quadratic term']
        ]

    def extractImage(self):
        import isceobj
        if (self.imageFile is None) or (self.leaderFile is None):
            self.parse()

        try:
            out = open(self.output, 'wb')
        except IOError as strerr:
            self.logger.error("IOError: %s" % strerr)

        self.imageFile.extractImage(output=out, dtype=self._dataType)
        out.close()

        self.frame.setSensingStart(self.imageFile.sensingStart)
        self.frame.setSensingStop(self.imageFile.sensingStop)
        sensingMid = self.imageFile.sensingStart + datetime.timedelta(
            seconds=0.5 * (self.imageFile.sensingStop -
                           self.imageFile.sensingStart).total_seconds())
        self.frame.setSensingMid(sensingMid)

        self.frame.setStartingRange(self.imageFile.nearRange)
        self.frame.setFarRange(self.imageFile.farRange)
        #        self.doppler_coeff = self.imageFile.dopplerCoeff
        self.frame.getInstrument().setPulseRepetitionFrequency(
            self.imageFile.prf)

        pol = self.TxPolMap[int(
            self.imageFile.polarization[0])] + self.TxPolMap[int(
                self.imageFile.polarization[1])]
        self.frame.setPolarization(pol)

        rawImage = isceobj.createSlcImage()
        rawImage.setByteOrder('l')
        rawImage.setAccessMode('read')
        rawImage.setFilename(self.output)
        rawImage.setWidth(self.imageFile.width)
        rawImage.setXmin(0)
        rawImage.setXmax(self.imageFile.width)
        rawImage.renderHdr()
        self.frame.setImage(rawImage)

        return

    def extractDoppler(self):
        '''
        Evaluate the doppler polynomial and return the average value for now.
        '''

        ####For insarApp

        quadratic = {}
        quadratic['a'] = self.doppler_coeff[0] / self.frame.getInstrument(
        ).getPulseRepetitionFrequency()
        quadratic['b'] = 0.
        quadratic['c'] = 0.

        ###For roiApp
        ###More accurate
        self.frame._dopplerVsPixel = self.doppler_coeff

        return quadratic

    def _decodeSceneReferenceNumber(self, referenceNumber):
        return referenceNumber
Пример #5
0
class ALOS2(Sensor):
    """
        Code to read CEOSFormat leader files for ALOS2 SLC data.
    """

    family = 'alos2'

    parameter_list = (WAVELENGTH, LEADERFILE,
                      IMAGEFILE) + Sensor.parameter_list

    fsampConst = {
        104: 1.047915957140240E+08,
        52: 5.239579785701190E+07,
        34: 3.493053190467460E+07,
        17: 1.746526595233730E+07
    }

    #Orbital Elements (Quality) Designator
    #ALOS-2/PALSAR-2 Level 1.1/1.5/2.1/3.1 CEOS SAR Product Format Description
    #PALSAR-2_xx_Format_CEOS_E_r.pdf
    orbitElementsDesignator = {
        '0': 'preliminary',
        '1': 'decision',
        '2': 'high precision'
    }

    def __init__(self, name=''):
        super().__init__(family=self.__class__.family, name=name)
        self.leaderFile = None
        self.imageFile = None

        #####Soecific doppler functions for ALOS2
        self.doppler_coeff = None
        self.azfmrate_coeff = None
        self.lineDirection = None
        self.pixelDirection = None

        self.frame = Frame()
        self.frame.configure()

        self.constants = {'polarization': 'HH', 'antennaLength': 10}

    def getFrame(self):
        return self.frame

    def parse(self):
        self.leaderFile = LeaderFile(self, file=self._leaderFile)
        self.leaderFile.parse()

        self.imageFile = ImageFile(self, file=self._imageFile)
        self.imageFile.parse()

        self.populateMetadata()

    def populateMetadata(self):
        """
            Create the appropriate metadata objects from our CEOSFormat metadata
        """
        frame = self._decodeSceneReferenceNumber(
            self.leaderFile.sceneHeaderRecord.
            metadata['Scene reference number'])

        fsamplookup = int(self.leaderFile.sceneHeaderRecord.
                          metadata['Range sampling rate in MHz'])

        rangePixelSize = Const.c / (2 * self.fsampConst[fsamplookup])

        ins = self.frame.getInstrument()
        platform = ins.getPlatform()
        platform.setMission(self.leaderFile.sceneHeaderRecord.
                            metadata['Sensor platform mission identifier'])
        platform.setAntennaLength(self.constants['antennaLength'])
        platform.setPointingDirection(1)
        platform.setPlanet(Planet(pname='Earth'))

        if self.wavelength:
            ins.setRadarWavelength(float(self.wavelength))
#            print('ins.radarWavelength = ', ins.getRadarWavelength(),
#                  type(ins.getRadarWavelength()))
        else:
            ins.setRadarWavelength(
                self.leaderFile.sceneHeaderRecord.metadata['Radar wavelength'])

        ins.setIncidenceAngle(self.leaderFile.sceneHeaderRecord.
                              metadata['Incidence angle at scene centre'])
        self.frame.getInstrument().setPulseRepetitionFrequency(
            self.leaderFile.sceneHeaderRecord.
            metadata['Pulse Repetition Frequency in mHz'] * 1.0e-3)
        ins.setRangePixelSize(rangePixelSize)
        ins.setRangeSamplingRate(self.fsampConst[fsamplookup])
        ins.setPulseLength(self.leaderFile.sceneHeaderRecord.
                           metadata['Range pulse length in microsec'] * 1.0e-6)
        chirpSlope = self.leaderFile.sceneHeaderRecord.metadata[
            'Nominal range pulse (chirp) amplitude coefficient linear term']
        chirpPulseBandwidth = abs(
            chirpSlope * self.leaderFile.sceneHeaderRecord.
            metadata['Range pulse length in microsec'] * 1.0e-6)
        ins.setChirpSlope(chirpSlope)
        ins.setInPhaseValue(7.5)
        ins.setQuadratureValue(7.5)

        self.lineDirection = self.leaderFile.sceneHeaderRecord.metadata[
            'Time direction indicator along line direction'].strip()
        self.pixelDirection = self.leaderFile.sceneHeaderRecord.metadata[
            'Time direction indicator along pixel direction'].strip()

        ######ALOS2 includes this information in clock angle
        clockAngle = self.leaderFile.sceneHeaderRecord.metadata[
            'Sensor clock angle']
        if clockAngle == 90.0:
            platform.setPointingDirection(-1)
        elif clockAngle == -90.0:
            platform.setPointingDirection(1)
        else:
            raise Exception(
                'Unknown look side. Clock Angle = {0}'.format(clockAngle))

#        print(self.leaderFile.sceneHeaderRecord.metadata["Sensor ID and mode of operation for this channel"])
        self.frame.setFrameNumber(frame)
        self.frame.setOrbitNumber(
            self.leaderFile.sceneHeaderRecord.metadata['Orbit number'])
        self.frame.setProcessingFacility(
            self.leaderFile.sceneHeaderRecord.
            metadata['Processing facility identifier'])
        self.frame.setProcessingSystem(
            self.leaderFile.sceneHeaderRecord.
            metadata['Processing system identifier'])
        self.frame.setProcessingSoftwareVersion(
            self.leaderFile.sceneHeaderRecord.
            metadata['Processing version identifier'])
        self.frame.setPolarization(self.constants['polarization'])
        self.frame.setNumberOfLines(
            self.imageFile.imageFDR.metadata['Number of lines per data set'])
        self.frame.setNumberOfSamples(
            self.imageFile.imageFDR.
            metadata['Number of pixels per line per SAR channel'])

        ######
        orb = self.frame.getOrbit()

        orb.setOrbitSource('Header')
        orb.setOrbitQuality(self.orbitElementsDesignator[
            self.leaderFile.platformPositionRecord.
            metadata['Orbital elements designator']])
        t0 = datetime.datetime(year=self.leaderFile.platformPositionRecord.
                               metadata['Year of data point'],
                               month=self.leaderFile.platformPositionRecord.
                               metadata['Month of data point'],
                               day=self.leaderFile.platformPositionRecord.
                               metadata['Day of data point'])
        t0 = t0 + datetime.timedelta(
            seconds=self.leaderFile.platformPositionRecord.
            metadata['Seconds of day'])

        #####Read in orbit in inertial coordinates
        deltaT = self.leaderFile.platformPositionRecord.metadata[
            'Time interval between data points']
        numPts = self.leaderFile.platformPositionRecord.metadata[
            'Number of data points']

        orb = self.frame.getOrbit()
        for i in range(numPts):
            vec = StateVector()
            t = t0 + datetime.timedelta(seconds=i * deltaT)
            vec.setTime(t)

            dataPoints = self.leaderFile.platformPositionRecord.metadata[
                'Positional Data Points'][i]
            pos = [
                dataPoints['Position vector X'],
                dataPoints['Position vector Y'],
                dataPoints['Position vector Z']
            ]
            vel = [
                dataPoints['Velocity vector X'],
                dataPoints['Velocity vector Y'],
                dataPoints['Velocity vector Z']
            ]
            vec.setPosition(pos)
            vec.setVelocity(vel)
            orb.addStateVector(vec)

        self.doppler_coeff = [
            self.leaderFile.sceneHeaderRecord.
            metadata['Cross track Doppler frequency centroid constant term'],
            self.leaderFile.sceneHeaderRecord.
            metadata['Cross track Doppler frequency centroid linear term'],
            self.leaderFile.sceneHeaderRecord.
            metadata['Cross track Doppler frequency centroid quadratic term']
        ]

        self.azfmrate_coeff = [
            self.leaderFile.sceneHeaderRecord.
            metadata['Cross track Doppler frequency rate constant term'],
            self.leaderFile.sceneHeaderRecord.
            metadata['Cross track Doppler frequency rate linear term'],
            self.leaderFile.sceneHeaderRecord.
            metadata['Cross track Doppler frequency rate quadratic term']
        ]


#        print('Terrain height: ', self.leaderFile.sceneHeaderRecord.metadata['Average terrain ellipsoid height'])

    def extractImage(self):
        import isceobj
        if (self.imageFile is None) or (self.leaderFile is None):
            self.parse()

        try:
            out = open(self.output, 'wb')
        except IOError as strerr:
            self.logger.error("IOError: %s" % strerr)

        self.imageFile.extractImage(output=out)
        out.close()

        #        rangeGate = self.leaderFile.sceneHeaderRecord.metadata['Range gate delay in microsec']*1e-6
        #        delt = datetime.timedelta(seconds=rangeGate)

        delt = datetime.timedelta(seconds=0.0)
        self.frame.setSensingStart(self.imageFile.sensingStart + delt)
        self.frame.setSensingStop(self.imageFile.sensingStop + delt)
        sensingMid = self.imageFile.sensingStart + datetime.timedelta(
            seconds=0.5 * (self.imageFile.sensingStop -
                           self.imageFile.sensingStart).total_seconds()) + delt
        self.frame.setSensingMid(sensingMid)

        self.frame.setStartingRange(self.imageFile.nearRange)

        self.frame.getInstrument().setPulseRepetitionFrequency(
            self.imageFile.prf)

        pixelSize = self.frame.getInstrument().getRangePixelSize()
        farRange = self.imageFile.nearRange + (pixelSize -
                                               1) * self.imageFile.width
        self.frame.setFarRange(farRange)

        rawImage = isceobj.createSlcImage()
        rawImage.setByteOrder('l')
        rawImage.setAccessMode('read')
        rawImage.setFilename(self.output)
        rawImage.setWidth(self.imageFile.width)
        rawImage.setXmin(0)
        rawImage.setXmax(self.imageFile.width)
        rawImage.renderHdr()
        self.frame.setImage(rawImage)

        return

    def extractDoppler(self):
        '''
        Evaluate the doppler polynomial and return the average value for now.
        '''
        midwidth = self.frame.getNumberOfSamples() / 2.0
        dop = 0.0
        prod = 1.0
        for ind, kk in enumerate(self.doppler_coeff):
            dop += kk * prod
            prod *= midwidth

        print('Average Doppler: {0}'.format(dop))

        ####For insarApp
        quadratic = {}
        quadratic['a'] = dop / self.frame.getInstrument(
        ).getPulseRepetitionFrequency()
        quadratic['b'] = 0.
        quadratic['c'] = 0.

        ####For roiApp
        ####More accurate
        ####CEOS already provides function vs pixel
        self.frame._dopplerVsPixel = self.doppler_coeff

        return quadratic

    def _decodeSceneReferenceNumber(self, referenceNumber):
        return referenceNumber
Пример #6
0
class EnviSAT_SLC(Sensor):

    parameter_list = (ORBIT_DIRECTORY, ORBITFILE, INSTRUMENTFILE,
                      INSTRUMENT_DIRECTORY, IMAGEFILE) + Sensor.parameter_list
    """
        A Class for parsing EnviSAT instrument and imagery files
    """

    family = 'envisat'

    def __init__(self, family='', name=''):
        super(EnviSAT_SLC,
              self).__init__(family if family else self.__class__.family,
                             name=name)
        self._imageFile = None
        self._instrumentFileData = None
        self._imageryFileData = None
        self.dopplerRangeTime = None
        self.rangeRefTime = None
        self.logger = logging.getLogger("isce.sensor.EnviSAT_SLC")
        self.frame = None
        self.frameList = []

        self.constants = {'antennaLength': 10.0, 'iBias': 128, 'qBias': 128}

    def getFrame(self):
        return self.frame

    def parse(self):
        """
            Parse both imagery and instrument files and create
            objects representing the platform, instrument and scene
        """

        self.frame = Frame()
        self.frame.configure()

        self._imageFile = ImageryFile(fileName=self._imageFileName)
        self._imageryFileData = self._imageFile.parse()

        if self.instrumentFile in [None, '']:
            self.findInstrumentFile()

        instrumentFileParser = InstrumentFile(fileName=self.instrumentFile)
        self._instrumentFileData = instrumentFileParser.parse()

        self.populateMetadata()

    def populateMetadata(self):

        self._populatePlatform()
        self._populateInstrument()
        self._populateFrame()
        self._populateOrbit()
        self.dopplerRangeTime = self._imageryFileData['doppler']
        self.rangeRefTime = self._imageryFileData['dopplerOrigin'][0] * 1.0e-9


#        print('Doppler confidence: ', 100.0 * self._imageryFileData['dopplerConfidence'][0])

    def _populatePlatform(self):
        """Populate the platform object with metadata"""
        platform = self.frame.getInstrument().getPlatform()

        # Populate the Platform and Scene objects
        platform.setMission("Envisat")
        platform.setPointingDirection(-1)
        platform.setAntennaLength(self.constants['antennaLength'])
        platform.setPlanet(Planet(pname="Earth"))

    def _populateInstrument(self):
        """Populate the instrument object with metadata"""
        instrument = self.frame.getInstrument()

        rangeSampleSpacing = Const.c / (
            2 * self._imageryFileData['rangeSamplingRate'])
        pri = self._imageryFileData['pri']

        ####These shouldnt matter for SLC data since data is already focused.
        txPulseLength = 512 / 19207680.000000
        chirpPulseBandwidth = 16.0e6
        chirpSlope = chirpPulseBandwidth / txPulseLength

        instrument.setRangePixelSize(rangeSampleSpacing)
        instrument.setPulseLength(txPulseLength)
        #instrument.setSwath(imageryFileData['SWATH'])
        instrument.setRadarFrequency(self._instrumentFileData['frequency'])
        instrument.setChirpSlope(chirpSlope)
        instrument.setRangeSamplingRate(
            self._imageryFileData['rangeSamplingRate'])
        instrument.setPulseRepetitionFrequency(1.0 / pri)
        #instrument.setRangeBias(rangeBias)
        instrument.setInPhaseValue(self.constants['iBias'])
        instrument.setQuadratureValue(self.constants['qBias'])

    def _populateFrame(self):
        """Populate the scene object with metadata"""
        numberOfLines = self._imageryFileData['numLines']
        numberOfSamples = self._imageryFileData['numSamples']
        pri = self._imageryFileData['pri']
        startingRange = Const.c * float(
            self._imageryFileData['timeToFirstSample']) * 1.0e-9 / 2.0
        rangeSampleSpacing = Const.c / (
            2 * self._imageryFileData['rangeSamplingRate'])
        farRange = startingRange + numberOfSamples * rangeSampleSpacing
        first_line_utc = datetime.datetime.strptime(
            self._imageryFileData['FIRST_LINE_TIME'], '%d-%b-%Y %H:%M:%S.%f')
        center_line_utc = datetime.datetime.strptime(
            self._imageryFileData['FIRST_LINE_TIME'], '%d-%b-%Y %H:%M:%S.%f')
        last_line_utc = datetime.datetime.strptime(
            self._imageryFileData['LAST_LINE_TIME'], '%d-%b-%Y %H:%M:%S.%f')
        centerTime = DTUtil.timeDeltaToSeconds(last_line_utc -
                                               first_line_utc) / 2.0
        center_line_utc = center_line_utc + datetime.timedelta(
            microseconds=int(centerTime * 1e6))

        self.frame.setStartingRange(startingRange)
        self.frame.setFarRange(farRange)
        self.frame.setProcessingFacility(self._imageryFileData['PROC_CENTER'])
        self.frame.setProcessingSystem(self._imageryFileData['SOFTWARE_VER'])
        self.frame.setTrackNumber(int(self._imageryFileData['REL_ORBIT']))
        self.frame.setOrbitNumber(int(self._imageryFileData['ABS_ORBIT']))
        self.frame.setPolarization(self._imageryFileData['MDS1_TX_RX_POLAR'])
        self.frame.setNumberOfSamples(numberOfSamples)
        self.frame.setNumberOfLines(numberOfLines)
        self.frame.setSensingStart(first_line_utc)
        self.frame.setSensingMid(center_line_utc)
        self.frame.setSensingStop(last_line_utc)

    def _populateOrbit(self):
        if self.orbitFile in [None, '']:
            self.findOrbitFile()

        dorParser = DOR(fileName=self.orbitFile)
        dorParser.parse()
        startTime = self.frame.getSensingStart() - datetime.timedelta(
            minutes=5)
        stopTime = self.frame.getSensingStop() + datetime.timedelta(minutes=5)
        self.frame.setOrbit(dorParser.orbit.trimOrbit(startTime, stopTime))

    def _populateImage(self, outname, width, length):

        #farRange = self.frame.getStartingRange() + width*self.frame.getInstrument().getRangeSamplingRate()
        # Update the NumberOfSamples and NumberOfLines in the Frame object
        self.frame.setNumberOfSamples(width)
        self.frame.setNumberOfLines(length)
        #self.frame.setFarRange(farRange)
        # Create a RawImage object
        rawImage = createSlcImage()
        rawImage.setFilename(outname)
        rawImage.setAccessMode('read')
        rawImage.setByteOrder('l')
        rawImage.setXmin(0)
        rawImage.setXmax(width)
        rawImage.setWidth(width)
        self.frame.setImage(rawImage)

    def extractImage(self):
        from datetime import datetime as dt
        import tempfile as tf

        self.parse()
        width = self._imageryFileData['numSamples']
        length = self._imageryFileData['numLines']
        self._imageFile.extractImage(self.output, width, length)
        self._populateImage(self.output, width, length)

        pass

    def findOrbitFile(self):

        datefmt = '%Y%m%d%H%M%S'
        #        sensingStart = self.frame.getSensingStart()
        sensingStart = datetime.datetime.strptime(
            self._imageryFileData['FIRST_LINE_TIME'], '%d-%b-%Y %H:%M:%S.%f')
        outFile = None

        if self.orbitDir in [None, '']:
            raise Exception(
                'No Envisat Orbit File or Orbit Directory specified')

        try:
            for fname in os.listdir(self.orbitDir):
                if not os.path.isfile(os.path.join(self.orbitDir, fname)):
                    continue

                if not fname.startswith('DOR'):
                    continue

                fields = fname.split('_')
                procdate = datetime.datetime.strptime(
                    fields[-6][-8:] + fields[-5], datefmt)
                startdate = datetime.datetime.strptime(fields[-4] + fields[-3],
                                                       datefmt)
                enddate = datetime.datetime.strptime(fields[-2] + fields[-1],
                                                     datefmt)

                if (sensingStart > startdate) and (sensingStart < enddate):
                    outFile = os.path.join(self.orbitDir, fname)
                    break

        except:
            raise Exception(
                'Error occured when trying to find orbit file in %s' %
                (self.orbitDir))

        if not outFile:
            raise Exception('Envisat orbit file could not be found in %s' %
                            (self.orbitDir))

        self.orbitFile = outFile
        return

    def findInstrumentFile(self):

        datefmt = '%Y%m%d%H%M%S'

        sensingStart = datetime.datetime.strptime(
            self._imageryFileData['FIRST_LINE_TIME'], '%d-%b-%Y %H:%M:%S.%f')
        print('sens: ', sensingStart)
        outFile = None

        if self.instrumentDir in [None, '']:
            raise Exception(
                'No Envisat Instrument File or Instrument Directory specified')

        try:
            for fname in os.listdir(self.instrumentDir):
                if not os.path.isfile(os.path.join(self.instrumentDir, fname)):
                    continue

                if not fname.startswith('ASA_INS'):
                    continue

                fields = fname.split('_')
                procdate = datetime.datetime.strptime(
                    fields[-6][-8:] + fields[-5], datefmt)
                startdate = datetime.datetime.strptime(fields[-4] + fields[-3],
                                                       datefmt)
                enddate = datetime.datetime.strptime(fields[-2] + fields[-1],
                                                     datefmt)

                if (sensingStart > startdate) and (sensingStart < enddate):
                    outFile = os.path.join(self.instrumentDir, fname)
                    break

        except:
            raise Exception(
                'Error occured when trying to find instrument file in %s' %
                (self.instrumentDir))

        if not outFile:
            raise Exception(
                'Envisat instrument file could not be found in %s' %
                (self.instrumentDir))

        self.instrumentFile = outFile
        return

    def extractDoppler(self):
        """
        Return the doppler centroid as defined in the ASAR file.
        """
        quadratic = {}

        r0 = self.frame.getStartingRange()
        dr = self.frame.instrument.getRangePixelSize()
        width = self.frame.getNumberOfSamples()

        midr = r0 + (width / 2.0) * dr
        midtime = 2 * midr / Const.c - self.rangeRefTime

        fd_mid = 0.0
        tpow = midtime
        for kk in self.dopplerRangeTime:
            fd_mid += kk * tpow
            tpow *= midtime

        ####For insarApp
        quadratic['a'] = fd_mid / self.frame.getInstrument(
        ).getPulseRepetitionFrequency()
        quadratic['b'] = 0.
        quadratic['c'] = 0.

        ####For roiApp
        ####More accurate
        from isceobj.Util import Poly1D

        coeffs = self.dopplerRangeTime
        dr = self.frame.getInstrument().getRangePixelSize()
        rref = 0.5 * Const.c * self.rangeRefTime
        r0 = self.frame.getStartingRange()
        norm = 0.5 * Const.c / dr

        dcoeffs = []
        for ind, val in enumerate(coeffs):
            dcoeffs.append(val / (norm**ind))

        poly = Poly1D.Poly1D()
        poly.initPoly(order=len(coeffs) - 1)
        poly.setMean((rref - r0) / dr - 1.0)
        poly.setCoeffs(dcoeffs)

        pix = np.linspace(0,
                          self.frame.getNumberOfSamples(),
                          num=len(coeffs) + 1)
        evals = poly(pix)
        fit = np.polyfit(pix, evals, len(coeffs) - 1)
        self.frame._dopplerVsPixel = list(fit[::-1])
        print('Doppler Fit: ', fit[::-1])

        return quadratic
Пример #7
0
class ERS_EnviSAT_SLC(Sensor):

    parameter_list = (ORBIT_TYPE,
                      ORBIT_DIRECTORY,
                      ORBITFILE,
                      IMAGEFILE)           + Sensor.parameter_list

    """
        A Class for parsing ERS instrument and imagery files (Envisat format)
    """

    family = 'ers'
    logging_name = 'isce.sensor.ers_envisat_slc'

    def __init__(self,family='',name=''):
        super(ERS_EnviSAT_SLC, self).__init__(family if family else  self.__class__.family, name=name)
        self._imageFile = None
        #self._instrumentFileData = None #none for ERS
        self._imageryFileData = None
        self.dopplerRangeTime = None
        self.rangeRefTime = None
        self.logger = logging.getLogger("isce.sensor.ERS_EnviSAT_SLC")
        self.frame = None
        self.frameList = []

        #NOTE: copied from ERS_SLC.py... only antennaLength used? -SH
        # Constants are from
        # J. J. Mohr and S. N. Madsen. Geometric calibration of ERS satellite
        # SAR images. IEEE T. Geosci. Remote, 39(4):842-850, Apr. 2001.
        self.constants = {'polarization': 'VV',
                          'antennaLength': 10,
                          'lookDirection': 'RIGHT',
                          'chirpPulseBandwidth': 15.50829e6,
                          'rangeSamplingRate': 18.962468e6,
                          'delayTime':6.622e-6,
                          'iBias': 15.5,
                          'qBias': 15.5}


    def getFrame(self):
        return self.frame

    def parse(self):
        """
            Parse both imagery and create
            objects representing the platform, instrument and scene
        """

        self.frame = Frame()
        self.frame.configure()

        self._imageFile = ImageryFile(fileName=self._imageFileName)
        self._imageryFileData = self._imageFile.parse()

        self.populateMetadata()

    def populateMetadata(self):

        self._populatePlatform()
        self._populateInstrument()
        self._populateFrame()
        #self._populateOrbit()
        if (self._orbitType == 'ODR'):
            self._populateDelftOrbits()
        elif (self._orbitType == 'PRC'):
            self._populatePRCOrbits()
        elif (self._orbitType == 'PDS'):
            self._populatePDSOrbits()
        #else:
        #    self._populateHeaderOrbit() #NOTE: No leader file
        #NOTE: remove?
        self.dopplerRangeTime = self._imageryFileData['doppler']
        self.rangeRefTime = self._imageryFileData['dopplerOrigin'][0] * 1.0e-9
#        print('Doppler confidence: ', 100.0 * self._imageryFileData['dopplerConfidence'][0])

    def _populatePlatform(self):
        """Populate the platform object with metadata"""
        platform = self.frame.getInstrument().getPlatform()

        # Populate the Platform and Scene objects
        platform.setMission("ERS")
        platform.setPointingDirection(-1)
        platform.setAntennaLength(self.constants['antennaLength'])
        platform.setPlanet(Planet(pname="Earth"))

    def _populateInstrument(self):
        """Populate the instrument object with metadata"""
        instrument = self.frame.getInstrument()

        rangeSampleSpacing = Const.c/(2*self._imageryFileData['rangeSamplingRate'])
        pri = self._imageryFileData['pri']


        ####These shouldnt matter for SLC data since data is already focused.
        txPulseLength = 512 / 19207680.000000
        chirpPulseBandwidth = 16.0e6
        chirpSlope = chirpPulseBandwidth/txPulseLength

        instrument.setRangePixelSize(rangeSampleSpacing)
        instrument.setPulseLength(txPulseLength)
        #instrument.setSwath(imageryFileData['SWATH'])
        instrument.setRadarFrequency(self._imageryFileData['radarFrequency'])
        instrument.setChirpSlope(chirpSlope)
        instrument.setRangeSamplingRate(self._imageryFileData['rangeSamplingRate'])
        instrument.setPulseRepetitionFrequency(1.0/pri)
        #instrument.setRangeBias(rangeBias)
        instrument.setInPhaseValue(self.constants['iBias'])
        instrument.setQuadratureValue(self.constants['qBias'])

    def _populateFrame(self):
        """Populate the scene object with metadata"""
        numberOfLines = self._imageryFileData['numLines']
        numberOfSamples = self._imageryFileData['numSamples']
        pri = self._imageryFileData['pri']
        startingRange = Const.c * float(self._imageryFileData['timeToFirstSample']) * 1.0e-9 / 2.0
        rangeSampleSpacing = Const.c/(2*self._imageryFileData['rangeSamplingRate'])
        farRange = startingRange + numberOfSamples*rangeSampleSpacing
        first_line_utc = datetime.datetime.strptime(self._imageryFileData['FIRST_LINE_TIME'], '%d-%b-%Y %H:%M:%S.%f')
        center_line_utc = datetime.datetime.strptime(self._imageryFileData['FIRST_LINE_TIME'], '%d-%b-%Y %H:%M:%S.%f')
        last_line_utc = datetime.datetime.strptime(self._imageryFileData['LAST_LINE_TIME'], '%d-%b-%Y %H:%M:%S.%f')
        centerTime = DTUtil.timeDeltaToSeconds(last_line_utc-first_line_utc)/2.0
        center_line_utc = center_line_utc + datetime.timedelta(microseconds=int(centerTime*1e6))

        self.frame.setStartingRange(startingRange)
        self.frame.setFarRange(farRange)
        self.frame.setProcessingFacility(self._imageryFileData['PROC_CENTER'])
        self.frame.setProcessingSystem(self._imageryFileData['SOFTWARE_VER'])
        self.frame.setTrackNumber(int(self._imageryFileData['REL_ORBIT']))
        self.frame.setOrbitNumber(int(self._imageryFileData['ABS_ORBIT']))
        self.frame.setPolarization(self._imageryFileData['MDS1_TX_RX_POLAR'])
        self.frame.setNumberOfSamples(numberOfSamples)
        self.frame.setNumberOfLines(numberOfLines)
        self.frame.setSensingStart(first_line_utc)
        self.frame.setSensingMid(center_line_utc)
        self.frame.setSensingStop(last_line_utc)

    def _populateDelftOrbits(self):
        """Populate an orbit object with the Delft orbits"""
        from isceobj.Orbit.ODR import ODR, Arclist
        self.logger.info("Using Delft Orbits")
        arclist = Arclist(os.path.join(self._orbitDir,'arclist'))
        arclist.parse()
        print(self.frame.getSensingStart())
        print(arclist)
        orbitFile = arclist.getOrbitFile(self.frame.getSensingStart())
        #print(orbitFile)
        odr = ODR(file=os.path.join(self._orbitDir,orbitFile))


        startTimePreInterp = self.frame.getSensingStart() - datetime.timedelta(minutes=60)
        stopTimePreInterp = self.frame.getSensingStop() + datetime.timedelta(minutes=60)
        odr.parseHeader(startTimePreInterp,stopTimePreInterp)
        startTime = self.frame.getSensingStart() - datetime.timedelta(minutes=5)
        stopTime = self.frame.getSensingStop() + datetime.timedelta(minutes=5)
        self.logger.debug("Extracting orbits between %s and %s" % (startTime,stopTime))
        orbit = odr.trimOrbit(startTime,stopTime)
        self.frame.setOrbit(orbit)

    def _populatePRCOrbits(self):
        """Populate an orbit object the D-PAF PRC orbits"""
        from isceobj.Orbit.PRC import PRC, Arclist
        self.logger.info("Using PRC Orbits")
        arclist = Arclist(os.path.join(self._orbitDir,'arclist'))
        arclist.parse()
        orbitFile = arclist.getOrbitFile(self.frame.getSensingStart())
        self.logger.debug("Using file %s" % (orbitFile))
        prc = PRC(file=os.path.join(self._orbitDir,orbitFile))
        prc.parse()
        startTime = self.frame.getSensingStart() - datetime.timedelta(minutes=5)
        stopTime = self.frame.getSensingStop() + datetime.timedelta(minutes=5)
        self.logger.debug("Extracting orbits between %s and %s" % (startTime,stopTime))
        fullOrbit = prc.getOrbit()
        orbit = fullOrbit.trimOrbit(startTime,stopTime)
        self.frame.setOrbit(orbit)

    def _populatePDSOrbits(self):
        """
        Populate an orbit object using the ERS-2 PDS format
        """
        from isceobj.Orbit.PDS import PDS
        self.logger.info("Using PDS Orbits")
        pds = PDS(file=self._orbitFile)
        pds.parse()
        startTime = self.frame.getSensingStart() - datetime.timedelta(minutes=5)
        stopTime = self.frame.getSensingStop() + datetime.timedelta(minutes=5)
        self.logger.debug("Extracting orbits between %s and %s" % (startTime,stopTime))
        fullOrbit = pds.getOrbit()
        orbit = fullOrbit.trimOrbit(startTime,stopTime)
        self.frame.setOrbit(orbit)


    def _populateImage(self,outname,width,length):

        #farRange = self.frame.getStartingRange() + width*self.frame.getInstrument().getRangeSamplingRate()
        # Update the NumberOfSamples and NumberOfLines in the Frame object
        self.frame.setNumberOfSamples(width)
        self.frame.setNumberOfLines(length)
        #self.frame.setFarRange(farRange)
        # Create a RawImage object
        rawImage = createSlcImage()
        rawImage.setFilename(outname)
        rawImage.setAccessMode('read')
        rawImage.setByteOrder('l')
        rawImage.setXmin(0)
        rawImage.setXmax(width)
        rawImage.setWidth(width)
        self.frame.setImage(rawImage)

    def extractImage(self):
        from datetime import datetime as dt
        import tempfile as tf

        self.parse()
        width = self._imageryFileData['numSamples']
        length = self._imageryFileData['numLines']
        self._imageFile.extractImage(self.output, width, length)
        self._populateImage(self.output, width, length)

        pass



    def extractDoppler(self):
        """
        Return the doppler centroid as defined in the ASAR file.
        """
        quadratic = {}

        r0 = self.frame.getStartingRange()
        dr = self.frame.instrument.getRangePixelSize()
        width = self.frame.getNumberOfSamples()

        midr = r0 + (width/2.0) * dr
        midtime = 2 * midr/ Const.c - self.rangeRefTime

        fd_mid = 0.0
        tpow = midtime
        for kk in self.dopplerRangeTime:
            fd_mid += kk * tpow
            tpow *= midtime


        ####For insarApp
        quadratic['a'] = fd_mid/self.frame.getInstrument().getPulseRepetitionFrequency()
        quadratic['b'] = 0.
        quadratic['c'] = 0.

        
        ####For roiApp
        ####More accurate
        from isceobj.Util import Poly1D
        
        coeffs = self.dopplerRangeTime
        dr = self.frame.getInstrument().getRangePixelSize()
        rref = 0.5 * Const.c * self.rangeRefTime 
        r0 = self.frame.getStartingRange()
        norm = 0.5*Const.c/dr

        dcoeffs = []
        for ind, val in enumerate(coeffs):
            dcoeffs.append( val / (norm**ind))


        poly = Poly1D.Poly1D()
        poly.initPoly(order=len(coeffs)-1)
        poly.setMean( (rref - r0)/dr - 1.0)
        poly.setCoeffs(dcoeffs)


        pix = np.linspace(0, self.frame.getNumberOfSamples(), num=len(coeffs)+1)
        evals = poly(pix)
        fit = np.polyfit(pix,evals, len(coeffs)-1)
        self.frame._dopplerVsPixel = list(fit[::-1])
        print('Doppler Fit: ', fit[::-1])


        return quadratic
Пример #8
0
class KOMPSAT5(Component):
    """
    A class representing a Level1Product meta data.
    Level1Product(hdf5=h5filename) will parse the hdf5
    file and produce an object with attributes for metadata.
    """

    logging_name = 'isce.Sensor.KOMPSAT5'

    def __init__(self):
        super(KOMPSAT5,self).__init__()
        self.hdf5 = None
        self.output = None
        self.frame = Frame()
        self.frame.configure()
        # Some extra processing parameters unique to CSK SLC (currently)
        self.dopplerCoeffs = []
        self.rangeFirstTime = None
        self.rangeLastTime = None
        self.rangeRefTime = None
        self.refUTC = None
        
        self.descriptionOfVariables = {}
        self.dictionaryOfVariables = {'HDF5': ['self.hdf5','str','mandatory'],
                                      'OUTPUT': ['self.output','str','optional']}
        
        self.lookMap = {'RIGHT': -1,
                        'LEFT': 1}                            
        return

    def __getstate__(self):
        d = dict(self.__dict__)
        del d['logger']
        return d

    def __setstate__(self,d):
        self.__dict__.update(d)
        self.logger = logging.getLogger('isce.Sensor.COSMO_SkyMed_SLC')
        return

    
    def getFrame(self):
        return self.frame
    
    def parse(self):
        try:
            fp = h5py.File(self.hdf5,'r')
        except Exception as strerr:
            self.logger.error("IOError: %s" % strerr)
            return None

        self.populateMetadata(fp)
        fp.close()

    def populateMetadata(self, file):
        """
            Populate our Metadata objects
        """
        
        self._populatePlatform(file)
        self._populateInstrument(file)
        self._populateFrame(file)
        self._populateOrbit(file)
        self._populateExtras(file)
    
    def _populatePlatform(self, file):
        platform = self.frame.getInstrument().getPlatform()

        platform.setMission(file.attrs['Satellite ID'])
        platform.setPointingDirection(self.lookMap[file.attrs['Look Side'].decode('utf-8')])
        platform.setPlanet(Planet("Earth"))                            

        ####This is an approximation for spotlight mode
        ####In spotlight mode, antenna length changes with azimuth position
        platform.setAntennaLength(file.attrs['Antenna Length'])
        try:
            if file.attrs['Multi-Beam ID'].startswith('ES'):
                platform.setAntennaLength(16000.0/file['S01/SBI'].attrs['Line Time Interval'])
        except:
            pass
    
    def _populateInstrument(self, file):
        instrument = self.frame.getInstrument()

#        rangePixelSize = Const.c/(2*file['S01'].attrs['Sampling Rate'])  
        rangePixelSize = file['S01/SBI'].attrs['Column Spacing']
        instrument.setRadarWavelength(file.attrs['Radar Wavelength'])
#        instrument.setPulseRepetitionFrequency(file['S01'].attrs['PRF'])
        instrument.setPulseRepetitionFrequency(1.0/file['S01/SBI'].attrs['Line Time Interval'])
        instrument.setRangePixelSize(rangePixelSize)
        instrument.setPulseLength(file['S01'].attrs['Range Chirp Length'])        
        instrument.setChirpSlope(file['S01'].attrs['Range Chirp Rate'])                
#        instrument.setRangeSamplingRate(file['S01'].attrs['Sampling Rate'])
        instrument.setRangeSamplingRate(1.0/file['S01/SBI'].attrs['Column Time Interval'])

        incangle = 0.5*(file['S01/SBI'].attrs['Far Incidence Angle'] +
                 file['S01/SBI'].attrs['Near Incidence Angle'])
        instrument.setIncidenceAngle(incangle) 


    def _populateFrame(self, file):

        rft = file['S01/SBI'].attrs['Zero Doppler Range First Time']
        slantRange = rft*Const.c/2.0
        self.frame.setStartingRange(slantRange)
        
        referenceUTC = self._parseNanoSecondTimeStamp(file.attrs['Reference UTC'])
        relStart = file['S01/SBI'].attrs['Zero Doppler Azimuth First Time']
        relEnd = file['S01/SBI'].attrs['Zero Doppler Azimuth Last Time']
        relMid = 0.5*(relStart + relEnd)
        
        sensingStart = self._combineDateTime(referenceUTC, relStart) 
        sensingStop = self._combineDateTime(referenceUTC, relEnd)        
        sensingMid = self._combineDateTime(referenceUTC, relMid)           
        
        
        self.frame.setPassDirection(file.attrs['Orbit Direction'])
        self.frame.setOrbitNumber(file.attrs['Orbit Number'])              
        self.frame.setProcessingFacility(file.attrs['Processing Centre'])        
        self.frame.setProcessingSoftwareVersion(file.attrs['L0 Software Version'])
        self.frame.setPolarization(file['S01'].attrs['Polarisation'])
        self.frame.setNumberOfLines(file['S01/SBI'].shape[0])
        self.frame.setNumberOfSamples(file['S01/SBI'].shape[1])
        self.frame.setSensingStart(sensingStart)
        self.frame.setSensingMid(sensingMid)
        self.frame.setSensingStop(sensingStop)

        rangePixelSize = self.frame.getInstrument().getRangePixelSize()
        farRange = slantRange +  (self.frame.getNumberOfSamples()-1)*rangePixelSize
        self.frame.setFarRange(farRange)

    def _populateOrbit(self,file):
        orbit = self.frame.getOrbit()
        
        orbit.setReferenceFrame('ECR')
        orbit.setOrbitSource('Header')
        t0 = datetime.datetime.strptime(file.attrs['Reference UTC'].decode('utf-8'),'%Y-%m-%d %H:%M:%S.%f000')
        t = file.attrs['State Vectors Times']
        position = file.attrs['ECEF Satellite Position']
        velocity = file.attrs['ECEF Satellite Velocity']
                
        for i in range(len(position)):
            vec = StateVector()
            dt = t0 + datetime.timedelta(seconds=t[i])          
            vec.setTime(dt)            
            vec.setPosition([position[i,0],position[i,1],position[i,2]])
            vec.setVelocity([velocity[i,0],velocity[i,1],velocity[i,2]])
            orbit.addStateVector(vec)


    def _populateExtras(self, file):
        """
        Populate some of the extra fields unique to processing TSX data.
        In the future, other sensors may need this information as well, 
        and a re-organization may be necessary.
        """
        from isceobj.Doppler.Doppler import Doppler

        scale = file['S01'].attrs['PRF'] * file['S01/SBI'].attrs['Line Time Interval']
        self.dopplerCoeffs = file.attrs['Centroid vs Range Time Polynomial']*scale
        self.rangeRefTime = file.attrs['Range Polynomial Reference Time']
        self.rangeFirstTime = file['S01/SBI'].attrs['Zero Doppler Range First Time']
        self.rangeLastTime = file['S01/SBI'].attrs['Zero Doppler Range Last Time']

    def extractImage(self):
        import os
        from ctypes import cdll, c_char_p
        extract_csk = cdll.LoadLibrary(os.path.dirname(__file__)+'/csk.so')
        inFile_c = c_char_p(bytes(self.hdf5, 'utf-8'))
        outFile_c = c_char_p(bytes(self.output, 'utf-8'))

        extract_csk.extract_csk_slc(inFile_c, outFile_c)

        self.parse()
        slcImage = isceobj.createSlcImage()
        slcImage.setFilename(self.output)
        slcImage.setXmin(0)
        slcImage.setXmax(self.frame.getNumberOfSamples())
        slcImage.setWidth(self.frame.getNumberOfSamples())
        slcImage.setAccessMode('r')
        self.frame.setImage(slcImage)
       

    def _parseNanoSecondTimeStamp(self,timestamp):
        """
            Parse a date-time string with nanosecond precision and return a datetime object
        """
        dateTime,nanoSeconds = timestamp.decode('utf-8').split('.')
        microsec = float(nanoSeconds)*1e-3
        dt = datetime.datetime.strptime(dateTime,'%Y-%m-%d %H:%M:%S')
        dt = dt + datetime.timedelta(microseconds=microsec)
        return dt

    def _combineDateTime(self,dobj, secsstr):
        '''Takes the date from dobj and time from secs to spit out a date time object.
        '''
        sec = float(secsstr)
        dt = datetime.timedelta(seconds = sec)
        return dobj + dt
       

    def extractDoppler(self):
        """
        Return the doppler centroid as defined in the HDF5 file.
        """
        quadratic = {}
        midtime = (self.rangeLastTime + self.rangeFirstTime)*0.5 - self.rangeRefTime
        fd_mid = self.dopplerCoeffs[0] + self.dopplerCoeffs[1]*midtime + self.dopplerCoeffs[2]*midtime*midtime

        quadratic['a'] = fd_mid/self.frame.getInstrument().getPulseRepetitionFrequency()
        quadratic['b'] = 0.
        quadratic['c'] = 0.
        return quadratic
Пример #9
0
class JERS(Component):
    """
    Code to read CEOSFormat leader files for ERS-1/2 SAR data.
    The tables used to create this parser are based on document
    number ER-IS-EPO-GS-5902.1 from the European Space Agency.
    """

    #Parsers.CEOS.CEOSFormat.ceosTypes['text'] = {'typeCode': 63, 'subtypeCode': [18,18,18]}
    #Parsers.CEOS.CEOSFormat.ceosTypes['leaderFile'] = {'typeCode': 192, 'subtypeCode': [63,18,18]}
    #Parsers.CEOS.CEOSFormat.ceosTypes['dataSetSummary'] = {'typeCode': 10, 'subtypeCode': [10,31,20]}
    #Parsers.CEOS.CEOSFormat.ceosTypes['platformPositionData'] = {'typeCode': 30, 'subtypeCode': [10,31,20]}
    #Parsers.CEOS.CEOSFormat.ceosTypes['facilityData'] = {'typeCode': 200, 'subtypeCode': [10,31,50]}
    #Parsers.CEOS.CEOSFormat.ceosTypes['datafileDescriptor'] = {'typeCode': 192, 'subtypeCode':[63,18,18]}
    #Parsers.CEOS.CEOSFormat.ceosTypes['signalData'] = {'typeCode': 10, 'subtypeCode': [50,31,20]}
    #Parsers.CEOS.CEOSFormat.ceosTypes['nullFileDescriptor'] = {'typeCode': 192, 'subtypeCode': [192,63,18]}

    def __init__(self):
        Component.__init__(self)
        self._leaderFile = None
        self._imageFile = None
        self.output = None

        self.frame = Frame()
        self.frame.configure()

        self.constants = {'polarization': 'HH',
                          'antennaLength': 12}

        self.descriptionOfVariables = {}
        self.dictionaryOfVariables = {'LEADERFILE': ['self._leaderFile','str','mandatory'],
                                      'IMAGEFILE': ['self._imageFile','str','mandatory'],
                                      'OUTPUT': ['self.output','str','optional']}

    def getFrame(self):
        return self.frame

    def parse(self):
        self.leaderFile = LeaderFile(file=self._leaderFile)
        self.leaderFile.parse()

        self.imageFile = ImageFile(file=self._imageFile)
        self.imageFile.parse()

        self.populateMetadata()

    def populateMetadata(self):
        """
            Create the appropriate metadata objects from our CEOSFormat metadata
        """
        frame = self.leaderFile.sceneHeaderRecord.metadata['Scene reference number'].strip()
        frame = self._decodeSceneReferenceNumber(frame)
        rangePixelSize = Constants.SPEED_OF_LIGHT/(2*self.leaderFile.sceneHeaderRecord.metadata['Range sampling rate']*1e6)

        self.frame.getInstrument().getPlatform().setMission(self.leaderFile.sceneHeaderRecord.metadata['Sensor platform mission identifier'])
        self.frame.getInstrument().getPlatform().setPlanet(Planet(pname='Earth'))

        self.frame.getInstrument().setWavelength(self.leaderFile.sceneHeaderRecord.metadata['Radar wavelength'])
        self.frame.getInstrument().setIncidenceAngle(self.leaderFile.sceneHeaderRecord.metadata['Incidence angle at scene centre'])
        self.frame.getInstrument().setPulseRepetitionFrequency(self.leaderFile.sceneHeaderRecord.metadata['Pulse Repetition Frequency'])
        self.frame.getInstrument().setRangePixelSize(rangePixelSize)
        self.frame.getInstrument().setPulseLength(self.leaderFile.sceneHeaderRecord.metadata['Range pulse length']*1e-6)
        chirpPulseBandwidth = 15.50829e6 # Is this really not in the CEOSFormat Header?
        self.frame.getInstrument().setChirpSlope(chirpPulseBandwidth/(self.leaderFile.sceneHeaderRecord.metadata['Range pulse length']*1e-6))

        self.frame.setFrameNumber(frame)
        self.frame.setOrbitNumber(self.leaderFile.sceneHeaderRecord.metadata['Orbit number'])
        #self.frame.setStartingRange(self.leaderFile.facilityRecord.metadata['Slant range reference'])
        self.frame.setProcessingFacility(self.leaderFile.sceneHeaderRecord.metadata['Processing facility identifier'])
        self.frame.setProcessingSystem(self.leaderFile.sceneHeaderRecord.metadata['Processing system identifier'])
        self.frame.setProcessingSoftwareVersion(self.leaderFile.sceneHeaderRecord.metadata['Processing version identifier'])
        self.frame.setPolarization('HH')
        self.frame.setNumberOfLines(self.imageFile.imageFDR.metadata['Number of lines per data set'])
        self.frame.setNumberOfSamples(self.imageFile.imageFDR.metadata['Number of pixels per line per SAR channel'])


        self.frame.getOrbit().setOrbitSource('Header')
        t0 = datetime.datetime(year=self.leaderFile.platformPositionRecord.metadata['Year of data point'],
                               month=self.leaderFile.platformPositionRecord.metadata['Month of data point'],
                               day=self.leaderFile.platformPositionRecord.metadata['Day of data point'])
        t0 = t0 + datetime.timedelta(seconds=self.leaderFile.platformPositionRecord.metadata['Seconds of day'])
        for i in range(self.leaderFile.platformPositionRecord.metadata['Number of data points']):
            vec = StateVector()
            t = t0 + datetime.timedelta(seconds=(i*self.leaderFile.platformPositionRecord.metadata['Time interval between DATA points']))
            vec.setTime(t)
            dataPoints = self.leaderFile.platformPositionRecord.metadata['Positional Data Points'][i]
            vec.setPosition([dataPoints['Position vector X'], dataPoints['Position vector Y'], dataPoints['Position vector Z']])
            vec.setVelocity([dataPoints['Velocity vector X'], dataPoints['Velocity vector Y'], dataPoints['Velocity vector Z']])
            self.frame.getOrbit().addStateVector(vec)

    def extractImage(self):
        raise NotImplementedError()

    def _decodeSceneReferenceNumber(self,referenceNumber):
        return referenceNumber
Пример #10
0
class Radarsat1(Sensor):
    """
    Code to read CEOSFormat leader files for Radarsat-1 SAR data.
    The tables used to create this parser are based on document number
    ER-IS-EPO-GS-5902.1 from the European Space Agency.
    """
    family = 'radarsat1'
    logging_name = 'isce.sensor.radarsat1'

    parameter_list = (LEADERFILE, IMAGEFILE, PARFILE) + Sensor.parameter_list

    auxLength = 50

    @logged
    def __init__(self, name=''):
        super().__init__(family=self.__class__.family, name=name)
        self.imageFile = None
        self.leaderFile = None

        #####Soecific doppler functions for RSAT1
        self.doppler_ref_range = None
        self.doppler_ref_azi = None
        self.doppler_predict = None
        self.doppler_DAR = None
        self.doppler_coeff = None

        self.frame = Frame()
        self.frame.configure()

        self.constants = {'polarization': 'HH', 'antennaLength': 15}

    def getFrame(self):
        return self.frame

    def parse(self):
        self.leaderFile = LeaderFile(self, file=self._leaderFile)
        self.leaderFile.parse()

        self.imageFile = ImageFile(self, file=self._imageFile)
        self.imageFile.parse()

        self.populateMetadata()

        if self._parFile:
            self.parseParFile()
        else:
            self.populateCEOSOrbit()

    def populateMetadata(self):
        """
            Create the appropriate metadata objects from our CEOSFormat metadata
        """
        frame = self._decodeSceneReferenceNumber(
            self.leaderFile.sceneHeaderRecord.
            metadata['Scene reference number'])
        try:
            rangePixelSize = Const.c / (2 * self.leaderFile.sceneHeaderRecord.
                                        metadata['Range sampling rate'] * 1e6)
        except ZeroDivisionError:
            rangePixelSize = 0

        ins = self.frame.getInstrument()
        platform = ins.getPlatform()
        platform.setMission(self.leaderFile.sceneHeaderRecord.
                            metadata['Sensor platform mission identifier'])
        platform.setAntennaLength(self.constants['antennaLength'])
        platform.setPointingDirection(-1)
        platform.setPlanet(Planet(pname='Earth'))

        ins.setRadarWavelength(
            self.leaderFile.sceneHeaderRecord.metadata['Radar wavelength'])
        ins.setIncidenceAngle(self.leaderFile.sceneHeaderRecord.
                              metadata['Incidence angle at scene centre'])
        ##RSAT-1 does not have PRF for raw data in leader file.
        #        self.frame.getInstrument().setPulseRepetitionFrequency(self.leaderFile.sceneHeaderRecord.metadata['Pulse Repetition Frequency'])
        ins.setRangePixelSize(rangePixelSize)
        ins.setPulseLength(
            self.leaderFile.sceneHeaderRecord.metadata['Range pulse length'] *
            1e-6)
        chirpPulseBandwidth = 15.50829e6  # Is this really not in the CEOSFormat Header?
        ins.setChirpSlope(
            chirpPulseBandwidth /
            (self.leaderFile.sceneHeaderRecord.metadata['Range pulse length'] *
             1e-6))
        ins.setInPhaseValue(7.5)
        ins.setQuadratureValue(7.5)

        self.frame.setFrameNumber(frame)
        self.frame.setOrbitNumber(
            self.leaderFile.sceneHeaderRecord.metadata['Orbit number'])
        self.frame.setProcessingFacility(
            self.leaderFile.sceneHeaderRecord.
            metadata['Processing facility identifier'])
        self.frame.setProcessingSystem(
            self.leaderFile.sceneHeaderRecord.
            metadata['Processing system identifier'])
        self.frame.setProcessingSoftwareVersion(
            self.leaderFile.sceneHeaderRecord.
            metadata['Processing version identifier'])
        self.frame.setPolarization(self.constants['polarization'])
        self.frame.setNumberOfLines(
            self.imageFile.imageFDR.metadata['Number of lines per data set'])
        self.frame.setNumberOfSamples(
            self.imageFile.imageFDR.
            metadata['Number of pixels per line per SAR channel'])

        self.frame.getOrbit().setOrbitSource('Header')
        self.frame.getOrbit().setOrbitQuality(
            self.leaderFile.platformPositionRecord.
            metadata['Orbital elements designator'])

    def populateCEOSOrbit(self):
        from isceobj.Orbit.Inertial import ECI2ECR

        t0 = datetime.datetime(year=self.leaderFile.platformPositionRecord.
                               metadata['Year of data point'],
                               month=self.leaderFile.platformPositionRecord.
                               metadata['Month of data point'],
                               day=self.leaderFile.platformPositionRecord.
                               metadata['Day of data point'])
        t0 = t0 + datetime.timedelta(
            seconds=self.leaderFile.platformPositionRecord.
            metadata['Seconds of day'])

        #####Read in orbit in inertial coordinates
        orb = Orbit()
        for i in range(self.leaderFile.platformPositionRecord.
                       metadata['Number of data points']):
            vec = StateVector()
            t = t0 + datetime.timedelta(
                seconds=(i * self.leaderFile.platformPositionRecord.
                         metadata['Time interval between DATA points']))
            vec.setTime(t)
            dataPoints = self.leaderFile.platformPositionRecord.metadata[
                'Positional Data Points'][i]
            vec.setPosition([
                dataPoints['Position vector X'],
                dataPoints['Position vector Y'],
                dataPoints['Position vector Z']
            ])
            vec.setVelocity([
                dataPoints['Velocity vector X'] / 1000.,
                dataPoints['Velocity vector Y'] / 1000.,
                dataPoints['Velocity vector Z'] / 1000.
            ])
            orb.addStateVector(vec)

        #####Convert orbits from ECI to ECEF frame.
        t0 = orb._stateVectors[0]._time
        ang = self.leaderFile.platformPositionRecord.metadata[
            'Greenwich mean hour angle']

        cOrb = ECI2ECR(orb, GAST=ang, epoch=t0)
        wgsorb = cOrb.convert()

        orb = self.frame.getOrbit()

        for sv in wgsorb:
            orb.addStateVector(sv)
            print(sv)

    def extractImage(self):
        import isceobj
        if (self.imageFile is None) or (self.leaderFile is None):
            self.parse()

        try:
            out = open(self.output, 'wb')
        except IOError as strerr:
            self.logger.error("IOError: %s" % strerr)

        self.imageFile.extractImage(output=out)
        out.close()

        ####RSAT1 is weird. Contains all useful info in RAW data and not leader.
        ins = self.frame.getInstrument()
        ins.setPulseRepetitionFrequency(self.imageFile.prf)
        ins.setPulseLength(self.imageFile.pulseLength)
        ins.setRangeSamplingRate(self.imageFile.rangeSamplingRate)
        ins.setRangePixelSize(Const.c / (2 * self.imageFile.rangeSamplingRate))
        ins.setChirpSlope(self.imageFile.chirpSlope)

        ######
        self.frame.setSensingStart(self.imageFile.sensingStart)
        sensingStop = self.imageFile.sensingStart + datetime.timedelta(
            seconds=((self.frame.getNumberOfLines() - 1) / self.imageFile.prf))
        sensingMid = self.imageFile.sensingStart + datetime.timedelta(
            seconds=0.5 *
            (sensingStop - self.imageFile.sensingStart).total_seconds())
        self.frame.setSensingStop(sensingStop)
        self.frame.setSensingMid(sensingMid)
        self.frame.setNumberOfSamples(self.imageFile.width)
        self.frame.setStartingRange(self.imageFile.startingRange)
        farRange = self.imageFile.startingRange + ins.getRangePixelSize(
        ) * self.imageFile.width * 0.5
        self.frame.setFarRange(farRange)

        rawImage = isceobj.createRawImage()
        rawImage.setByteOrder('l')
        rawImage.setAccessMode('read')
        rawImage.setFilename(self.output)
        rawImage.setWidth(self.imageFile.width)
        rawImage.setXmin(0)
        rawImage.setXmax(self.imageFile.width)
        rawImage.renderHdr()
        self.frame.setImage(rawImage)

    def parseParFile(self):
        '''Parse the par file if any is available.'''
        if self._parFile not in (None, ''):
            par = ParFile(self._parFile)

            ####Update orbit
            svs = par['prep_block']['sensor']['ephemeris']['sv_block'][
                'state_vector']
            datefmt = '%Y%m%d%H%M%S%f'
            for entry in svs:
                sv = StateVector()
                sv.setPosition(
                    [float(entry['x']),
                     float(entry['y']),
                     float(entry['z'])])
                sv.setVelocity([
                    float(entry['xv']),
                    float(entry['yv']),
                    float(entry['zv'])
                ])
                sv.setTime(datetime.datetime.strptime(entry['Date'], datefmt))
                self.frame.orbit.addStateVector(sv)

            self.frame.orbit._stateVectors = sorted(
                self.frame.orbit._stateVectors, key=lambda x: x.getTime())

            doppinfo = par['prep_block']['sensor']['beam'][
                'DopplerCentroidParameters']
            #######Selectively update some values.
            #######Currently used only for doppler centroids.

            self.doppler_ref_range = float(doppinfo['reference_range'])
            self.doppler_ref_azi = datetime.datetime.strptime(
                doppinfo['reference_date'], '%Y%m%d%H%M%S%f')
            self.doppler_predict = float(doppinfo['Predict_doppler'])
            self.doppler_DAR = float(doppinfo['DAR_doppler'])

            coeff = doppinfo['doppler_centroid_coefficients']
            rngOrder = int(coeff['number_of_coefficients_first_dimension']) - 1
            azOrder = int(coeff['number_of_coefficients_second_dimension']) - 1

            self.doppler_coeff = Poly2D.Poly2D()
            self.doppler_coeff.initPoly(rangeOrder=rngOrder,
                                        azimuthOrder=azOrder)
            self.doppler_coeff.setMeanRange(self.doppler_ref_range)
            self.doppler_coeff.setMeanAzimuth(
                secondsSinceMidnight(self.doppler_ref_azi))

            parms = []
            for ii in range(azOrder + 1):
                row = []
                for jj in range(rngOrder + 1):
                    key = 'a%d%d' % (ii, jj)
                    val = float(coeff[key])
                    row.append(val)

                parms.append(row)

            self.doppler_coeff.setCoeffs(parms)

    def extractDoppler(self):
        '''
        Evaluate the doppler polynomial and return the average value for now.
        '''

        rmin = self.frame.getStartingRange()
        rmax = self.frame.getFarRange()
        rmid = 0.5 * (rmin + rmax)
        delr = Const.c / (2 * self.frame.instrument.rangeSamplingRate)

        azmid = secondsSinceMidnight(self.frame.getSensingMid())

        print(rmid, self.doppler_coeff.getMeanRange())
        print(azmid, self.doppler_coeff.getMeanAzimuth())

        if self.doppler_coeff is None:
            raise Exception(
                'ASF PARFILE was not provided. Cannot determine default doppler.'
            )

        dopav = self.doppler_coeff(azmid, rmid)
        prf = self.frame.getInstrument().getPulseRepetitionFrequency()
        quadratic = {}
        quadratic['a'] = dopav / prf
        quadratic['b'] = 0.
        quadratic['c'] = 0.

        ######Set up the doppler centroid computation just like CSK at mid azimuth
        order = self.doppler_coeff._rangeOrder
        rng = np.linspace(rmin, rmax, num=(order + 2))
        pix = (rng - rmin) / delr
        val = [self.doppler_coeff(azmid, x) for x in rng]

        print(rng, val)
        print(delr, pix)
        fit = np.polyfit(pix, val, order)
        self.frame._dopplerVsPixel = list(fit[::-1])
        #        self.frame._dopplerVsPixel = [dopav,0.,0.,0.]
        return quadratic

    def _decodeSceneReferenceNumber(self, referenceNumber):
        return referenceNumber
Пример #11
0
class Radarsat1(Component):
    """
        Code to read CEOSFormat leader files for Radarsat-1 SAR data.  The tables used to create
        this parser are based on document number ER-IS-EPO-GS-5902.1 from the European
        Space Agency.
    """
    auxLength = 50

    def __init__(self):
        Component.__init__(self)
        self._leaderFile = None
        self._imageFile = None
        self._parFile = None
        self.output = None
        self.imageFile = None
        self.leaderFile = None

        #####Soecific doppler functions for RSAT1
        self.doppler_ref_range = None
        self.doppler_ref_azi = None
        self.doppler_predict = None
        self.doppler_DAR = None
        self.doppler_coeff = None

        self.frame = Frame()
        self.frame.configure()

        self.constants = {'polarization': 'HH', 'antennaLength': 15}

        self.descriptionOfVariables = {}
        self.dictionaryOfVariables = {
            'LEADERFILE': ['self._leaderFile', 'str', 'mandatory'],
            'IMAGEFILE': ['self._imageFile', 'str', 'mandatory'],
            'PARFILE': ['self._parFile', 'str', 'optional'],
            'OUTPUT': ['self.output', 'str', 'optional']
        }

    def getFrame(self):
        return self.frame

    def parse(self):
        self.leaderFile = LeaderFile(self, file=self._leaderFile)
        self.leaderFile.parse()

        self.imageFile = ImageFile(self, file=self._imageFile)
        self.imageFile.parse()

        self.populateMetadata()

    def populateMetadata(self):
        """
            Create the appropriate metadata objects from our CEOSFormat metadata
        """
        frame = self._decodeSceneReferenceNumber(
            self.leaderFile.sceneHeaderRecord.
            metadata['Scene reference number'])
        try:
            rangePixelSize = Const.c / (2 * self.leaderFile.sceneHeaderRecord.
                                        metadata['Range sampling rate'] * 1e6)
        except ZeroDivisionError:
            rangePixelSize = 0

        ins = self.frame.getInstrument()
        platform = ins.getPlatform()
        platform.setMission(self.leaderFile.sceneHeaderRecord.
                            metadata['Sensor platform mission identifier'])
        platform.setAntennaLength(self.constants['antennaLength'])
        platform.setPointingDirection(-1)
        platform.setPlanet(Planet('Earth'))

        ins.setRadarWavelength(
            self.leaderFile.sceneHeaderRecord.metadata['Radar wavelength'])
        ins.setIncidenceAngle(self.leaderFile.sceneHeaderRecord.
                              metadata['Incidence angle at scene centre'])
        ##RSAT-1 does not have PRF for raw data in leader file.
        #        self.frame.getInstrument().setPulseRepetitionFrequency(self.leaderFile.sceneHeaderRecord.metadata['Pulse Repetition Frequency'])
        ins.setRangePixelSize(rangePixelSize)
        ins.setPulseLength(
            self.leaderFile.sceneHeaderRecord.metadata['Range pulse length'] *
            1e-6)
        chirpPulseBandwidth = 15.50829e6  # Is this really not in the CEOSFormat Header?
        ins.setChirpSlope(
            chirpPulseBandwidth /
            (self.leaderFile.sceneHeaderRecord.metadata['Range pulse length'] *
             1e-6))
        ins.setInPhaseValue(7.5)
        ins.setQuadratureValue(7.5)

        self.frame.setFrameNumber(frame)
        self.frame.setOrbitNumber(
            self.leaderFile.sceneHeaderRecord.metadata['Orbit number'])
        self.frame.setProcessingFacility(
            self.leaderFile.sceneHeaderRecord.
            metadata['Processing facility identifier'])
        self.frame.setProcessingSystem(
            self.leaderFile.sceneHeaderRecord.
            metadata['Processing system identifier'])
        self.frame.setProcessingSoftwareVersion(
            self.leaderFile.sceneHeaderRecord.
            metadata['Processing version identifier'])
        self.frame.setPolarization(self.constants['polarization'])
        self.frame.setNumberOfLines(
            self.imageFile.imageFDR.metadata['Number of lines per data set'])
        self.frame.setNumberOfSamples(
            self.imageFile.imageFDR.
            metadata['Number of pixels per line per SAR channel'])

        self.frame.getOrbit().setOrbitSource('Header')
        self.frame.getOrbit().setOrbitQuality(
            self.leaderFile.platformPositionRecord.
            metadata['Orbital elements designator'])
        t0 = datetime.datetime(year=self.leaderFile.platformPositionRecord.
                               metadata['Year of data point'],
                               month=self.leaderFile.platformPositionRecord.
                               metadata['Month of data point'],
                               day=self.leaderFile.platformPositionRecord.
                               metadata['Day of data point'])
        t0 = t0 + datetime.timedelta(
            seconds=self.leaderFile.platformPositionRecord.
            metadata['Seconds of day'])

        #####Read in orbit in inertial coordinates
        orb = Orbit()
        for i in range(self.leaderFile.platformPositionRecord.
                       metadata['Number of data points']):
            vec = StateVector()
            t = t0 + datetime.timedelta(
                seconds=(i * self.leaderFile.platformPositionRecord.
                         metadata['Time interval between DATA points']))
            vec.setTime(t)
            dataPoints = self.leaderFile.platformPositionRecord.metadata[
                'Positional Data Points'][i]
            vec.setPosition([
                dataPoints['Position vector X'],
                dataPoints['Position vector Y'],
                dataPoints['Position vector Z']
            ])
            vec.setVelocity([
                dataPoints['Velocity vector X'] / 1000.,
                dataPoints['Velocity vector Y'] / 1000.,
                dataPoints['Velocity vector Z'] / 1000.
            ])
            orb.addStateVector(vec)

        #####Convert orbits from ECI to ECEF frame.
        convOrb = ECI2ECEF(orb, eci='ECI_TOD')
        wgsorb = convOrb.convert()

        orb = self.frame.getOrbit()

        for sv in wgsorb:
            orb.addStateVector(sv)

        self.parseParFile()

    def extractImage(self):
        import isceobj
        if (self.imageFile is None) or (self.leaderFile is None):
            self.parse()

        try:
            out = open(self.output, 'wb')
        except IOError as strerr:
            self.logger.error("IOError: %s" % strerr)

        self.imageFile.extractImage(output=out)
        out.close()

        ####RSAT1 is weird. Contains all useful info in RAW data and not leader.
        ins = self.frame.getInstrument()
        ins.setPulseRepetitionFrequency(self.imageFile.prf)
        ins.setPulseLength(self.imageFile.pulseLength)
        ins.setRangeSamplingRate(self.imageFile.rangeSamplingRate)
        ins.setRangePixelSize(Const.c / (2 * self.imageFile.rangeSamplingRate))
        ins.setChirpSlope(self.imageFile.chirpSlope)

        ######
        self.frame.setSensingStart(self.imageFile.sensingStart)
        sensingStop = self.imageFile.sensingStart + datetime.timedelta(
            seconds=((self.frame.getNumberOfLines() - 1) / self.imageFile.prf))
        sensingMid = self.imageFile.sensingStart + datetime.timedelta(
            seconds=0.5 *
            (sensingStop - self.imageFile.sensingStart).total_seconds())
        self.frame.setSensingStop(sensingStop)
        self.frame.setSensingMid(sensingMid)
        self.frame.setNumberOfSamples(self.imageFile.width)
        self.frame.setStartingRange(self.imageFile.startingRange)
        farRange = self.imageFile.startingRange + ins.getRangePixelSize(
        ) * self.imageFile.width * 0.5
        self.frame.setFarRange(farRange)

        rawImage = isceobj.createRawImage()
        rawImage.setByteOrder('l')
        rawImage.setAccessMode('read')
        rawImage.setFilename(self.output)
        rawImage.setWidth(self.imageFile.width)
        rawImage.setXmin(0)
        rawImage.setXmax(self.imageFile.width)
        rawImage.renderHdr()
        self.frame.setImage(rawImage)

    def parseParFile(self):
        '''Parse the par file if any is available.'''
        if self._parFile not in (None, ''):
            par = ParFile(self._parFile)

            doppinfo = par['prep_block']['sensor']['beam'][
                'DopplerCentroidParameters']
            #######Selectively update some values.
            #######Currently used only for doppler centroids.

            self.doppler_ref_range = float(doppinfo['reference_range'])
            self.doppler_ref_azi = datetime.datetime.strptime(
                doppinfo['reference_date'], '%Y%m%d%H%M%S%f')
            self.doppler_predict = float(doppinfo['Predict_doppler'])
            self.doppler_DAR = float(doppinfo['DAR_doppler'])

            coeff = doppinfo['doppler_centroid_coefficients']
            rngOrder = int(coeff['number_of_coefficients_first_dimension'])
            azOrder = int(coeff['number_of_coefficients_second_dimension'])

            self.doppler_coeff = Polynomial(rangeOrder=rngOrder,
                                            azimuthOrder=azOrder)
            self.doppler_coeff.setMeanRange(self.doppler_ref_range)
            self.doppler_coeff.setMeanAzimuth(
                secondsSinceMidnight(self.doppler_ref_azi))

            for ii in range(azOrder):
                for jj in range(rngOrder):
                    key = 'a%d%d' % (ii, jj)
                    val = float(coeff[key])
                    self.doppler_coeff.setCoeff(ii, jj, val)

    def extractDoppler(self):
        '''
        Evaluate the doppler polynomial and return the average value for now.
        '''

        rmin = self.frame.getStartingRange()
        rmax = self.frame.getFarRange()
        rmid = 0.5 * (rmin + rmax)

        azmid = secondsSinceMidnight(self.frame.getSensingMid())

        print(rmid, self.doppler_coeff.getMeanRange())
        print(azmid, self.doppler_coeff.getMeanAzimuth())

        if self.doppler_coeff is None:
            raise Exception(
                'ASF PARFILE was not provided. Cannot determine default doppler.'
            )

        dopav = self.doppler_coeff(azmid, rmid)
        prf = self.frame.getInstrument().getPulseRepetitionFrequency()
        quadratic = {}
        quadratic['a'] = dopav / prf
        quadratic['b'] = 0.
        quadratic['c'] = 0.
        return quadratic

    def _decodeSceneReferenceNumber(self, referenceNumber):
        return referenceNumber
Пример #12
0
class ALOS_SLC(Sensor):
    """
        Code to read CEOSFormat leader files for ALOS SLC data.
    """

    parameter_list = (WAVELENGTH,
                      LEADERFILE,
                      IMAGEFILE) + Sensor.parameter_list
    family = 'alos_slc'
    logging_name = 'isce.sensor.ALOS_SLC'

    #Orbital Elements (Quality) Designator
    #ALOS-2/PALSAR-2 Level 1.1/1.5/2.1/3.1 CEOS SAR Product Format Description
    #PALSAR-2_xx_Format_CEOS_E_r.pdf
    orbitElementsDesignator = {'0': 'preliminary',
                               '1': 'decision',
                               '2': 'high precision'}

    def __init__(self, name=''):
        super().__init__(family=self.__class__.family, name=name)
        self.imageFile = None
        self.leaderFile = None

        # Specific doppler functions for ALOS
        self.doppler_coeff = None
        self.azfmrate_coeff = None
        self.lineDirection = None
        self.pixelDirection = None

        self.frame = Frame()
        self.frame.configure()

        self.constants = {'antennaLength': 15}

    def getFrame(self):
        return self.frame

    def parse(self):
        self.leaderFile = LeaderFile(self, file=self._leaderFile)
        self.leaderFile.parse()

        self.imageFile = ImageFile(self, file=self._imageFile)
        self.imageFile.parse()
        self.populateMetadata()
        self._populateExtras()

    def populateMetadata(self):
        """
            Create the appropriate metadata objects from our CEOSFormat metadata
        """
        frame = self._decodeSceneReferenceNumber(self.leaderFile.sceneHeaderRecord.metadata['Scene reference number'])

        fsamplookup = self.leaderFile.sceneHeaderRecord.metadata['Range sampling rate in MHz']*1.0e6

        rangePixelSize = Const.c/(2*fsamplookup)

        ins = self.frame.getInstrument()
        platform = ins.getPlatform()
        platform.setMission(self.leaderFile.sceneHeaderRecord.metadata['Sensor platform mission identifier'])
        platform.setAntennaLength(self.constants['antennaLength'])
        platform.setPointingDirection(1)
        platform.setPlanet(Planet(pname='Earth'))

        if self.wavelength:
            ins.setRadarWavelength(float(self.wavelength))
        else:
            ins.setRadarWavelength(self.leaderFile.sceneHeaderRecord.metadata['Radar wavelength'])

        ins.setIncidenceAngle(self.leaderFile.sceneHeaderRecord.metadata['Incidence angle at scene centre'])
        self.frame.getInstrument().setPulseRepetitionFrequency(self.leaderFile.sceneHeaderRecord.metadata['Pulse Repetition Frequency in mHz']*1.0e-3)
        ins.setRangePixelSize(rangePixelSize)
        ins.setRangeSamplingRate(fsamplookup)
        ins.setPulseLength(self.leaderFile.sceneHeaderRecord.metadata['Range pulse length in microsec']*1.0e-6)
        chirpSlope = self.leaderFile.sceneHeaderRecord.metadata['Nominal range pulse (chirp) amplitude coefficient linear term']
        chirpPulseBandwidth = abs(chirpSlope * self.leaderFile.sceneHeaderRecord.metadata['Range pulse length in microsec']*1.0e-6)
        ins.setChirpSlope(chirpSlope)
        ins.setInPhaseValue(7.5)
        ins.setQuadratureValue(7.5)

        self.lineDirection = self.leaderFile.sceneHeaderRecord.metadata['Time direction indicator along line direction'].strip()
        self.pixelDirection =  self.leaderFile.sceneHeaderRecord.metadata['Time direction indicator along pixel direction'].strip()

        ######ALOS includes this information in clock angle
        clockAngle = self.leaderFile.sceneHeaderRecord.metadata['Sensor clock angle']
        if clockAngle == 90.0:
            platform.setPointingDirection(-1)
        elif clockAngle == -90.0:
            platform.setPointingDirection(1)
        else:
            raise Exception('Unknown look side. Clock Angle = {0}'.format(clockAngle))

        self.frame.setFrameNumber(frame)
        self.frame.setOrbitNumber(self.leaderFile.sceneHeaderRecord.metadata['Orbit number'])
        self.frame.setProcessingFacility(self.leaderFile.sceneHeaderRecord.metadata['Processing facility identifier'])
        self.frame.setProcessingSystem(self.leaderFile.sceneHeaderRecord.metadata['Processing system identifier'])
        self.frame.setProcessingSoftwareVersion(self.leaderFile.sceneHeaderRecord.metadata['Processing version identifier'])
        self.frame.setNumberOfLines(self.imageFile.imageFDR.metadata['Number of lines per data set'])
        self.frame.setNumberOfSamples(self.imageFile.imageFDR.metadata['Number of pixels per line per SAR channel'])
        self.frame.instrument.setAzimuthPixelSize(self.leaderFile.dataQualitySummaryRecord.metadata['Azimuth resolution'])
        
        ######
        orb = self.frame.getOrbit()

        orb.setOrbitSource('Header')
        orb.setOrbitQuality(
            self.orbitElementsDesignator[
                self.leaderFile.platformPositionRecord.metadata['Orbital elements designator']
            ]
        )
        t0 = datetime.datetime(year=self.leaderFile.platformPositionRecord.metadata['Year of data point'],
                               month=self.leaderFile.platformPositionRecord.metadata['Month of data point'],
                               day=self.leaderFile.platformPositionRecord.metadata['Day of data point'])
        t0 = t0 + datetime.timedelta(seconds=self.leaderFile.platformPositionRecord.metadata['Seconds of day'])

        #####Read in orbit in inertial coordinates
        deltaT = self.leaderFile.platformPositionRecord.metadata['Time interval between data points']
        numPts = self.leaderFile.platformPositionRecord.metadata['Number of data points']


        orb = self.frame.getOrbit()
        for i in range(numPts):
            vec = StateVector()
            t = t0 + datetime.timedelta(seconds=i*deltaT)
            vec.setTime(t)

            dataPoints = self.leaderFile.platformPositionRecord.metadata['Positional Data Points'][i]
            pos = [dataPoints['Position vector X'], dataPoints['Position vector Y'], dataPoints['Position vector Z']]
            vel = [dataPoints['Velocity vector X'], dataPoints['Velocity vector Y'], dataPoints['Velocity vector Z']]
            vec.setPosition(pos)
            vec.setVelocity(vel)
            orb.addStateVector(vec)


        self.doppler_coeff = [self.leaderFile.sceneHeaderRecord.metadata['Cross track Doppler frequency centroid constant term'],
        self.leaderFile.sceneHeaderRecord.metadata['Cross track Doppler frequency centroid linear term'],
        self.leaderFile.sceneHeaderRecord.metadata['Cross track Doppler frequency centroid quadratic term']]


        self.azfmrate_coeff =  [self.leaderFile.sceneHeaderRecord.metadata['Cross track Doppler frequency rate constant term'],
        self.leaderFile.sceneHeaderRecord.metadata['Cross track Doppler frequency rate linear term'],
        self.leaderFile.sceneHeaderRecord.metadata['Cross track Doppler frequency rate quadratic term']]

    def _populateExtras(self):
        dataset = self.leaderFile.radiometricRecord.metadata
        print("Record Number: %d" % (dataset["Record Number"]))
        print("First Record Subtype: %d" % (dataset["First Record Subtype"]))
        print("Record Type Code: %d" % (dataset["Record Type Code"]))
        print("Second Record Subtype: %d" % (dataset["Second Record Subtype"]))
        print("Third Record Subtype: %d" % (dataset["Third Record Subtype"]))
        print("Record Length: %d" % (dataset["Record Length"]))
        print("SAR channel indicator: %d" % (dataset["SAR channel indicator"]))
        print("Number of data sets: %d" % (dataset["Number of data sets"]))
        numPts = dataset['Number of data sets']
        for i in range(numPts):
            if i > 1:
                break
            print('Radiometric record field: %d' % (i+1))
            dataset = self.leaderFile.radiometricRecord.metadata[
                'Radiometric data sets'][i]
            DT11 = complex(dataset['Real part of DT 1,1'],
                           dataset['Imaginary part of DT 1,1'])
            DT12 = complex(dataset['Real part of DT 1,2'],
                           dataset['Imaginary part of DT 1,2'])
            DT21 = complex(dataset['Real part of DT 2,1'],
                           dataset['Imaginary part of DT 2,1'])
            DT22 = complex(dataset['Real part of DT 2,2'],
                           dataset['Imaginary part of DT 2,2'])
            DR11 = complex(dataset['Real part of DR 1,1'],
                           dataset['Imaginary part of DR 1,1'])
            DR12 = complex(dataset['Real part of DR 1,2'],
                           dataset['Imaginary part of DR 1,2'])
            DR21 = complex(dataset['Real part of DR 2,1'],
                           dataset['Imaginary part of DR 2,1'])
            DR22 = complex(dataset['Real part of DR 2,2'],
                           dataset['Imaginary part of DR 2,2'])
            print("Calibration factor [dB]: %f" %
                  (dataset["Calibration factor"]))
            print('Distortion matrix Trasmission [DT11, DT12, DT21, DT22]: '
                  '[%s, %s, %s, %s]' %
                  (str(DT11), str(DT12), str(DT21), str(DT22)))
            print('Distortion matrix Reception [DR11, DR12, DR21, DR22]: '
                  '[%s, %s, %s, %s]' %
                  (str(DR11), str(DR12), str(DR21), str(DR22)))
            self.transmit = Distortion(DT12, DT21, DT22)
            self.receive = Distortion(DR12, DR21, DR22)
            self.calibrationFactor = float(
                dataset['Calibration factor'])

    def extractImage(self):
        import isceobj
        if (self.imageFile is None) or (self.leaderFile is None):
            self.parse()

        try:
            out = open(self.output, 'wb')
        except IOError as strerr:
            self.logger.error("IOError: %s" % strerr)

        self.imageFile.extractImage(output=out)
        out.close()

        self.frame.setSensingStart(self.imageFile.sensingStart)
        self.frame.setSensingStop(self.imageFile.sensingStop)
        sensingMid = self.imageFile.sensingStart + datetime.timedelta(seconds = 0.5* (self.imageFile.sensingStop - self.imageFile.sensingStart).total_seconds())
        self.frame.setSensingMid(sensingMid)

        try:
            rngGate=  Const.c*0.5*self.leaderFile.sceneHeaderRecord.metadata['Range gate delay in microsec']*1e-6
        except:
            rngGate = None

        if (rngGate is None) or (rngGate == 0.0):
            rngGate = self.imageFile.nearRange

        self.frame.setStartingRange(rngGate)

        self.frame.getInstrument().setPulseRepetitionFrequency(self.imageFile.prf)

        pixelSize = self.frame.getInstrument().getRangePixelSize()
        farRange = self.imageFile.nearRange + (pixelSize-1) * self.imageFile.width
        self.frame.setFarRange(farRange)
        self.frame.setPolarization(self.imageFile.current_polarization)
        
        rawImage = isceobj.createSlcImage()
        rawImage.setByteOrder('l')
        rawImage.setAccessMode('read')
        rawImage.setFilename(self.output)
        rawImage.setWidth(self.imageFile.width)
        rawImage.setXmin(0)
        rawImage.setXmax(self.imageFile.width)
        rawImage.renderHdr()
        self.frame.setImage(rawImage)

        return


    def extractDoppler(self):
        '''
        Evaluate the doppler polynomial and return the average value for now.
        '''
        midwidth = self.frame.getNumberOfSamples() / 2.0
        dop = 0.0
        prod = 1.0
        for ind, kk in enumerate(self.doppler_coeff):
            dop += kk * prod
            prod *= midwidth

        print ('Average Doppler: {0}'.format(dop))

        ####For insarApp
        quadratic = {}
        quadratic['a'] = dop / self.frame.getInstrument().getPulseRepetitionFrequency()
        quadratic['b'] = 0.
        quadratic['c'] = 0.


        ####For roiApp
        ####More accurate
        ####CEOS already provides function vs pixel
        self.frame._dopplerVsPixel = self.doppler_coeff
        return quadratic

    def _decodeSceneReferenceNumber(self,referenceNumber):
        return referenceNumber
Пример #13
0
class ERS_SLC(Sensor):

    family = 'ers_slc'
    logging_name = 'isce.sensor.ers_slc'

    parameter_list = (IMAGEFILE,
                      LEADERFILE,
                      ORBIT_TYPE,
                      ORBIT_DIRECTORY,
                      ORBIT_FILE)      + Sensor.parameter_list

    @logged
    def __init__(self, name=''):
        super().__init__(family=self.__class__.family, name=name)

        self.frame = Frame()
        self.frame.configure()
        self.dopplerRangeTime = None

        # Constants are from
        # J. J. Mohr and S. N. Madsen. Geometric calibration of ERS satellite
        # SAR images. IEEE T. Geosci. Remote, 39(4):842-850, Apr. 2001.
        self.constants = {'polarization': 'VV',
                          'antennaLength': 10,
                          'lookDirection': 'RIGHT',
                          'chirpPulseBandwidth': 15.50829e6,
                          'rangeSamplingRate': 18.962468e6,
                          'delayTime':6.622e-6,
                          'iBias': 15.5,
                          'qBias': 15.5}
        return None

    def getFrame(self):
        return self.frame

    def parse(self):
        self.leaderFile = LeaderFile(file=self._leaderFile)
        self.leaderFile.parse()

        self.imageFile = ImageFile(self)
        self.imageFile.parse()

        self.populateMetadata()

    def populateMetadata(self):
        """
        Create the appropriate metadata objects from our CEOSFormat metadata
        """

        self._populatePlatform()
        self._populateInstrument()
        self._populateFrame()
        if (self._orbitType == 'ODR'):
            self._populateDelftOrbits()
        elif (self._orbitType == 'PRC'):
            self._populatePRCOrbits()
        elif (self._orbitType == 'PDS'):
            self._populatePDSOrbits()
        else:
            self._populateHeaderOrbit()

        self._populateDoppler()

    def _populatePlatform(self):
        """
        Populate the platform object with metadata
        """

        platform = self.frame.getInstrument().getPlatform()

        platform.setMission(self.leaderFile.sceneHeaderRecord.metadata[
            'Sensor platform mission identifier'])
        platform.setAntennaLength(self.constants['antennaLength'])
        platform.setPointingDirection(-1)
        platform.setPlanet(Planet(pname='Earth'))

    def _populateInstrument(self):
        """Populate the instrument object with metadata"""
        instrument = self.frame.getInstrument()
        prf = self.leaderFile.sceneHeaderRecord.metadata['Pulse Repetition Frequency']
        rangeSamplingRate = self.leaderFile.sceneHeaderRecord.metadata['Range sampling rate']*1.0e6
        rangePixelSize = Const.c/(2.0*rangeSamplingRate)

        instrument.setRadarWavelength(
            self.leaderFile.sceneHeaderRecord.metadata['Radar wavelength'])
        instrument.setIncidenceAngle(
            self.leaderFile.sceneHeaderRecord.metadata[
            'Incidence angle at scene centre'])
        instrument.setPulseRepetitionFrequency(prf)
        instrument.setRangeSamplingRate(rangeSamplingRate)
        instrument.setRangePixelSize(rangePixelSize)
        instrument.setPulseLength(self.leaderFile.sceneHeaderRecord.metadata[
            'Range pulse length']*1e-6)
        instrument.setChirpSlope(self.constants['chirpPulseBandwidth']/
            (self.leaderFile.sceneHeaderRecord.metadata['Range pulse length']*
             1e-6))
        instrument.setInPhaseValue(self.constants['iBias'])
        instrument.setQuadratureValue(self.constants['qBias'])

    def _populateFrame(self):
        """Populate the scene object with metadata"""
        rangeSamplingRate = self.constants['rangeSamplingRate']
        rangePixelSize = Const.c/(2.0*rangeSamplingRate)
        pulseInterval = 1.0/self.frame.getInstrument().getPulseRepetitionFrequency()
        frame = self._decodeSceneReferenceNumber(
            self.leaderFile.sceneHeaderRecord.metadata[
            'Scene reference number'])

        prf = self.frame.instrument.getPulseRepetitionFrequency()
        tau0 = self.leaderFile.sceneHeaderRecord.metadata['Zero-doppler range time of first range pixel']*1.0e-3
        startingRange = tau0*Const.c/2.0
        farRange = startingRange + self.imageFile.width*rangePixelSize


        first_line_utc = datetime.datetime.strptime(self.leaderFile.sceneHeaderRecord.metadata['Zero-doppler azimuth time of first azimuth pixel'], "%d-%b-%Y %H:%M:%S.%f")
        mid_line_utc = first_line_utc + datetime.timedelta(seconds = (self.imageFile.length-1) * 0.5 / prf)

        last_line_utc = first_line_utc + datetime.timedelta(seconds = (self.imageFile.length-1)/prf)

        self.logger.debug("Frame UTC start, mid, end times:  %s %s %s" % (first_line_utc,mid_line_utc,last_line_utc))

        self.frame.setFrameNumber(frame)
        self.frame.setOrbitNumber(self.leaderFile.sceneHeaderRecord.metadata['Orbit number'])
        self.frame.setStartingRange(startingRange)
        self.frame.setFarRange(farRange)
        self.frame.setProcessingFacility(self.leaderFile.sceneHeaderRecord.metadata['Processing facility identifier'])
        self.frame.setProcessingSystem(self.leaderFile.sceneHeaderRecord.metadata['Processing system identifier'])
        self.frame.setProcessingSoftwareVersion(self.leaderFile.sceneHeaderRecord.metadata['Processing version identifier'])
        self.frame.setPolarization(self.constants['polarization'])
        self.frame.setNumberOfLines(self.imageFile.length)
        self.frame.setNumberOfSamples(self.imageFile.width)
        self.frame.setSensingStart(first_line_utc)
        self.frame.setSensingMid(mid_line_utc)
        self.frame.setSensingStop(last_line_utc)

    def _populateHeaderOrbit(self):
        """Populate an orbit object with the header orbits"""
        self.logger.info("Using Header Orbits")
        orbit = self.frame.getOrbit()

        orbit.setOrbitSource('Header')
        orbit.setOrbitQuality('Unknown')
        t0 = datetime.datetime(year=self.leaderFile.platformPositionRecord.metadata['Year of data point'],
                               month=self.leaderFile.platformPositionRecord.metadata['Month of data point'],
                               day=self.leaderFile.platformPositionRecord.metadata['Day of data point'])
        t0 = t0 + datetime.timedelta(microseconds=self.leaderFile.platformPositionRecord.metadata['Seconds of day']*1e6)
        for i in range(self.leaderFile.platformPositionRecord.metadata['Number of data points']):
            vec = StateVector()
            deltaT = self.leaderFile.platformPositionRecord.metadata['Time interval between DATA points']
            t = t0 + datetime.timedelta(microseconds=i*deltaT*1e6)
            vec.setTime(t)
            dataPoints = self.leaderFile.platformPositionRecord.metadata['Positional Data Points'][i]
            vec.setPosition([dataPoints['Position vector X'], dataPoints['Position vector Y'], dataPoints['Position vector Z']])
            vec.setVelocity([dataPoints['Velocity vector X'], dataPoints['Velocity vector Y'], dataPoints['Velocity vector Z']])
            orbit.addStateVector(vec)

    def _populateDelftOrbits(self):
        """Populate an orbit object with the Delft orbits"""
        from isceobj.Orbit.ODR import ODR, Arclist
        self.logger.info("Using Delft Orbits")
        arclist = Arclist(os.path.join(self._orbitDir,'arclist'))
        arclist.parse()
        orbitFile = arclist.getOrbitFile(self.frame.getSensingStart())
        odr = ODR(file=os.path.join(self._orbitDir,orbitFile))


        startTimePreInterp = self.frame.getSensingStart() - datetime.timedelta(minutes=60)
        stopTimePreInterp = self.frame.getSensingStop() + datetime.timedelta(minutes=60)
        odr.parseHeader(startTimePreInterp,stopTimePreInterp)
        startTime = self.frame.getSensingStart() - datetime.timedelta(minutes=5)
        stopTime = self.frame.getSensingStop() + datetime.timedelta(minutes=5)
        self.logger.debug("Extracting orbits between %s and %s" % (startTime,stopTime))
        orbit = odr.trimOrbit(startTime,stopTime)
        self.frame.setOrbit(orbit)

    def _populatePRCOrbits(self):
        """Populate an orbit object the D-PAF PRC orbits"""
        from isceobj.Orbit.PRC import PRC, Arclist
        self.logger.info("Using PRC Orbits")
        arclist = Arclist(os.path.join(self._orbitDir,'arclist'))
        arclist.parse()
        orbitFile = arclist.getOrbitFile(self.frame.getSensingStart())
        self.logger.debug("Using file %s" % (orbitFile))
        prc = PRC(file=os.path.join(self._orbitDir,orbitFile))
        prc.parse()
        startTime = self.frame.getSensingStart() - datetime.timedelta(minutes=5)
        stopTime = self.frame.getSensingStop() + datetime.timedelta(minutes=5)
        self.logger.debug("Extracting orbits between %s and %s" % (startTime,stopTime))
        fullOrbit = prc.getOrbit()
        orbit = fullOrbit.trimOrbit(startTime,stopTime)
        self.frame.setOrbit(orbit)

    def _populatePDSOrbits(self):
        """
        Populate an orbit object using the ERS-2 PDS format
        """
        from isceobj.Orbit.PDS import PDS
        self.logger.info("Using PDS Orbits")
        pds = PDS(file=self._orbitFile)
        pds.parse()
        startTime = self.frame.getSensingStart() - datetime.timedelta(minutes=5)
        stopTime = self.frame.getSensingStop() + datetime.timedelta(minutes=5)
        self.logger.debug("Extracting orbits between %s and %s" % (startTime,stopTime))
        fullOrbit = pds.getOrbit()
        orbit = fullOrbit.trimOrbit(startTime,stopTime)
        self.frame.setOrbit(orbit)

    def _populateDoppler(self):
        '''
        Extract doppler from the CEOS file.
        '''

        prf = self.frame.instrument.getPulseRepetitionFrequency()

        #####ERS provides doppler as a function of slant range time in seconds
        d0 = self.leaderFile.sceneHeaderRecord.metadata['Cross track Doppler frequency centroid constant term']

        d1 = self.leaderFile.sceneHeaderRecord.metadata['Cross track Doppler frequency centroid linear term']

        d2 = self.leaderFile.sceneHeaderRecord.metadata['Cross track Doppler frequency centroid quadratic term']

        self.dopplerRangeTime = [d0, d1, d2]

        return

    def extractDoppler(self):

        width = self.frame.getNumberOfSamples()
        prf = self.frame.instrument.getPulseRepetitionFrequency()

        midtime = 0.5*width/self.frame.instrument.getRangeSamplingRate() 

        fd_mid = 0.0
        x = 1.0
        for ind, coeff in enumerate(self.dopplerRangeTime):
            fd_mid += coeff * x
            x *= midtime

        ####For insarApp
        quadratic = {}
        quadratic['a'] = fd_mid / prf
        quadratic['b'] = 0.0
        quadratic['c'] = 0.0


        ###For roiApp more accurate
        ####Convert stuff to pixel wise coefficients
        dr = self.frame.getInstrument().getRangePixelSize()
        norm = 0.5*Const.c/dr

        dcoeffs = []
        for ind, val in enumerate(self.dopplerRangeTime):
            dcoeffs.append( val / (norm**ind))


        self.frame._dopplerVsPixel = dcoeffs
        print('Doppler Fit: ', fit[::-1])

        return quadratic



    def extractImage(self):
        import array
        import math

        self.parse()
        try:
            out = open(self.output, 'wb')
        except:
            raise Exception('Cannot open output file: %s'%(self.output))

        self.imageFile.extractImage(output=out)
        out.close()

        rawImage = isceobj.createSlcImage()
        rawImage.setByteOrder('l')
        rawImage.setAccessMode('read')
        rawImage.setFilename(self.output)
        rawImage.setWidth(self.imageFile.width)
        rawImage.setXmin(0)
        rawImage.setXmax(self.imageFile.width)
        self.frame.setImage(rawImage)

        prf = self.frame.getInstrument().getPulseRepetitionFrequency()
        senStart = self.frame.getSensingStart()
        numPulses = int(math.ceil(DTU.timeDeltaToSeconds(self.frame.getSensingStop()-senStart)*prf))
        musec0 = (senStart.hour*3600 + senStart.minute*60 + senStart.second)*10**6 + senStart.microsecond
        maxMusec = (24*3600)*10**6#use it to check if we went across  a day. very rare
        day0 = (datetime.datetime(senStart.year,senStart.month,senStart.day) - datetime.datetime(senStart.year,1,1)).days + 1
        outputArray  = array.array('d',[0]*2*numPulses)
        self.frame.auxFile = self.output + '.aux'
        fp = open(self.frame.auxFile,'wb')
        j = -1
        for i1 in range(numPulses):
            j += 1
            musec = round((j/prf)*10**6) + musec0
            if musec >= maxMusec:
                day0 += 1
                musec0 = musec%maxMusec
                musec = musec0
                j = 0
            outputArray[2*i1] = day0
            outputArray[2*i1+1] = musec

        outputArray.tofile(fp)
        fp.close()


    def _decodeSceneReferenceNumber(self,referenceNumber):
        frameNumber = referenceNumber.split('=')
        if (len(frameNumber) > 2):
            frameNumber = frameNumber[2].strip()
        else:
            frameNumber = frameNumber[0]

        return frameNumber
class COSMO_SkyMed_SLC(Sensor):
    """
    A class representing a Level1Product meta data.
    Level1Product(hdf5=h5filename) will parse the hdf5
    file and produce an object with attributes for metadata.
    """
    parameter_list = (HDF5, ) + Sensor.parameter_list
    logging_name = 'isce.Sensor.COSMO_SkyMed_SLC'
    family = 'cosmo_skymed_slc'

    def __init__(self, family='', name=''):
        super(COSMO_SkyMed_SLC,
              self).__init__(family if family else self.__class__.family,
                             name=name)
        self.frame = Frame()
        self.frame.configure()
        # Some extra processing parameters unique to CSK SLC (currently)
        self.dopplerRangeTime = []
        self.dopplerAzimuthTime = []
        self.azimuthRefTime = None
        self.rangeRefTime = None
        self.rangeFirstTime = None
        self.rangeLastTime = None

        self.lookMap = {'RIGHT': -1, 'LEFT': 1}
        return

    def __getstate__(self):
        d = dict(self.__dict__)
        del d['logger']
        return d

    def __setstate__(self, d):
        self.__dict__.update(d)
        self.logger = logging.getLogger('isce.Sensor.COSMO_SkyMed_SLC')
        return

    def getFrame(self):
        return self.frame

    def parse(self):
        try:
            fp = h5py.File(self.hdf5, 'r')
        except Exception as strerr:
            self.logger.error("IOError: %s" % strerr)
            return None

        self.populateMetadata(fp)
        fp.close()

    def populateMetadata(self, file):
        """
            Populate our Metadata objects
        """

        self._populatePlatform(file)
        self._populateInstrument(file)
        self._populateFrame(file)
        self._populateOrbit(file)
        self._populateExtras(file)

    def _populatePlatform(self, file):
        platform = self.frame.getInstrument().getPlatform()

        platform.setMission(file.attrs['Satellite ID'])
        platform.setPointingDirection(
            self.lookMap[file.attrs['Look Side'].decode('utf-8')])
        platform.setPlanet(Planet(pname="Earth"))

        ####This is an approximation for spotlight mode
        ####In spotlight mode, antenna length changes with azimuth position
        platform.setAntennaLength(file.attrs['Antenna Length'])
        try:
            if file.attrs['Multi-Beam ID'].startswith('ES'):
                platform.setAntennaLength(
                    16000.0 / file['S01/SBI'].attrs['Line Time Interval'])
        except:
            pass

    def _populateInstrument(self, file):
        instrument = self.frame.getInstrument()

        #        rangePixelSize = Const.c/(2*file['S01'].attrs['Sampling Rate'])
        rangePixelSize = file['S01/SBI'].attrs['Column Spacing']
        instrument.setRadarWavelength(file.attrs['Radar Wavelength'])
        #        instrument.setPulseRepetitionFrequency(file['S01'].attrs['PRF'])
        instrument.setPulseRepetitionFrequency(
            1.0 / file['S01/SBI'].attrs['Line Time Interval'])
        instrument.setRangePixelSize(rangePixelSize)
        instrument.setPulseLength(file['S01'].attrs['Range Chirp Length'])
        instrument.setChirpSlope(file['S01'].attrs['Range Chirp Rate'])
        #        instrument.setRangeSamplingRate(file['S01'].attrs['Sampling Rate'])
        instrument.setRangeSamplingRate(
            1.0 / file['S01/SBI'].attrs['Column Time Interval'])

        incangle = 0.5 * (file['S01/SBI'].attrs['Far Incidence Angle'] +
                          file['S01/SBI'].attrs['Near Incidence Angle'])
        instrument.setIncidenceAngle(incangle)

    def _populateFrame(self, file):

        rft = file['S01/SBI'].attrs['Zero Doppler Range First Time']
        slantRange = rft * Const.c / 2.0
        self.frame.setStartingRange(slantRange)

        referenceUTC = self._parseNanoSecondTimeStamp(
            file.attrs['Reference UTC'])
        relStart = file['S01/SBI'].attrs['Zero Doppler Azimuth First Time']
        relEnd = file['S01/SBI'].attrs['Zero Doppler Azimuth Last Time']
        relMid = 0.5 * (relStart + relEnd)

        sensingStart = self._combineDateTime(referenceUTC, relStart)
        sensingStop = self._combineDateTime(referenceUTC, relEnd)
        sensingMid = self._combineDateTime(referenceUTC, relMid)

        self.frame.setPassDirection(file.attrs['Orbit Direction'])
        self.frame.setOrbitNumber(file.attrs['Orbit Number'])
        self.frame.setProcessingFacility(file.attrs['Processing Centre'])
        self.frame.setProcessingSoftwareVersion(
            file.attrs['L0 Software Version'])
        self.frame.setPolarization(file['S01'].attrs['Polarisation'])
        self.frame.setNumberOfLines(file['S01/SBI'].shape[0])
        self.frame.setNumberOfSamples(file['S01/SBI'].shape[1])
        self.frame.setSensingStart(sensingStart)
        self.frame.setSensingMid(sensingMid)
        self.frame.setSensingStop(sensingStop)

        rangePixelSize = self.frame.getInstrument().getRangePixelSize()
        farRange = slantRange + (self.frame.getNumberOfSamples() -
                                 1) * rangePixelSize
        self.frame.setFarRange(farRange)

    def _populateOrbit(self, file):
        orbit = self.frame.getOrbit()

        orbit.setReferenceFrame('ECR')
        orbit.setOrbitSource('Header')
        t0 = datetime.datetime.strptime(
            file.attrs['Reference UTC'].decode('utf-8'),
            '%Y-%m-%d %H:%M:%S.%f000')
        t = file.attrs['State Vectors Times']
        position = file.attrs['ECEF Satellite Position']
        velocity = file.attrs['ECEF Satellite Velocity']

        for i in range(len(position)):
            vec = StateVector()
            dt = t0 + datetime.timedelta(seconds=t[i])
            vec.setTime(dt)
            vec.setPosition([position[i, 0], position[i, 1], position[i, 2]])
            vec.setVelocity([velocity[i, 0], velocity[i, 1], velocity[i, 2]])
            orbit.addStateVector(vec)

    def _populateExtras(self, file):
        """
        Populate some of the extra fields unique to processing TSX data.
        In the future, other sensors may need this information as well,
        and a re-organization may be necessary.
        """
        from isceobj.Doppler.Doppler import Doppler

        self.dopplerRangeTime = file.attrs['Centroid vs Range Time Polynomial']
        self.dopplerAzimuthTime = file.attrs[
            'Centroid vs Azimuth Time Polynomial']
        self.rangeRefTime = file.attrs['Range Polynomial Reference Time']
        self.azimuthRefTime = file.attrs['Azimuth Polynomial Reference Time']
        self.rangeFirstTime = file['S01/SBI'].attrs[
            'Zero Doppler Range First Time']
        self.rangeLastTime = file['S01/SBI'].attrs[
            'Zero Doppler Range Last Time']

        # get Doppler rate information, vs. azimuth first EJF 2015/00/05
        # guessing that same scale applies as for Doppler centroid
        self.dopplerRateCoeffs = file.attrs[
            'Doppler Rate vs Azimuth Time Polynomial']

    def extractImage(self):
        import os
        from ctypes import cdll, c_char_p
        extract_csk = cdll.LoadLibrary(os.path.dirname(__file__) + '/csk.so')
        inFile_c = c_char_p(bytes(self.hdf5, 'utf-8'))
        outFile_c = c_char_p(bytes(self.output, 'utf-8'))

        extract_csk.extract_csk_slc(inFile_c, outFile_c)

        self.parse()
        slcImage = isceobj.createSlcImage()
        slcImage.setFilename(self.output)
        slcImage.setXmin(0)
        slcImage.setXmax(self.frame.getNumberOfSamples())
        slcImage.setWidth(self.frame.getNumberOfSamples())
        slcImage.setAccessMode('r')
        self.frame.setImage(slcImage)

    def _parseNanoSecondTimeStamp(self, timestamp):
        """
            Parse a date-time string with nanosecond precision and return a datetime object
        """
        dateTime, nanoSeconds = timestamp.decode('utf-8').split('.')
        microsec = float(nanoSeconds) * 1e-3
        dt = datetime.datetime.strptime(dateTime, '%Y-%m-%d %H:%M:%S')
        dt = dt + datetime.timedelta(microseconds=microsec)
        return dt

    def _combineDateTime(self, dobj, secsstr):
        '''Takes the date from dobj and time from secs to spit out a date time object.
        '''
        sec = float(secsstr)
        dt = datetime.timedelta(seconds=sec)
        return datetime.datetime.combine(dobj.date(), datetime.time(0, 0)) + dt

    def extractDoppler(self):
        """
        Return the doppler centroid as defined in the HDF5 file.
        """
        import numpy as np

        quadratic = {}
        midtime = (self.rangeLastTime +
                   self.rangeFirstTime) * 0.5 - self.rangeRefTime

        fd_mid = 0.0
        x = 1.0
        for ind, coeff in enumerate(self.dopplerRangeTime):
            fd_mid += coeff * x
            x *= midtime

        ####insarApp style
        quadratic['a'] = fd_mid / self.frame.getInstrument(
        ).getPulseRepetitionFrequency()
        quadratic['b'] = 0.
        quadratic['c'] = 0.

        ####For roiApp more accurate
        ####Convert stuff to pixel wise coefficients
        from isceobj.Util import Poly1D

        coeffs = self.dopplerRangeTime
        dr = self.frame.getInstrument().getRangePixelSize()
        rref = 0.5 * Const.c * self.rangeRefTime
        r0 = self.frame.getStartingRange()
        norm = 0.5 * Const.c / dr

        dcoeffs = []
        for ind, val in enumerate(coeffs):
            dcoeffs.append(val / (norm**ind))

        poly = Poly1D.Poly1D()
        poly.initPoly(order=len(coeffs) - 1)
        poly.setMean((rref - r0) / dr - 1.0)
        poly.setCoeffs(dcoeffs)

        pix = np.linspace(0,
                          self.frame.getNumberOfSamples(),
                          num=len(coeffs) + 1)
        evals = poly(pix)
        fit = np.polyfit(pix, evals, len(coeffs) - 1)
        self.frame._dopplerVsPixel = list(fit[::-1])
        print('Doppler Fit: ', fit[::-1])

        #EMG - 20160420 This section was introduced in the populateMetadata method by EJF in r2022
        #Its pupose seems to be to set self.doppler_coeff and self.azfmrate_coeff, which don't seem
        #to be used anywhere in ISCE. Need to take time to understand the need for this and consult
        #with EJF.
        #
        ## save the Doppler centroid coefficients, converting units from .h5 file
        ## units in the file are quadratic coefficients in Hz, Hz/sec, and Hz/(sec^2)
        ## ISCE expects Hz, Hz/(range sample), Hz/(range sample)^2
        ## note that RS2 Doppler values are estimated at time dc.dopplerCentroidReferenceTime,
        ## so the values might need to be adjusted for ISCE usage
        ## adapted from RS2 version EJF 2015/09/05
        #        poly = self.frame._dopplerVsPixel
        #        rangeSamplingRate = self.frame.getInstrument().getPulseRepetitionFrequency()
        #        # need to convert units
        #        poly[1] = poly[1]/rangeSamplingRate
        #        poly[2] = poly[2]/rangeSamplingRate**2
        #        self.doppler_coeff = poly
        #
        ## similarly save Doppler azimuth fm rate values, converting units
        ## units in the file are quadratic coefficients in Hz, Hz/sec, and Hz/(sec^2)
        ## units are already converted below
        ## Guessing that ISCE expects Hz, Hz/(azimuth line), Hz/(azimuth line)^2
        ## note that RS2 Doppler values are estimated at time dc.dopplerRateReferenceTime,
        ## so the values might need to be adjusted for ISCE usage
        ## modified from RS2 version EJF 2015/09/05
        ## CSK Doppler azimuth FM rate not yet implemented in reading section, set to zero for now
        #
        #        fmpoly = self.dopplerRateCoeffs
        #        # don't need to convert units
        ##        fmpoly[1] = fmpoly[1]/rangeSamplingRate
        ##        fmpoly[2] = fmpoly[2]/rangeSamplingRate**2
        #        self.azfmrate_coeff = fmpoly
        #EMG - 20160420

        return quadratic
Пример #15
0
class ICEYE_SLC(Sensor):
    """
    A class representing a Level1Product meta data.
    Level1Product(hdf5=h5filename) will parse the hdf5
    file and produce an object with attributes for metadata.
    """
    parameter_list = (HDF5, APPLY_SLANT_RANGE_PHASE) + Sensor.parameter_list
    logging_name = 'isce.Sensor.ICEYE_SLC'
    family = 'iceye_slc'

    def __init__(self, family='', name=''):
        super(ICEYE_SLC,
              self).__init__(family if family else self.__class__.family,
                             name=name)
        self.frame = Frame()
        self.frame.configure()
        # Some extra processing parameters unique to CSK SLC (currently)
        self.dopplerRangeTime = []
        self.dopplerAzimuthTime = []
        self.azimuthRefTime = None
        self.rangeRefTime = None
        self.rangeFirstTime = None
        self.rangeLastTime = None

        self.lookMap = {'RIGHT': -1, 'LEFT': 1}
        return

    def __getstate__(self):
        d = dict(self.__dict__)
        del d['logger']
        return d

    def __setstate__(self, d):
        self.__dict__.update(d)
        self.logger = logging.getLogger('isce.Sensor.ICEYE_SLC')
        return

    def getFrame(self):
        return self.frame

    def parse(self):
        try:
            fp = h5py.File(self.hdf5, 'r')
        except Exception as strerr:
            self.logger.error("IOError: %s" % strerr)
            return None

        self.populateMetadata(fp)
        fp.close()

    def populateMetadata(self, file):
        """
            Populate our Metadata objects
        """

        self._populatePlatform(file)
        self._populateInstrument(file)
        self._populateFrame(file)
        self._populateOrbit(file)
        self._populateExtras(file)

    def _populatePlatform(self, file):
        platform = self.frame.getInstrument().getPlatform()

        platform.setMission(file['satellite_name'][()])
        platform.setPointingDirection(
            self.lookMap[file['look_side'][()].upper()])
        platform.setPlanet(Planet(pname="Earth"))

        ####This is an approximation for spotlight mode
        ####In spotlight mode, antenna length changes with azimuth position
        platform.setAntennaLength(2 * file['azimuth_ground_spacing'][()])

        assert (file['range_looks'][()] == 1)
        assert (file['azimuth_looks'][()] == 1)

    def _populateInstrument(self, file):
        instrument = self.frame.getInstrument()

        rangePixelSize = file['slant_range_spacing'][()]
        instrument.setRadarWavelength(Const.c / file['carrier_frequency'][()])
        instrument.setPulseRepetitionFrequency(file['processing_prf'][()])
        instrument.setRangePixelSize(rangePixelSize)
        instrument.setPulseLength(file['chirp_duration'][()])
        instrument.setChirpSlope(file['chirp_bandwidth'][()] /
                                 file['chirp_duration'][()])
        instrument.setRangeSamplingRate(file['range_sampling_rate'][()])

        incangle = file['local_incidence_angle']
        instrument.setIncidenceAngle(incangle[incangle.size // 2])

    def _populateFrame(self, file):

        rft = file['first_pixel_time'][()]
        slantRange = rft * Const.c / 2.0
        self.frame.setStartingRange(slantRange)

        sensingStart = datetime.datetime.strptime(
            file['zerodoppler_start_utc'][()].decode('utf-8'),
            '%Y-%m-%dT%H:%M:%S.%f')
        sensingStop = datetime.datetime.strptime(
            file['zerodoppler_end_utc'][()].decode('utf-8'),
            '%Y-%m-%dT%H:%M:%S.%f')
        sensingMid = sensingStart + 0.5 * (sensingStop - sensingStart)

        self.frame.setPassDirection(file['orbit_direction'][()])
        self.frame.setOrbitNumber(file['orbit_absolute_number'][()])
        self.frame.setProcessingFacility('ICEYE')
        self.frame.setProcessingSoftwareVersion(
            str(file['processor_version'][()]))
        self.frame.setPolarization(file['polarization'][()])
        self.frame.setNumberOfLines(file['number_of_azimuth_samples'][()])
        self.frame.setNumberOfSamples(file['number_of_range_samples'][()])
        self.frame.setSensingStart(sensingStart)
        self.frame.setSensingMid(sensingMid)
        self.frame.setSensingStop(sensingStop)

        rangePixelSize = self.frame.getInstrument().getRangePixelSize()
        farRange = slantRange + (self.frame.getNumberOfSamples() -
                                 1) * rangePixelSize
        self.frame.setFarRange(farRange)

    def _populateOrbit(self, file):
        import numpy as np
        orbit = self.frame.getOrbit()

        orbit.setReferenceFrame('ECR')
        orbit.setOrbitSource('Header')
        t = file['state_vector_time_utc'][:]
        position = np.zeros((t.size, 3))
        position[:, 0] = file['posX'][:]
        position[:, 1] = file['posY'][:]
        position[:, 2] = file['posZ'][:]

        velocity = np.zeros((t.size, 3))
        velocity[:, 0] = file['velX'][:]
        velocity[:, 1] = file['velY'][:]
        velocity[:, 2] = file['velZ'][:]

        for ii in range(t.size):
            vec = StateVector()
            vec.setTime(
                datetime.datetime.strptime(t[ii][0].decode('utf-8'),
                                           '%Y-%m-%dT%H:%M:%S.%f'))
            vec.setPosition(
                [position[ii, 0], position[ii, 1], position[ii, 2]])
            vec.setVelocity(
                [velocity[ii, 0], velocity[ii, 1], velocity[ii, 2]])
            orbit.addStateVector(vec)

    def _populateExtras(self, file):
        """
        Populate some of the extra fields unique to processing TSX data.
        In the future, other sensors may need this information as well,
        and a re-organization may be necessary.
        """
        import numpy as np
        self.dcpoly = np.mean(file['dc_estimate_coeffs'][:], axis=0)

    def extractImage(self):
        import numpy as np
        import h5py

        self.parse()

        fid = h5py.File(self.hdf5, 'r')

        si = fid['s_i']
        sq = fid['s_q']

        nLines = si.shape[0]
        spectralShift = 2 * self.frame.getInstrument().getRangePixelSize(
        ) / self.frame.getInstrument().getRadarWavelength()
        spectralShift -= np.floor(spectralShift)
        phsShift = np.exp(-1j * 2 * np.pi * spectralShift *
                          np.arange(si.shape[1]))
        with open(self.output, 'wb') as fout:
            for ii in range(nLines):
                line = (si[ii, :] + 1j * sq[ii, :])
                if self.applySlantRangePhase:
                    line *= phsShift
                line.astype(np.complex64).tofile(fout)

        fid.close()

        slcImage = isceobj.createSlcImage()
        slcImage.setFilename(self.output)
        slcImage.setXmin(0)
        slcImage.setXmax(self.frame.getNumberOfSamples())
        slcImage.setWidth(self.frame.getNumberOfSamples())
        slcImage.setAccessMode('r')
        self.frame.setImage(slcImage)

    def extractDoppler(self):
        """
        Return the doppler centroid as defined in the HDF5 file.
        """
        import numpy as np

        quadratic = {}

        rangePixelSize = self.frame.getInstrument().getRangePixelSize()
        rt0 = self.frame.getStartingRange() / (2 * Const.c)
        rt1 = rt0 + ((self.frame.getNumberOfSamples() - 1) *
                     rangePixelSize) / (2 * Const.c)

        ####insarApp style
        quadratic['a'] = np.polyval(self.dcpoly, 0.5 *
                                    (rt0 + rt1)) / self.frame.PRF
        quadratic['b'] = 0.
        quadratic['c'] = 0.

        ####For roiApp more accurate
        ####Convert stuff to pixel wise coefficients
        x = np.linspace(rt0, rt1, num=len(self.dcpoly) + 1)
        pix = np.linspace(0,
                          self.frame.getNumberOfSamples(),
                          num=len(self.dcpoly) + 1)
        evals = np.polyval(self.dcpoly, x)
        fit = np.polyfit(pix, evals, len(self.dcpoly) - 1)
        self.frame._dopplerVsPixel = list(fit[::-1])
        print('Doppler Fit: ', self.frame._dopplerVsPixel)

        return quadratic