Beispiel #1
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
Beispiel #2
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
Beispiel #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
Beispiel #4
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
Beispiel #5
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
Beispiel #6
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
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
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