Exemplo n.º 1
0
Arquivo: ERS.py Projeto: yunjunz/isce2
class ERS(Sensor):

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

    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._leaderFile = None
        self._imageFile = None
        self.frameList = []

        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(pname='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.warning(
                    "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())
        self.logger.info('Using ODR file: ' + orbitFile)

        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
        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
Exemplo n.º 2
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
Exemplo n.º 3
0
class ERS_SLC(Sensor):

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

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

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

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

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

    def getFrame(self):
        return self.frame

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

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

        self.populateMetadata()

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

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

        self._populateDoppler()

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

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

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

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

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

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

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


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

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

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

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

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

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

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


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

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

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

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

        prf = self.frame.instrument.getPulseRepetitionFrequency()

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

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

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

        self.dopplerRangeTime = [d0, d1, d2]

        return

    def extractDoppler(self):

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

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

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

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


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

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


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

        return quadratic



    def extractImage(self):
        import array
        import math

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

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

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

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

        outputArray.tofile(fp)
        fp.close()


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

        return frameNumber
Exemplo n.º 4
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
class COSMO_SkyMed_SLC(Sensor):
    """
    A class representing a Level1Product meta data.
    Level1Product(hdf5=h5filename) will parse the hdf5
    file and produce an object with attributes for metadata.
    """
    parameter_list = (HDF5, ) + Sensor.parameter_list
    logging_name = 'isce.Sensor.COSMO_SkyMed_SLC'
    family = 'cosmo_skymed_slc'

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

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

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

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

    def getFrame(self):
        return self.frame

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

        self.populateMetadata(fp)
        fp.close()

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

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

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

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

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

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

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

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

    def _populateFrame(self, file):

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

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

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

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

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

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

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

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

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

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

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

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

        extract_csk.extract_csk_slc(inFile_c, outFile_c)

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

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

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

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

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

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

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

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

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

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

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

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

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

        return quadratic
Exemplo n.º 6
0
class ALOS_SLC(Sensor):
    """
        Code to read CEOSFormat leader files for ALOS SLC data.
    """

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

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

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

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

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

        self.constants = {'antennaLength': 15}

    def getFrame(self):
        return self.frame

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

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

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

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

        rangePixelSize = Const.c/(2*fsamplookup)

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

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

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

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

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

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

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

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


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

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


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


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

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

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

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

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

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

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

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

        self.frame.setStartingRange(rngGate)

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

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

        return


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

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

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


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

    def _decodeSceneReferenceNumber(self,referenceNumber):
        return referenceNumber
Exemplo n.º 7
0
class KOMPSAT5(Component):
    """
    A class representing a Level1Product meta data.
    Level1Product(hdf5=h5filename) will parse the hdf5
    file and produce an object with attributes for metadata.
    """

    logging_name = 'isce.Sensor.KOMPSAT5'

    def __init__(self):
        super(KOMPSAT5, self).__init__()
        self.hdf5 = None
        self.output = None
        self.frame = Frame()
        self.frame.configure()
        # Some extra processing parameters unique to CSK SLC (currently)
        self.dopplerCoeffs = []
        self.rangeFirstTime = None
        self.rangeLastTime = None
        self.rangeRefTime = None
        self.refUTC = None

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

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

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

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

    def getFrame(self):
        return self.frame

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

        self.populateMetadata(fp)
        fp.close()

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

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

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

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

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

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

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

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

    def _populateFrame(self, file):

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

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

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

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

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

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

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

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

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

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

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

        extract_csk.extract_csk_slc(inFile_c, outFile_c)

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

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

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

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

        quadratic['a'] = fd_mid / self.frame.getInstrument(
        ).getPulseRepetitionFrequency()
        quadratic['b'] = 0.
        quadratic['c'] = 0.
        return quadratic
Exemplo n.º 8
0
class Radarsat2(Component):
    """
        A Class representing RadarSAT 2 data
    """
    def __init__(self):
        Component.__init__(self)        
        self.xml = None
        self.tiff = None
        self.output = None
        self.product = _Product()                                
        self.frame = Frame()
        self.frame.configure()
        
        self.descriptionOfVariables = {}
        self.dictionaryOfVariables = {'XML': ['self.xml','str','mandatory'],
                                      'TIFF': ['self.tiff','str','mandatory'],
                                      'OUTPUT': ['self.output','str','optional']}
        
                                               
    def getFrame(self):
        return self.frame
    
    def parse(self):
        try:
            fp = open(self.xml,'r')
        except IOError as strerr:
            print("IOError: %s" % strerr)
            return
        self._xml_root = ElementTree(file=fp).getroot()                     
        self.product.set_from_etnode(self._xml_root)
        self.populateMetadata()
        
        fp.close()
    
    def populateMetadata(self):
        """
            Create metadata objects from the metadata files
        """
        mission = self.product.sourceAttributes.satellite
        swath = self.product.sourceAttributes.radarParameters.beams
        frequency = self.product.sourceAttributes.radarParameters.radarCenterFrequency
        prf = self.product.sourceAttributes.radarParameters.prf        
        rangePixelSize = self.product.imageAttributes.rasterAttributes.sampledPixelSpacing
        rangeSamplingRate = Const.c/(2*rangePixelSize)        
        pulseLength = self.product.sourceAttributes.radarParameters.pulseLengths[0]
        pulseBandwidth = self.product.sourceAttributes.radarParameters.pulseBandwidths[0]
        polarization = self.product.sourceAttributes.radarParameters.polarizations
        lookSide = lookMap[self.product.sourceAttributes.radarParameters.antennaPointing.upper()]
        facility = self.product.imageGenerationParameters.generalProcessingInformation._processingFacility
        version = self.product.imageGenerationParameters.generalProcessingInformation.softwareVersion
        lines = self.product.imageAttributes.rasterAttributes.numberOfLines
        samples = self.product.imageAttributes.rasterAttributes.numberOfSamplesPerLine
        startingRange = self.product.imageGenerationParameters.slantRangeToGroundRange.slantRangeTimeToFirstRangeSample * (Const.c/2)
        incidenceAngle = (self.product.imageGenerationParameters.sarProcessingInformation.incidenceAngleNearRange + self.product.imageGenerationParameters.sarProcessingInformation.incidenceAngleFarRange)/2

        lineFlip =  (self.product.imageAttributes.rasterAttributes.lineTimeOrdering.upper() == 'DECREASING')

        if lineFlip:
            dataStopTime = self.product.imageGenerationParameters.sarProcessingInformation.zeroDopplerTimeFirstLine
            dataStartTime = self.product.imageGenerationParameters.sarProcessingInformation.zeroDopplerTimeLastLine
        else:
            dataStartTime = self.product.imageGenerationParameters.sarProcessingInformation.zeroDopplerTimeFirstLine
            dataStopTime = self.product.imageGenerationParameters.sarProcessingInformation.zeroDopplerTimeLastLine

        passDirection = self.product.sourceAttributes.orbitAndAttitude.orbitInformation.passDirection
        height = self.product.imageGenerationParameters.sarProcessingInformation._satelliteHeight

        ####Populate platform
        platform = self.frame.getInstrument().getPlatform()
        platform.setPlanet(Planet("Earth"))
        platform.setMission(mission)
        platform.setPointingDirection(lookSide)
        platform.setAntennaLength(15.0)

        ####Populate instrument
        instrument = self.frame.getInstrument()
        instrument.setRadarFrequency(frequency)
        instrument.setPulseRepetitionFrequency(prf)
        instrument.setPulseLength(pulseLength)
        instrument.setChirpSlope(pulseBandwidth/pulseLength)
        instrument.setIncidenceAngle(incidenceAngle)
        #self.frame.getInstrument().setRangeBias(0)
        instrument.setRangePixelSize(rangePixelSize)
        instrument.setRangeSamplingRate(rangeSamplingRate)
        instrument.setBeamNumber(swath)
        instrument.setPulseLength(pulseLength)


        #Populate Frame
        #self.frame.setSatelliteHeight(height)
        self.frame.setSensingStart(dataStartTime)
        self.frame.setSensingStop(dataStopTime)
        diffTime = DTUtil.timeDeltaToSeconds(dataStopTime - dataStartTime)/2.0
        sensingMid = dataStartTime + datetime.timedelta(microseconds=int(diffTime*1e6))
        self.frame.setSensingMid(sensingMid)
        self.frame.setPassDirection(passDirection)
        self.frame.setPolarization(polarization) 
        self.frame.setStartingRange(startingRange)
        self.frame.setFarRange(startingRange + (samples-1)*rangePixelSize)
        self.frame.setNumberOfLines(lines)
        self.frame.setNumberOfSamples(samples)
        self.frame.setProcessingFacility(facility)
        self.frame.setProcessingSoftwareVersion(version)
        
        # Initialize orbit objects
        # Read into temp orbit first. 
        # Radarsat 2 needs orbit extensions.
        tempOrbit = Orbit()

        self.frame.getOrbit().setOrbitSource('Header: ' + self.product.sourceAttributes.orbitAndAttitude.orbitInformation.orbitDataFile)
        self.frame.setPassDirection(passDirection)
        stateVectors = self.product.sourceAttributes.orbitAndAttitude.orbitInformation.stateVectors
        for i in range(len(stateVectors)):
            position = [stateVectors[i].xPosition, stateVectors[i].yPosition, stateVectors[i].zPosition]
            velocity = [stateVectors[i].xVelocity, stateVectors[i].yVelocity, stateVectors[i].zVelocity]
            vec = StateVector()            
            vec.setTime(stateVectors[i].timeStamp)
            vec.setPosition(position)
            vec.setVelocity(velocity)
            tempOrbit.addStateVector(vec)

        planet = self.frame.instrument.platform.planet
        orbExt = OrbitExtender(planet=planet)
        orbExt.configure()
        newOrb = orbExt.extendOrbit(tempOrbit)

        for sv in newOrb:
            self.frame.getOrbit().addStateVector(sv)


    def extractImage(self, verbose=True):
        '''
        Use gdal to extract the slc.
        '''

        try:
            from osgeo import gdal
        except ImportError:
            raise Exception('GDAL python bindings not found. Need this for RSAT2 / TandemX / Sentinel1A.')

        self.parse()

        width = self.frame.getNumberOfSamples()
        lgth  = self.frame.getNumberOfLines()
        lineFlip = (self.product.imageAttributes.rasterAttributes.lineTimeOrdering.upper() == 'DECREASING')
        pixFlip = (self.product.imageAttributes.rasterAttributes.pixelTimeOrdering.upper() == 'DECREASING')

        src = gdal.Open(self.tiff.strip(), gdal.GA_ReadOnly)
        cJ = np.complex64(1.0j)

        ####Images are small enough that we can do it all in one go - Piyush
        real = src.GetRasterBand(1).ReadAsArray(0,0,width,lgth)
        imag = src.GetRasterBand(2).ReadAsArray(0,0,width,lgth)

        if (real is None) or (imag is None):
            raise Exception('Input Radarsat2 SLC seems to not be a 2 band Int16 image.')

        data = real+cJ*imag

        real = None
        imag = None
        src = None

        if lineFlip:
            if verbose:
                print('Vertically Flipping data')
            data = np.flipud(data)

        if pixFlip:
            if verbose:
                print('Horizontally Flipping data')
            data = np.fliplr(data)

        data.tofile(self.output)

        ####
        slcImage = isceobj.createSlcImage()
        slcImage.setByteOrder('l')
        slcImage.setFilename(self.output)
        slcImage.setAccessMode('read')
        slcImage.setWidth(width)
        slcImage.setLength(lgth)
        slcImage.setXmin(0)
        slcImage.setXmax(width)
#        slcImage.renderHdr()
        self.frame.setImage(slcImage)


    def extractDoppler(self):
        '''
        self.parse()
        Extract doppler information as needed by mocomp
        '''
        ins = self.frame.getInstrument()
        dc = self.product.imageGenerationParameters.dopplerCentroid
        quadratic = {}

        r0 = self.frame.startingRange
        fs = ins.getRangeSamplingRate()
        tNear = 2*r0/Const.c

        tMid = tNear + 0.5*self.frame.getNumberOfSamples()/fs
        t0 = dc.dopplerCentroidReferenceTime
        poly = dc.dopplerCentroidCoefficients
       
        fd_mid = 0.0
        for kk in range(len(poly)):
            fd_mid += poly[kk] * (tMid - t0)**kk
        
        quadratic['a'] = fd_mid / ins.getPulseRepetitionFrequency()
        quadratic['b'] = 0.
        quadratic['c'] = 0.
        return quadratic
Exemplo n.º 9
0
class Sentinel1(Sensor):
    """
        A Class representing Sentinel1 StripMap data
    """

    family = 's1sm'
    logging = 'isce.sensor.S1_SM'

    parameter_list = (
        XML,
        TIFF,
        MANIFEST,
        SAFE,
        ORBIT_FILE,
        ORBIT_DIR,
        POLARIZATION,
    ) + Sensor.parameter_list

    def __init__(self, family='', name=''):

        super(Sentinel1,
              self).__init__(family if family else self.__class__.family,
                             name=name)

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

        self._xml_root = None

    def validateUserInputs(self):
        '''
        Validate inputs from user.
        Populate tiff and xml from SAFE folder name.
        '''

        import fnmatch
        import zipfile

        if not self.xml:
            if not self.safe:
                raise Exception('SAFE directory is not provided')

        ####First find annotation file
        ####Dont need swath number when driving with xml and tiff file
        if not self.xml:
            swathid = 's1?-s?-slc-{}'.format(self.polarization)

        dirname = self.safe
        if not self.xml:
            match = None

            if dirname.endswith('.zip'):
                pattern = os.path.join('*SAFE', 'annotation',
                                       swathid) + '*.xml'
                zf = zipfile.ZipFile(dirname, 'r')
                match = fnmatch.filter(zf.namelist(), pattern)
                zf.close()

                if (len(match) == 0):
                    raise Exception(
                        'No annotation xml file found in zip file: {0}'.format(
                            dirname))

                ####Add /vsizip at the start to make it a zip file
                self.xml = '/vsizip/' + os.path.join(dirname, match[0])

            else:
                pattern = os.path.join('annotation', swathid) + '*.xml'
                match = glob.glob(os.path.join(dirname, pattern))

                if (len(match) == 0):
                    raise Exception(
                        'No annotation xml file found in {0}'.format(dirname))

                self.xml = match[0]

        if not self.xml:
            raise Exception('No annotation files found')

        print('Input XML file: ', self.xml)

        ####Find TIFF file
        if (not self.tiff) and (self.safe):
            match = None

            if dirname.endswith('.zip'):
                pattern = os.path.join('*SAFE', 'measurement',
                                       swathid) + '*.tiff'
                zf = zipfile.ZipFile(dirname, 'r')
                match = fnmatch.filter(zf.namelist(), pattern)
                zf.close()

                if (len(match) == 0):
                    raise Exception(
                        'No tiff file found in zip file: {0}'.format(dirname))

                ####Add /vsizip at the start to make it a zip file
                self.tiff = '/vsizip/' + os.path.join(dirname, match[0])

            else:
                pattern = os.path.join('measurement', swathid) + '*.tiff'
                match = glob.glob(os.path.join(dirname, pattern))

                if len(match) == 0:
                    raise Exception(
                        'No tiff file found in directory: {0}'.format(dirname))

                self.tiff = match[0]

            print('Input TIFF files: ', self.tiff)

        ####Find manifest files
        if self.safe:
            if dirname.endswith('.zip'):
                pattern = '*SAFE/manifest.safe'
                zf = zipfile.ZipFile(dirname, 'r')
                match = fnmatch.filter(zf.namelist(), pattern)
                zf.close()
                self.manifest = '/vsizip/' + os.path.join(dirname, match[0])
            else:
                self.manifest = os.path.join(dirname, 'manifest.safe')

            print('Manifest files: ', self.manifest)

        return

    def getFrame(self):
        return self.frame

    def parse(self):
        '''
        Actual parsing of the metadata for the product.
        '''
        from isceobj.Sensor.TOPS.Sentinel1 import s1_findOrbitFile
        ###Check user inputs
        self.validateUserInputs()

        if self.xml.startswith('/vsizip'):
            import zipfile
            parts = self.xml.split(os.path.sep)

            if parts[2] == '':
                parts[2] = os.path.sep

            zipname = os.path.join(*(parts[2:-3]))
            fname = os.path.join(*(parts[-3:]))

            zf = zipfile.ZipFile(zipname, 'r')
            xmlstr = zf.read(fname)
            zf.close()
        else:
            with open(self.xml, 'r') as fid:
                xmlstr = fid.read()

        self._xml_root = ET.fromstring(xmlstr)
        self.populateMetadata()

        if self.manifest:
            self.populateIPFVersion()
        else:
            self.frame.setProcessingFacility('ESA')
            self.frame.setProcessingSoftwareVersion('IPFx.xx')

        if not self.orbitFile:
            if self.orbitDir:
                self.orbitFile = s1_findOrbitFile(
                    self.orbitDir,
                    self.frame.sensingStart,
                    self.frame.sensingStop,
                    mission=self.frame.getInstrument().getPlatform(
                    ).getMission())

        if self.orbitFile:
            orb = self.extractPreciseOrbit()
            self.frame.orbit.setOrbitSource(os.path.basename(self.orbitFile))
        else:
            orb = self.extractOrbitFromAnnotation()
            self.frame.orbit.setOrbitSource('Annotation')

        for sv in orb:
            self.frame.orbit.addStateVector(sv)

    def grab_from_xml(self, path):
        try:
            res = self._xml_root.find(path).text
        except:
            raise Exception('Tag= %s not found' % (path))

        if res is None:
            raise Exception('Tag = %s not found' % (path))

        return res

    def convertToDateTime(self, string):
        dt = datetime.datetime.strptime(string, "%Y-%m-%dT%H:%M:%S.%f")
        return dt

    def populateMetadata(self):
        """
            Create metadata objects from the metadata files
        """
        ####Set each parameter one - by - one
        mission = self.grab_from_xml('adsHeader/missionId')
        swath = self.grab_from_xml('adsHeader/swath')
        polarization = self.grab_from_xml('adsHeader/polarisation')

        frequency = float(
            self.grab_from_xml(
                'generalAnnotation/productInformation/radarFrequency'))
        passDirection = self.grab_from_xml(
            'generalAnnotation/productInformation/pass')

        rangePixelSize = float(
            self.grab_from_xml(
                'imageAnnotation/imageInformation/rangePixelSpacing'))
        azimuthPixelSize = float(
            self.grab_from_xml(
                'imageAnnotation/imageInformation/azimuthPixelSpacing'))
        rangeSamplingRate = Const.c / (2.0 * rangePixelSize)
        prf = 1.0 / float(
            self.grab_from_xml(
                'imageAnnotation/imageInformation/azimuthTimeInterval'))

        lines = int(
            self.grab_from_xml(
                'imageAnnotation/imageInformation/numberOfLines'))
        samples = int(
            self.grab_from_xml(
                'imageAnnotation/imageInformation/numberOfSamples'))

        startingRange = float(
            self.grab_from_xml(
                'imageAnnotation/imageInformation/slantRangeTime')
        ) * Const.c / 2.0
        incidenceAngle = float(
            self.grab_from_xml(
                'imageAnnotation/imageInformation/incidenceAngleMidSwath'))
        dataStartTime = self.convertToDateTime(
            self.grab_from_xml(
                'imageAnnotation/imageInformation/productFirstLineUtcTime'))
        dataStopTime = self.convertToDateTime(
            self.grab_from_xml(
                'imageAnnotation/imageInformation/productLastLineUtcTime'))

        pulseLength = float(
            self.grab_from_xml(
                'generalAnnotation/downlinkInformationList/downlinkInformation/downlinkValues/txPulseLength'
            ))
        chirpSlope = float(
            self.grab_from_xml(
                'generalAnnotation/downlinkInformationList/downlinkInformation/downlinkValues/txPulseRampRate'
            ))
        pulseBandwidth = pulseLength * chirpSlope

        ####Sentinel is always right looking
        lookSide = -1

        #        height = self.product.imageGenerationParameters.sarProcessingInformation._satelliteHeight

        ####Populate platform
        platform = self.frame.getInstrument().getPlatform()
        platform.setPlanet(Planet(pname="Earth"))
        platform.setMission(mission)
        platform.setPointingDirection(lookSide)
        platform.setAntennaLength(2 * azimuthPixelSize)

        ####Populate instrument
        instrument = self.frame.getInstrument()
        instrument.setRadarFrequency(frequency)
        instrument.setPulseRepetitionFrequency(prf)
        instrument.setPulseLength(pulseLength)
        instrument.setChirpSlope(pulseBandwidth / pulseLength)
        instrument.setIncidenceAngle(incidenceAngle)
        #self.frame.getInstrument().setRangeBias(0)
        instrument.setRangePixelSize(rangePixelSize)
        instrument.setRangeSamplingRate(rangeSamplingRate)
        instrument.setBeamNumber(swath)
        instrument.setPulseLength(pulseLength)

        #Populate Frame
        #self.frame.setSatelliteHeight(height)
        self.frame.setSensingStart(dataStartTime)
        self.frame.setSensingStop(dataStopTime)
        diffTime = DTUtil.timeDeltaToSeconds(dataStopTime -
                                             dataStartTime) / 2.0
        sensingMid = dataStartTime + datetime.timedelta(
            microseconds=int(diffTime * 1e6))
        self.frame.setSensingMid(sensingMid)
        self.frame.setPassDirection(passDirection)
        self.frame.setPolarization(polarization)
        self.frame.setStartingRange(startingRange)
        self.frame.setFarRange(startingRange + (samples - 1) * rangePixelSize)
        self.frame.setNumberOfLines(lines)
        self.frame.setNumberOfSamples(samples)

        self.frame.setPassDirection(passDirection)

    def extractOrbitFromAnnotation(self):
        '''
        Extract orbit information from xml node.
        '''

        node = self._xml_root.find('generalAnnotation/orbitList')
        frameOrbit = Orbit()
        frameOrbit.setOrbitSource('Header')

        for child in node:
            timestamp = self.convertToDateTime(child.find('time').text)
            pos = []
            vel = []
            posnode = child.find('position')
            velnode = child.find('velocity')
            for tag in ['x', 'y', 'z']:
                pos.append(float(posnode.find(tag).text))

            for tag in ['x', 'y', 'z']:
                vel.append(float(velnode.find(tag).text))

            vec = StateVector()
            vec.setTime(timestamp)
            vec.setPosition(pos)
            vec.setVelocity(vel)
            frameOrbit.addStateVector(vec)

        planet = self.frame.instrument.platform.planet
        orbExt = OrbitExtender(planet=planet)
        orbExt.configure()
        newOrb = orbExt.extendOrbit(frameOrbit)

        return newOrb

    def extractPreciseOrbit(self):
        '''
        Extract precise orbit from given Orbit file.
        '''
        try:
            fp = open(self.orbitFile, 'r')
        except IOError as strerr:
            print("IOError: %s" % strerr)
            return

        _xml_root = ET.ElementTree(file=fp).getroot()

        node = _xml_root.find('Data_Block/List_of_OSVs')

        orb = Orbit()
        orb.configure()

        margin = datetime.timedelta(seconds=40.0)
        tstart = self.frame.getSensingStart() - margin
        tend = self.frame.getSensingStop() + margin

        for child in node:
            timestamp = self.convertToDateTime(child.find('UTC').text[4:])

            if (timestamp >= tstart) and (timestamp < tend):

                pos = []
                vel = []

                for tag in ['VX', 'VY', 'VZ']:
                    vel.append(float(child.find(tag).text))

                for tag in ['X', 'Y', 'Z']:
                    pos.append(float(child.find(tag).text))

                vec = StateVector()
                vec.setTime(timestamp)
                vec.setPosition(pos)
                vec.setVelocity(vel)
                orb.addStateVector(vec)

        fp.close()

        return orb

    def extractImage(self):
        """
           Use gdal python bindings to extract image
        """
        try:
            from osgeo import gdal
        except ImportError:
            raise Exception(
                'GDAL python bindings not found. Need this for RSAT2/ TandemX / Sentinel1A.'
            )

        self.parse()
        width = self.frame.getNumberOfSamples()
        lgth = self.frame.getNumberOfLines()

        src = gdal.Open(self.tiff.strip(), gdal.GA_ReadOnly)
        band = src.GetRasterBand(1)
        fid = open(self.output, 'wb')
        for ii in range(lgth):
            data = band.ReadAsArray(0, ii, width, 1)
            data.tofile(fid)

        fid.close()
        src = None
        band = None

        ####
        slcImage = isceobj.createSlcImage()
        slcImage.setByteOrder('l')
        slcImage.setFilename(self.output)
        slcImage.setAccessMode('read')
        slcImage.setWidth(self.frame.getNumberOfSamples())
        slcImage.setLength(self.frame.getNumberOfLines())
        slcImage.setXmin(0)
        slcImage.setXmax(self.frame.getNumberOfSamples())
        self.frame.setImage(slcImage)

    def extractDoppler(self):
        '''
        self.parse()
        Extract doppler information as needed by mocomp
        '''
        from isceobj.Util import Poly1D

        node = self._xml_root.find('dopplerCentroid/dcEstimateList')

        tdiff = 1.0e9
        dpoly = None

        for index, burst in enumerate(node):
            refTime = self.convertToDateTime(burst.find('azimuthTime').text)

            delta = abs((refTime - self.frame.sensingMid).total_seconds())
            if delta < tdiff:
                tdiff = delta
                r0 = 0.5 * Const.c * float(burst.find('t0').text)
                coeffs = [
                    float(val)
                    for val in burst.find('dataDcPolynomial').text.split()
                ]

                poly = Poly1D.Poly1D()
                poly.initPoly(order=len(coeffs) - 1)
                poly.setMean(r0)
                poly.setNorm(0.5 * Const.c)
                poly.setCoeffs(coeffs)

                dpoly = poly

        if dpoly is None:
            raise Exception(
                'Could not extract Doppler information for S1 scene')

        ###Part for insarApp
        ###Should be removed in the future
        rmid = self.frame.startingRange + 0.5 * self.frame.getNumberOfSamples(
        ) * self.frame.getInstrument().getRangePixelSize()

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

        ###Actual Doppler Polynomial for accurate processing
        ###Will be used in roiApp
        pix = np.linspace(0,
                          self.frame.getNumberOfSamples(),
                          num=dpoly._order + 2)
        rngs = self.frame.startingRange + pix * self.frame.getInstrument(
        ).getRangePixelSize()
        evals = dpoly(rngs)
        fit = np.polyfit(pix, evals, dpoly._order)
        self.frame._dopplerVsPixel = list(fit[::-1])
        print('Doppler Fit : ', fit[::-1])

        return quadratic

    def populateIPFVersion(self):
        '''
        Get IPF version from the manifest file.
        '''

        try:
            if self.manifest.startswith('/vsizip'):
                import zipfile
                parts = self.manifest.split(os.path.sep)
                if parts[2] == '':
                    parts[2] = os.path.sep
                zipname = os.path.join(*(parts[2:-2]))
                fname = os.path.join(*(parts[-2:]))
                print('MANS: ', zipname, fname)

                zf = zipfile.ZipFile(zipname, 'r')
                xmlstr = zf.read(fname)

            else:
                with open(self.manifest, 'r') as fid:
                    xmlstr = fid.read()

            ####Setup namespace
            nsp = "{http://www.esa.int/safe/sentinel-1.0}"

            root = ET.fromstring(xmlstr)

            elem = root.find('.//metadataObject[@ID="processing"]')

            rdict = elem.find('.//xmlData/' + nsp + 'processing/' + nsp +
                              'facility').attrib
            self.frame.setProcessingFacility(rdict['site'] + ', ' +
                                             rdict['country'])

            rdict = elem.find('.//xmlData/' + nsp + 'processing/' + nsp +
                              'facility/' + nsp + 'software').attrib

            self.frame.setProcessingSoftwareVersion(rdict['name'] + ' ' +
                                                    rdict['version'])

        except:  ###Not a critical error ... continuing
            print(
                'Could not read version number successfully from manifest file: ',
                self.manifest)
            pass

        return
class UAVSAR_HDF5_SLC(Sensor):
    """
    A class representing a Level1Product meta data.
    Level1Product(hdf5=h5filename) will parse the hdf5
    file and produce an object with attributes for metadata.
    """
    parameter_list = (HDF5, FREQUENCY, POLARIZATION) + Sensor.parameter_list

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

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

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

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

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

    def getFrame(self):
        return self.frame

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

        self.populateMetadata(fp)
        fp.close()

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

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

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

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

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

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

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

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

        incangle = 0.0
        instrument.setIncidenceAngle(incangle)

    def _populateFrame(self, file):

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

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

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

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

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

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

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

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

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

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

    def extractImage(self):

        import numpy as np
        import h5py

        self.parse()

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

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

        fid.close()

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

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

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

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

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

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

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

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

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

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

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

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

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

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

        return quadratic
Exemplo n.º 11
0
class Risat1(Sensor):
    """
        Code to read CEOSFormat leader files for Risat-1 SAR data.
    """
    family = "risat1"
    logging_name = 'isce.sensor.Risat1'
    parameter_list = (IMAGEFILE, LEADERFILE, METAFILE) + 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.lineDirection = None
        self.pixelDirection = 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()

    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 height: ', 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.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'])
        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.setChirpSlope(7.5e12)
        ins.setInPhaseValue(127.0)
        ins.setQuadratureValue(127.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')

        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=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 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()

        #####Extend the orbits by a few points
        planet = self.frame.instrument.platform.planet
        orbExt = OrbitExtender()
        orbExt.configure()
        orbExt._newPoints = 4
        newOrb = orbExt.extendOrbit(wgsorb)

        orb = self.frame.getOrbit()

        for sv in newOrb:
            orb.addStateVector(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()

        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)

        dr = self.frame.instrument.rangePixelSize
        self.frame.setStartingRange(self.imageFile.nearRange)
        self.frame.setFarRange(self.imageFile.nearRange +
                               (self.imageFile.width - 1) * dr)
        self.doppler_coeff = self.imageFile.dopplerCoeff
        self.frame.getInstrument().setPulseRepetitionFrequency(
            self.imageFile.prf)
        self.frame.instrument.setPulseLength(self.imageFile.chirpLength)

        print('Pulse length: ', self.imageFile.chirpLength)
        print('Roll angle: ', self.imageFile.roll)

        if self.imageFile.roll > 0.:
            self.frame.instrument.platform.setPointingDirection(1)
        else:
            self.frame.instrument.platform.setPointingDirection(-1)

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

        return

    def extractDoppler(self):
        '''
        Evaluate the doppler polynomial and return the average value for now.
        '''
        print('Doppler: ', self.doppler_coeff)
        quadratic = {}
        quadratic['a'] = self.doppler_coeff[1] / self.frame.getInstrument(
        ).getPulseRepetitionFrequency()
        quadratic['b'] = 0.
        quadratic['c'] = 0.
        return quadratic

    def _decodeSceneReferenceNumber(self, referenceNumber):
        return referenceNumber
Exemplo n.º 12
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
Exemplo n.º 13
0
class ICEYE_SLC(Sensor):
    """
    A class representing a Level1Product meta data.
    Level1Product(hdf5=h5filename) will parse the hdf5
    file and produce an object with attributes for metadata.
    """
    parameter_list = (HDF5, APPLY_SLANT_RANGE_PHASE) + Sensor.parameter_list
    logging_name = 'isce.Sensor.ICEYE_SLC'
    family = 'iceye_slc'

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

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

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

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

    def getFrame(self):
        return self.frame

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

        self.populateMetadata(fp)
        fp.close()

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

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

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

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

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

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

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

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

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

    def _populateFrame(self, file):

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

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

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

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

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

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

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

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

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

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

        self.parse()

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

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

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

        fid.close()

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

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

        quadratic = {}

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

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

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

        return quadratic