示例#1
0
class ALOS(Component):
    """Code to read CEOSFormat leader files for ALOS 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 = 'alos'
    logging_name = 'isce.sensor.ALOS'

    parameter_list = (IMAGEFILE, LEADERFILE, OUTPUT, RESAMPLE_FLAG)

    #    polarizationMap = ['H','V','H+V']

    ## This is manifestly better than a method complete the lazy instantation
    ## of an instance attribute
    transmit = Distortion(complex(2.427029e-3, 1.293019e-2),
                          complex(-1.147240e-2, -6.228230e-3),
                          complex(9.572169e-1, 3.829563e-1))
    receive = Distortion(complex(-6.263392e-3, 7.082863e-3),
                         complex(-6.297074e-3, 8.026685e-3),
                         complex(7.217117e-1, -2.367683e-2))

    constants = Constants(iBias=15.5,
                          qBias=15.5,
                          pointingDirection=-1,
                          antennaLength=8.9)

    HEADER_LINES = 720

    RESAMPLE_FLAG = {
        '': 'do Nothing',
        'single2dual': 'resample from single to dual pole',
        'dual2single': 'resample from dual to single'
    }

    @logged
    def __init__(self, name=''):
        super(ALOS, self).__init__(family=self.__class__.family, name=name)
        self._leaderFile = None
        self._imageFile = None
        self.frame = None
        return None

    #2013-06-03 Kosal: the functions below overwrite the transmit property
    #initiated above
    '''
    @property
    def transmit(self):
        return self.__class__.transmit
    @transmit.setter
    def transmit(self, x):
        raise TypeError(
            "ALOS.transmit is a protected class attribute and cannot be set"
            )
    @property
    def receive(self):
        return self.__class__.receive
    @receive.setter
    def receive(self, x):
        raise TypeError(
            "ALOS.receive is a protected class attribute and cannot be set"
            )
    '''

    #Kosal

    def getFrame(self):
        return self.frame

    def setLeaderFile(self, ldr):
        self._leaderFile = ldr
        return

    def parse(self):
        self.leaderFile = LeaderFile(file=self._leaderFile)
        self.imageFile = ImageFile(self)
        try:
            self.leaderFile.parse()
            self.imageFile.parse()
        except IOError:
            return
        self.populateMetadata()

    def populateMetadata(self):
        """
        Create the appropriate metadata objects from our CEOSFormat metadata
        """
        self._populatePlatform()
        self._populateInstrument()
        self._populateFrame()
        # Header orbits
        self._populateOrbit()
        self._populateAttitude()
        self._populateDistortions()
        pass

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

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

    def _populateInstrument(self):
        instrument = self.frame.getInstrument()
        rangePixelSize = None
        rangeSamplingRate = None
        chirpSlope = None
        bandwidth = None
        prf = None
        try:
            rangeSamplingRate = self.leaderFile.sceneHeaderRecord.metadata[
                'Range sampling rate'] * 1e6
            pulseLength = self.leaderFile.sceneHeaderRecord.metadata[
                'Range pulse length'] * 1e-6
            rangePixelSize = SPEED_OF_LIGHT / (2.0 * rangeSamplingRate)
            prf = self.leaderFile.sceneHeaderRecord.metadata[
                'Pulse Repetition Frequency']
            beamNumber = self.leaderFile.sceneHeaderRecord.metadata[
                'Antenna beam number']
            if self.imageFile.prf:
                prf = self.imageFile.prf
            else:
                self.logger.info("Using nominal PRF")
            bandwidth = self.leaderFile.calibrationRecord.metadata[
                'Band width'] * 1e6
            #if (not bandwidth):
            #    bandwidth = self.leaderFile.sceneHeaderRecord.metadata[
            #    'Bandwidth per look in range']
            chirpSlope = -(bandwidth / pulseLength)
        except AttributeError:
            self.logger.info("Some of the instrument parameters were not set")

        self.logger.debug("PRF: %s" % prf)
        self.logger.debug("Bandwidth: %s" % bandwidth)
        self.logger.debug("Pulse Length: %s" % pulseLength)
        self.logger.debug("Chirp Slope: %s" % chirpSlope)
        self.logger.debug("Range Pixel Size: %s" % rangePixelSize)
        self.logger.debug("Range Sampling Rate: %s" % rangeSamplingRate)
        self.logger.debug("Beam Number: %s" % beamNumber)
        instrument.setRadarWavelength(
            self.leaderFile.sceneHeaderRecord.metadata['Radar wavelength'])
        instrument.setIncidenceAngle(
            self.leaderFile.sceneHeaderRecord.
            metadata['Incidence angle at scene centre'])
        instrument.setPulseRepetitionFrequency(prf)
        instrument.setRangePixelSize(rangePixelSize)
        instrument.setRangeSamplingRate(rangeSamplingRate)
        instrument.setPulseLength(pulseLength)
        instrument.setChirpSlope(chirpSlope)
        instrument.setInPhaseValue(self.constants['iBias'])
        instrument.setQuadratureValue(self.constants['qBias'])
        instrument.setBeamNumber(beamNumber)
        return None

    def _populateFrame(self, polarization='HH', farRange=None):
        frame = self._decodeSceneReferenceNumber(
            self.leaderFile.sceneHeaderRecord.
            metadata['Scene reference number'])

        try:
            first_line_utc = self.imageFile.start_time
            last_line_utc = self.imageFile.stop_time
            centerTime = DTUtil.timeDeltaToSeconds(last_line_utc -
                                                   first_line_utc) / 2.0
            center_line_utc = first_line_utc + datetime.timedelta(
                microseconds=int(centerTime * 1e6))
            self.frame.setSensingStart(first_line_utc)
            self.frame.setSensingMid(center_line_utc)
            self.frame.setSensingStop(last_line_utc)
            rangePixelSize = self.frame.getInstrument().getRangePixelSize()
            farRange = (self.imageFile.startingRange +
                        self.imageFile.width * rangePixelSize)
        except TypeError as strerr:
            self.logger.warn(strerr)

        self.frame.frameNumber = frame
        self.frame.setOrbitNumber(
            self.leaderFile.sceneHeaderRecord.metadata['Orbit number'])
        self.frame.setStartingRange(self.imageFile.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(polarization)
        self.frame.setNumberOfLines(self.imageFile.length)
        self.frame.setNumberOfSamples(self.imageFile.width)

    def _populateOrbit(self):
        orbit = self.frame.getOrbit()
        velocityScale = 1.0
        if (self.leaderFile.sceneHeaderRecord.
                metadata['Processing facility identifier'] == 'ERSDAC'):
            # The ERSDAC header orbits are in mm/s
            velocityScale = 1000.0

        orbit.setReferenceFrame(self.leaderFile.platformPositionRecord.
                                metadata['Reference coordinate system'])
        orbit.setOrbitSource('Header')
        orbitQuality = self._decodeOrbitQuality(
            self.leaderFile.platformPositionRecord.
            metadata['Orbital elements designator'])
        orbit.setOrbitQuality(orbitQuality)

        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 = OrbitStateVector()
            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'] / velocityScale,
                dataPoints['Velocity vector Y'] / velocityScale,
                dataPoints['Velocity vector Z'] / velocityScale
            ])
            orbit.addStateVector(vec)

    def _populateAttitude(self):
        if (self.leaderFile.leaderFDR.
                metadata['Number of attitude data records'] != 1):
            return

        attitude = self.frame.getAttitude()
        attitude.setAttitudeSource("Header")

        year = int(
            self.leaderFile.sceneHeaderRecord.metadata['Scene centre time']
            [0:4])
        t0 = datetime.datetime(year=year, month=1, day=1)

        for i in range(self.leaderFile.platformAttitudeRecord.
                       metadata['Number of attitude data points']):
            vec = AttitudeStateVector()

            dataPoints = self.leaderFile.platformAttitudeRecord.metadata[
                'Attitude Data Points'][i]
            t = t0 + datetime.timedelta(
                days=(dataPoints['Day of the year'] - 1),
                milliseconds=dataPoints['Millisecond of day'])
            vec.setTime(t)
            vec.setPitch(dataPoints['Pitch'])
            vec.setRoll(dataPoints['Roll'])
            vec.setYaw(dataPoints['Yaw'])
            attitude.addStateVector(vec)

    def _populateDistortions(self):
        return None

    def readOrbitPulse(self, leader, raw, width):
        from isceobj.Sensor import readOrbitPulse as ROP
        rawImage = isceobj.createRawImage()
        leaImage = isceobj.createStreamImage()
        auxImage = isceobj.createImage()
        rawImage.initImage(raw, 'read', width)
        rawImage.createImage()
        rawAccessor = rawImage.getImagePointer()
        leaImage.initImage(leader, 'read')
        leaImage.createImage()
        leaAccessor = leaImage.getImagePointer()
        widthAux = 2
        auxName = raw + '.aux'
        self.frame.auxFile = auxName
        auxImage.initImage(auxName, 'write', widthAux, type='DOUBLE')
        auxImage.createImage()
        auxAccessor = auxImage.getImagePointer()
        length = rawImage.getLength()
        ROP.setNumberBitesPerLine_Py(width)
        ROP.setNumberLines_Py(length)
        ROP.readOrbitPulse_Py(leaAccessor, rawAccessor, auxAccessor)
        rawImage.finalizeImage()
        leaImage.finalizeImage()
        auxImage.finalizeImage()
        return None

    ## Can this even be done/
    ## should the pointer be an __Int__?
    def readOrbitPulseDevelopement(self, leader, raw, width):
        from isceobj.Sensor import readOrbitPulse as ROP
        with isceobj.contextRawImage(
                width=width,
                accessMode='read',
        ) as rawImage:
            with isceobj.contextStreamImage(
                    width=width,
                    accessMode='read',
            ) as leaImage:
                with isceobj.contextImage(
                        width=width,
                        accessMode='write',
                ) as auxImage:

                    rawAccessor = rawImage.getImagePointer()
                    leaAccessor = leaImage.getImagePointer()
                    widthAux = 2
                    auxName = raw + '.aux'
                    self.frame.auxFile = auxName
                    auxImage.initImage(auxName,
                                       'write',
                                       widthAux,
                                       type='DOUBLE')
                    auxImage.createImage()
                    auxAccessor = auxImage.getImagePointer()
                    length = rawImage.getLength()
                    ROP.setNumberBitesPerLine_Py(width)
                    ROP.setNumberLines_Py(length)
                    ROP.readOrbitPulse_Py(leaAccessor, rawAccessor,
                                          auxAccessor)
                    pass  #rawImage.finalizeImage()
                pass  #leaImage.finalizeImage()
            pass  #auxImage.finalizeImage()
        return None

    def extractImage(self):
        # 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 RuntimeError
        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.imageFile = ImageFile(self)

            try:
                self.leaderFile.parse()
                self.imageFile.parse(calculateRawDimensions=False)
                outputNow = self.output + appendStr
                if not (self._resampleFlag == ''):
                    filein = self.output + '__tmp__'
                    self.imageFile.extractImage(filein)
                    self.populateMetadata()
                    objResample = None
                    if (self._resampleFlag == 'single2dual'):
                        objResample = ALOS_fbs2fbdPy()
                    else:
                        objResample = ALOS_fbd2fbsPy()
                    objResample.wireInputPort('frame', object=self.frame)
                    objResample.setInputFilename(filein)
                    objResample.setOutputFilename(outputNow)
                    objResample.run()
                    objResample.updateFrame(self.frame)
                    os.remove(filein)
                else:
                    self.imageFile.extractImage(outputNow)
                    self.populateMetadata()
                width = self.frame.getImage().getWidth()
                self.readOrbitPulse(self._leaderFile, outputNow, width)
                self.frameList.append(self.frame)
            except IOError:
                return
            pass
        ## refactor this with __init__.tkfunc
        return tkfunc(self)

    def _decodeSceneReferenceNumber(self, referenceNumber):
        return referenceNumber

    def _decodeOrbitQuality(self, quality):
        try:
            quality = int(quality)
        except ValueError:
            quality = None

        qualityString = ''
        if (quality == 0):
            qualityString = 'Preliminary'
        elif (quality == 1):
            qualityString = 'Decision'
        elif (quality == 2):
            qualityString = 'High Precision'
        else:
            qualityString = 'Unknown'

        return qualityString
示例#2
0
文件: ALOS.py 项目: yunjunz/isce2
class ALOS(Sensor):
    """Code to read CEOSFormat leader files for ALOS 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 = 'alos'
    logging_name = 'isce.sensor.ALOS'

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

    #    polarizationMap = ['H','V','H+V']

    ## This is manifestly better than a method complete the lazy instantation
    ## of an instance attribute
    transmit = Distortion(complex(2.427029e-3, 1.293019e-2),
                          complex(-1.147240e-2, -6.228230e-3),
                          complex(9.572169e-1, 3.829563e-1))
    receive = Distortion(complex(-6.263392e-3, 7.082863e-3),
                         complex(-6.297074e-3, 8.026685e-3),
                         complex(7.217117e-1, -2.367683e-2))

    constants = Constants(iBias=63.5,
                          qBias=63.5,
                          pointingDirection=-1,
                          antennaLength=8.9)

    HEADER_LINES = 720

    RESAMPLE_FLAG = {
        '': 'do Nothing',
        'single2dual': 'resample from single to dual pole',
        'dual2single': 'resample from dual to single'
    }

    @logged
    def __init__(self, name=''):
        super().__init__(family=self.__class__.family, name=name)
        self._leaderFile = None
        self._imageFile = None
        self.frame = None
        return None

    #2013-06-03 Kosal: the functions below overwrite the transmit property
    #initiated above
    '''
    @property
    def transmit(self):
        return self.__class__.transmit
    @transmit.setter
    def transmit(self, x):
        raise TypeError(
            "ALOS.transmit is a protected class attribute and cannot be set"
            )
    @property
    def receive(self):
        return self.__class__.receive
    @receive.setter
    def receive(self, x):
        raise TypeError(
            "ALOS.receive is a protected class attribute and cannot be set"
            )
    '''

    #Kosal

    def getFrame(self):
        return self.frame

    def setLeaderFile(self, ldr):
        self._leaderFile = ldr
        return

    def parse(self):
        self.leaderFile = LeaderFile(file=self._leaderFile)
        self.imageFile = ImageFile(self)
        try:
            self.leaderFile.parse()
            self.imageFile.parse()
        except IOError:
            return
        self.populateMetadata()

    def populateMetadata(self):
        """
        Create the appropriate metadata objects from our CEOSFormat metadata
        """
        self._populatePlatform()
        self._populateInstrument()
        self._populateFrame()
        # Header orbits
        self._populateOrbit()
        self._populateAttitude()
        self._populateDistortions()

        productLevel = float(
            self.leaderFile.sceneHeaderRecord.metadata['Product level code'])

        #this proves to be not accurate. Adjusting first frame is OK, but adjusting following frames would cause discontinuities between frames. C. Liang, 20-dec-2021
        # if productLevel == 1.0:
        #     self.updateRawParameters()
        pass

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

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

    def _populateInstrument(self):
        instrument = self.frame.getInstrument()
        rangePixelSize = None
        rangeSamplingRate = None
        chirpSlope = None
        bandwidth = None
        prf = None
        try:
            rangeSamplingRate = self.leaderFile.sceneHeaderRecord.metadata[
                'Range sampling rate'] * 1e6
            pulseLength = self.leaderFile.sceneHeaderRecord.metadata[
                'Range pulse length'] * 1e-6
            rangePixelSize = SPEED_OF_LIGHT / (2.0 * rangeSamplingRate)
            prf = self.leaderFile.sceneHeaderRecord.metadata[
                'Pulse Repetition Frequency'] / 1000.

            ###Fix for quad pol data
            if prf > 3000:
                prf = prf / 2.0

            print('LEADER PRF: ', prf)
            beamNumber = self.leaderFile.sceneHeaderRecord.metadata[
                'Antenna beam number']
            #            if self.imageFile.prf:
            #                prf = self.imageFile.prf
            #            else:
            #                self.logger.info("Using nominal PRF")
            bandwidth = self.leaderFile.calibrationRecord.metadata[
                'Band width'] * 1e6
            #if (not bandwidth):
            #    bandwidth = self.leaderFile.sceneHeaderRecord.metadata[
            #    'Bandwidth per look in range']
            chirpSlope = -(bandwidth / pulseLength)
        except AttributeError:
            self.logger.info("Some of the instrument parameters were not set")

        self.logger.debug("PRF: %s" % prf)
        self.logger.debug("Bandwidth: %s" % bandwidth)
        self.logger.debug("Pulse Length: %s" % pulseLength)
        self.logger.debug("Chirp Slope: %s" % chirpSlope)
        self.logger.debug("Range Pixel Size: %s" % rangePixelSize)
        self.logger.debug("Range Sampling Rate: %s" % rangeSamplingRate)
        self.logger.debug("Beam Number: %s" % beamNumber)
        instrument.setRadarWavelength(
            self.leaderFile.sceneHeaderRecord.metadata['Radar wavelength'])
        instrument.setIncidenceAngle(
            self.leaderFile.sceneHeaderRecord.
            metadata['Incidence angle at scene centre'])
        instrument.setPulseRepetitionFrequency(prf)
        instrument.setRangePixelSize(rangePixelSize)
        instrument.setRangeSamplingRate(rangeSamplingRate)
        instrument.setPulseLength(pulseLength)
        instrument.setChirpSlope(chirpSlope)
        instrument.setInPhaseValue(self.constants['iBias'])
        instrument.setQuadratureValue(self.constants['qBias'])
        instrument.setBeamNumber(beamNumber)
        return None

    def _populateFrame(self, polarization='HH', farRange=None):
        frame = self._decodeSceneReferenceNumber(
            self.leaderFile.sceneHeaderRecord.
            metadata['Scene reference number'])

        try:
            first_line_utc = self.imageFile.start_time
            last_line_utc = self.imageFile.stop_time
            centerTime = DTUtil.timeDeltaToSeconds(last_line_utc -
                                                   first_line_utc) / 2.0
            center_line_utc = first_line_utc + datetime.timedelta(
                microseconds=int(centerTime * 1e6))
            self.frame.setSensingStart(first_line_utc)
            self.frame.setSensingMid(center_line_utc)
            self.frame.setSensingStop(last_line_utc)
            rangePixelSize = self.frame.getInstrument().getRangePixelSize()
            farRange = (self.imageFile.startingRange +
                        self.imageFile.width * rangePixelSize)
        except TypeError as strerr:
            self.logger.warning(strerr)

        self.frame.frameNumber = frame
        self.frame.setOrbitNumber(
            self.leaderFile.sceneHeaderRecord.metadata['Orbit number'])
        self.frame.setStartingRange(self.imageFile.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(polarization)
        self.frame.setNumberOfLines(self.imageFile.length)
        self.frame.setNumberOfSamples(self.imageFile.width)

    def _populateOrbit(self):
        orbit = self.frame.getOrbit()
        velocityScale = 1.0
        if (self.leaderFile.sceneHeaderRecord.
                metadata['Processing facility identifier'] == 'ERSDAC'):
            # The ERSDAC header orbits are in mm/s
            velocityScale = 1000.0

        orbit.setReferenceFrame(self.leaderFile.platformPositionRecord.
                                metadata['Reference coordinate system'])
        orbit.setOrbitSource('Header')
        orbitQuality = self._decodeOrbitQuality(
            self.leaderFile.platformPositionRecord.
            metadata['Orbital elements designator'])
        orbit.setOrbitQuality(orbitQuality)

        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 = OrbitStateVector()
            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'] / velocityScale,
                dataPoints['Velocity vector Y'] / velocityScale,
                dataPoints['Velocity vector Z'] / velocityScale
            ])
            orbit.addStateVector(vec)

    def _populateAttitude(self):
        if (self.leaderFile.leaderFDR.
                metadata['Number of attitude data records'] != 1):
            return

        attitude = self.frame.getAttitude()
        attitude.setAttitudeSource("Header")

        year = int(
            self.leaderFile.sceneHeaderRecord.metadata['Scene centre time']
            [0:4])
        t0 = datetime.datetime(year=year, month=1, day=1)

        for i in range(self.leaderFile.platformAttitudeRecord.
                       metadata['Number of attitude data points']):
            vec = AttitudeStateVector()

            dataPoints = self.leaderFile.platformAttitudeRecord.metadata[
                'Attitude Data Points'][i]
            t = t0 + datetime.timedelta(
                days=(dataPoints['Day of the year'] - 1),
                milliseconds=dataPoints['Millisecond of day'])
            vec.setTime(t)
            vec.setPitch(dataPoints['Pitch'])
            vec.setRoll(dataPoints['Roll'])
            vec.setYaw(dataPoints['Yaw'])
            attitude.addStateVector(vec)

    def _populateDistortions(self):
        return None

    def readOrbitPulse(self, leader, raw, width):
        '''
        No longer used. Can't rely on raw data headers. Should be done as part of extract Image.
        '''

        from isceobj.Sensor import readOrbitPulse as ROP
        print('TTTT')
        rawImage = isceobj.createRawImage()
        leaImage = isceobj.createStreamImage()
        auxImage = isceobj.createImage()
        rawImage.initImage(raw, 'read', width)
        rawImage.renderVRT()
        rawImage.createImage()
        rawAccessor = rawImage.getImagePointer()
        leaImage.initImage(leader, 'read')
        leaImage.createImage()
        leaAccessor = leaImage.getImagePointer()
        widthAux = 2
        auxName = raw + '.aux'
        self.frame.auxFile = auxName
        auxImage.initImage(auxName, 'write', widthAux, type='DOUBLE')
        auxImage.createImage()
        auxAccessor = auxImage.getImagePointer()
        length = rawImage.getLength()
        ROP.setNumberBitesPerLine_Py(width)
        ROP.setNumberLines_Py(length)
        ROP.readOrbitPulse_Py(leaAccessor, rawAccessor, auxAccessor)
        rawImage.finalizeImage()
        leaImage.finalizeImage()
        auxImage.finalizeImage()
        return None

    def makeFakeAux(self, outputNow):
        '''
        Generate an aux file based on sensing start and prf.
        '''
        import math, array

        prf = self.frame.getInstrument().getPulseRepetitionFrequency()
        senStart = self.frame.getSensingStart()
        numPulses = self.frame.numberOfLines
        # 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()

    ## Can this even be done/
    ## should the pointer be an __Int__?
    def readOrbitPulseDevelopement(self, leader, raw, width):
        from isceobj.Sensor import readOrbitPulse as ROP
        with isceobj.contextRawImage(
                width=width,
                accessMode='read',
        ) as rawImage:
            with isceobj.contextStreamImage(
                    width=width,
                    accessMode='read',
            ) as leaImage:
                with isceobj.contextImage(
                        width=width,
                        accessMode='write',
                ) as auxImage:

                    rawAccessor = rawImage.getImagePointer()
                    leaAccessor = leaImage.getImagePointer()
                    widthAux = 2
                    auxName = raw + '.aux'
                    self.frame.auxFile = auxName
                    auxImage.initImage(auxName,
                                       'write',
                                       widthAux,
                                       type='DOUBLE')
                    auxImage.createImage()
                    auxAccessor = auxImage.getImagePointer()
                    length = rawImage.getLength()
                    ROP.setNumberBitesPerLine_Py(width)
                    ROP.setNumberLines_Py(length)
                    ROP.readOrbitPulse_Py(leaAccessor, rawAccessor,
                                          auxAccessor)
                    pass  #rawImage.finalizeImage()
                pass  #leaImage.finalizeImage()
            pass  #auxImage.finalizeImage()
        return None

    def extractImage(self):
        if (len(self._imageFileList) != len(self._leaderFileList)):
            self.logger.error(
                "Number of leader files different from number of image files.")
            raise RuntimeError
        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.imageFile = ImageFile(self)

            try:
                self.leaderFile.parse()
                self.imageFile.parse(calculateRawDimensions=False)
                outputNow = self.output + appendStr
                if not (self._resampleFlag == ''):
                    filein = self.output + '__tmp__'
                    self.imageFile.extractImage(filein,
                                                i)  #image number start with 0
                    self.populateMetadata()
                    objResample = None
                    if (self._resampleFlag == 'single2dual'):
                        objResample = ALOS_fbs2fbdPy()
                    else:
                        objResample = ALOS_fbd2fbsPy()
                    objResample.wireInputPort('frame', object=self.frame)
                    objResample.setInputFilename(filein)
                    objResample.setOutputFilename(outputNow)
                    objResample.run()
                    objResample.updateFrame(self.frame)
                    os.remove(filein)
                else:
                    self.imageFile.extractImage(outputNow,
                                                i)  #image number start with 0
                    self.populateMetadata()
                width = self.frame.getImage().getWidth()
                #                self.readOrbitPulse(self._leaderFile,outputNow,width)
                self.makeFakeAux(outputNow)
                self.frameList.append(self.frame)
            except IOError:
                return
            pass
        ## refactor this with __init__.tkfunc
        return tkfunc(self)

    def _decodeSceneReferenceNumber(self, referenceNumber):
        return referenceNumber

    def _decodeOrbitQuality(self, quality):
        try:
            quality = int(quality)
        except ValueError:
            quality = None

        qualityString = ''
        if (quality == 0):
            qualityString = 'Preliminary'
        elif (quality == 1):
            qualityString = 'Decision'
        elif (quality == 2):
            qualityString = 'High Precision'
        else:
            qualityString = 'Unknown'

        return qualityString

    def updateRawParameters(self):
        '''
        Parse the data in python.
        '''
        with open(self._imageFile, 'rb') as fp:
            width = self.imageFile.width
            numberOfLines = self.imageFile.length
            prefix = self.imageFile.prefix
            suffix = self.imageFile.suffix
            dataSize = self.imageFile.dataSize

            fp.seek(720, os.SEEK_SET)  # Skip the header
            tags = []

            print('WIDTH: ', width)
            print('LENGTH: ', numberOfLines)
            print('PREFIX: ', prefix)
            print('SUFFIX: ', suffix)
            print('DATASIZE: ', dataSize)

            for i in range(numberOfLines):
                if not i % 1000: self.logger.info("Line %s" % i)
                imageRecord = CEOS.CEOSDB(xml=os.path.join(
                    xmlPrefix, 'alos/image_record.xml'),
                                          dataFile=fp)
                imageRecord.parse()

                tags.append(
                    float(imageRecord.
                          metadata['Sensor acquisition milliseconds of day']))
                data = fp.read(dataSize)
                pass
        ###Do parameter fit
        import numpy as np

        tarr = np.array(tags) - tags[0]
        ref = np.arange(tarr.size) / self.frame.PRF
        print('PRF: ', self.frame.PRF)
        ####Check every 20 microsecs
        off = np.arange(50) * 2.0e-5
        res = np.zeros(off.size)

        ###Check which offset produces the same millisec truncation
        ###Assumes PRF is correct
        for xx in range(off.size):
            ttrunc = np.floor((ref + off[xx]) * 1000)
            res[xx] = np.sum(tarr - ttrunc)

        res = np.abs(res)

        #        import matplotlib.pyplot as plt
        #        plt.plot(res)
        #        plt.show()

        delta = datetime.timedelta(seconds=np.argmin(res) * 2.0e-5)
        print('TIME OFFSET: ', delta)
        self.frame.sensingStart += delta
        self.frame.sensingMid += delta
        self.frame.sensingStop += delta
        return None
示例#3
0
class Generic(Component):
    """
    A class to parse generic SAR data stored in the HDF5 format
    """

    logging_name = 'isce.sensor.Generic'

    def __init__(self):
        super(Generic, self).__init__()
        self._hdf5File = None
        self.output = None
        self.frame = Frame()
        self.frame.configure()

        self.logger = logging.getLogger('isce.sensor.Generic')

        self.descriptionOfVariables = {}
        self.dictionaryOfVariables = {
            'HDF5': ['self._hdf5File', 'str', 'mandatory'],
            'OUTPUT': ['self.output', 'str', 'optional']
        }
        return None

    def getFrame(self):
        return self.frame

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

        self.populateMetadata(fp)
        fp.close()

    def populateMetadata(self, file):
        """
        Create the appropriate metadata objects from our HDF5 file
        """
        self._populatePlatform(file)
        self._populateInstrument(file)
        self._populateFrame(file)
        self._populateOrbit(file)

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

        platform.setMission(file['Platform'].attrs['Mission'])
        platform.setPlanet(Planet(pname='Earth'))
        platform.setAntennaLength(file['Platform'].attrs['Antenna Length'])

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

        instrument.setRadarWavelength(file['Instrument'].attrs['Wavelength'])
        instrument.setPulseRepetitionFrequency(
            file['Instrument'].attrs['Pulse Repetition Frequency'])
        instrument.setRangePixelSize(
            file['Instrument'].attrs['Range Pixel Size'])
        instrument.setPulseLength(file['Instrument'].attrs['Pulse Length'])
        instrument.setChirpSlope(file['Instrument'].attrs['Chirp Slope'])
        instrument.setRangeSamplingRate(
            file['Instrument'].attrs['Range Sampling Frequency'])
        instrument.setInPhaseValue(file['Frame'].attrs['In Phase Bias'])
        instrument.setQuadratureValue(file['Frame'].attrs['Quadrature Bias'])

    def _populateFrame(self, file):
        size = file['Frame'].shape
        start = DTU.parseIsoDateTime(file['Frame'].attrs['Sensing Start'])
        stop = DTU.parseIsoDateTime(file['Frame'].attrs['Sensing Stop'])
        deltaT = DTU.timeDeltaToSeconds(stop - start)
        mid = start + datetime.timedelta(microseconds=int(deltaT / 2.0 * 1e6))
        startingRange = file['Frame'].attrs['Starting Range']
        rangePixelSize = file['Instrument'].attrs['Range Pixel Size']
        farRange = startingRange + size[1] * rangePixelSize

        self.frame.setStartingRange(file['Frame'].attrs['Starting Range'])
        self.frame.setFarRange(farRange)
        self.frame.setNumberOfLines(size[0])
        self.frame.setNumberOfSamples(2 * size[1])
        self.frame.setSensingStart(start)
        self.frame.setSensingMid(mid)
        self.frame.setSensingStop(stop)

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

        orbit.setReferenceFrame('ECR')
        orbit.setOrbitSource(file['Orbit'].attrs['Source'])

        for i in range(len(file['Orbit']['Time'])):
            vec = StateVector()
            time = DTU.parseIsoDateTime(file['Orbit']['Time'][i])
            vec.setTime(time)
            vec.setPosition(list(file['Orbit']['Position'][i]))
            vec.setVelocity(list(file['Orbit']['Velocity'][i]))
            orbit.addStateVector(vec)

    def extractImage(self):
        try:
            file = h5py.File(self._hdf5File, 'r')
        except Exception as strerror:
            self.logger.error("IOError: %s" % strerror)
            return
        size = file['Frame'].shape
        dtype = self._translateDataType(file['Frame'].attrs['Image Type'])
        length = size[0]
        width = size[1]
        data = numpy.memmap(self.output,
                            dtype=dtype,
                            mode='w+',
                            shape=(length, width, 2))
        data[:, :, :] = file['Frame'][:, :, :]
        del data

        rawImage = isceobj.createRawImage()
        rawImage.setByteOrder('l')
        rawImage.setAccessMode('r')
        rawImage.setFilename(self.output)
        rawImage.setWidth(2 * width)
        rawImage.setXmin(0)
        rawImage.setXmax(2 * width)
        self.frame.setImage(rawImage)
        self.populateMetadata(file)

        file.close()

    def write(self, output, compression=None):
        """
        Given a frame object (appropriately populated) and an image, create
        an HDF5 from those objects.
        """
        if (not self.frame):
            self.logger.error("Frame not set")
            raise AttributeError("Frame not set")

        h5file = h5py.File(output, 'w')
        self._writeMetadata(h5file, compression)

    def _writeMetadata(self, h5file, compression=None):
        self._writePlatform(h5file)
        self._writeInstrument(h5file)
        self._writeFrame(h5file, compression)
        self._writeOrbit(h5file)

    def _writePlatform(self, h5file):
        platform = self.frame.getInstrument().getPlatform()
        if (not platform):
            self.logger.error("Platform not set")
            raise AttributeError("Platform not set")

        group = h5file.create_group('Platform')
        group.attrs['Mission'] = platform.getMission()
        group.attrs['Planet'] = platform.getPlanet().name
        group.attrs['Antenna Length'] = platform.getAntennaLength()

    def _writeInstrument(self, h5file):
        instrument = self.frame.getInstrument()
        if (not instrument):
            self.logger.error("Instrument not set")
            raise AttributeError("Instrument not set")

        group = h5file.create_group('Instrument')
        group.attrs['Wavelength'] = instrument.getRadarWavelength()
        group.attrs[
            'Pulse Repetition Frequency'] = instrument.getPulseRepetitionFrequency(
            )
        group.attrs['Range Pixel Size'] = instrument.getRangePixelSize()
        group.attrs['Pulse Length'] = instrument.getPulseLength()
        group.attrs['Chirp Slope'] = instrument.getChirpSlope()
        group.attrs[
            'Range Sampling Frequency'] = instrument.getRangeSamplingRate()
        group.attrs['In Phase Bias'] = instrument.getInPhaseValue()
        group.attrs['Quadrature Bias'] = instrument.getQuadratureValue()

    def _writeFrame(self, h5file, compression=None):
        group = self._writeImage(h5file, compression)
        group.attrs['Starting Range'] = self.frame.getStartingRange()
        group.attrs['Sensing Start'] = self.frame.getSensingStart().isoformat()
        group.attrs['Sensing Stop'] = self.frame.getSensingStop().isoformat()

    def _writeImage(self, h5file, compression=None):
        image = self.frame.getImage()
        if (not image):
            self.logger.error("Image not set")
            raise AttributeError("Image not set")
        filename = image.getFilename()
        length = image.getLength()
        width = image.getWidth()

        dtype = self._translateDataType(image.dataType)
        if (image.dataType == 'BYTE'):
            width = int(width / 2)

        self.logger.debug("Width: %s" % (width))
        self.logger.debug("Length: %s" % (length))
        data = numpy.memmap(filename,
                            dtype=dtype,
                            mode='r',
                            shape=(length, 2 * width))
        dset = h5file.create_dataset("Frame", (length, width, 2),
                                     dtype=dtype,
                                     compression=compression)
        dset.attrs['Image Type'] = image.dataType
        dset[:, :, 0] = data[:, ::2]
        dset[:, :, 1] = data[:, 1::2]
        del data

        return dset

    def _writeOrbit(self, h5file):
        # Add orbit information
        (time, position, velocity) = self._orbitToArray()
        group = h5file.create_group("Orbit")
        group.attrs['Source'] = self.frame.getOrbit().getOrbitSource()
        group.attrs['Reference Frame'] = self.frame.getOrbit(
        ).getReferenceFrame()
        timedset = h5file.create_dataset("Orbit/Time",
                                         time.shape,
                                         dtype=time.dtype)
        posdset = h5file.create_dataset("Orbit/Position",
                                        position.shape,
                                        dtype=numpy.float64)
        veldset = h5file.create_dataset("Orbit/Velocity",
                                        velocity.shape,
                                        dtype=numpy.float64)
        timedset[...] = time
        posdset[...] = position
        veldset[...] = velocity

    def _orbitToArray(self):
        orbit = self.frame.getOrbit()
        if (not orbit):
            self.logger.error("Orbit not set")
            raise AttributeError("Orbit not set")

        time = []
        position = []
        velocity = []
        for sv in orbit:
            timeString = sv.getTime().isoformat()
            time.append(timeString)
            position.append(sv.getPosition())
            velocity.append(sv.getVelocity())

        return numpy.array(time), numpy.array(position), numpy.array(velocity)

    def _translateDataType(self, imageType):
        dtype = ''
        if (imageType == 'BYTE'):
            dtype = 'int8'
        elif (imageType == 'CFLOAT'):
            dtype = 'float32'
        elif (imageType == 'SHORT'):
            dtype = 'int16'
        else:
            self.logger.error("Unknown data type %s" % (imageType))
            raise ValueError("Unknown data type %s" % (imageType))

        return dtype