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

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

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

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

        self.descriptionOfVariables = {}
        self.dictionaryOfVariables = {
            'LEADERFILE': ['self._leaderFile', 'str', 'mandatory'],
            'IMAGEFILE': ['self._imageFile', 'str', 'mandatory'],
            'PARFILE': ['self._parFile', 'str', 'optional'],
            'OUTPUT': ['self.output', 'str', 'optional']
        }
Example #2
0
    def __init__(self, name=''):
        super().__init__(family=self.__class__.family, name=name)
        self.imageFile = None
        self.leaderFile = None

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

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

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

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

        self.RxPolMap = {
            1: 'V',
            2: 'H',
        }
    def __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
Example #4
0
 def __init__(self, name=''):
     super().__init__(family=self.family, name=name)
     self.frame = Frame()
     self.frame.configure()
     self._elp = None
     self._peg = None
     elp = self.elp
     return
Example #5
0
    def __init__(self, sar, obj):
        self.sar = sar
        self.obj = obj
        self.missionId = self.obj.xpath('.//missionId/text()')[0]
        self.missionId_char = MISSION_RE.search(self.missionId).group(1)
        self.frame = Frame()
        self.frame.configure()

        self.parse()
Example #6
0
    def extractImage(self):
        # just in case there was only one image and it was passed as a str
        #instead of a list with only one element
        if (isinstance(self._imageFileList, str)):
            self._imageFileList = [self._imageFileList]
            self._leaderFileList = [self._leaderFileList]
        if (len(self._imageFileList) != len(self._leaderFileList)):
            self.logger.error(
                "Number of leader files different from number of image files.")
            raise RuntimeError
        self.frameList = []
        for i in range(len(self._imageFileList)):
            appendStr = "_" + str(i)
            #if only one file don't change the name
            if (len(self._imageFileList) == 1):
                appendStr = ''

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

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

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

        self.logger = logging.getLogger(self.logging_name)

        self.frameList = []

        return None
Example #8
0
 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']}
Example #9
0
    def parse(self):
        """
            Parse both imagery and create
            objects representing the platform, instrument and scene
        """

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

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

        self.populateMetadata()
Example #10
0
    def parse(self):
        """
            Parse both imagery and instrument files and create
            objects representing the platform, instrument and scene
        """

        self.frame = Frame()
        self.frame.configure()
        self._xemtFileParser = XEMTFile(fileName=self.xemtFile)
        self._xemtFileParser.parse()
        self._xmlFileParser = XMLFile(fileName=self.xmlFile)
        self._xmlFileParser.parse()
        self.populateMetadata()
Example #11
0
    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}
Example #12
0
 def __init__(self):
     # These are attributes representing the starting time and stopping
     # time of the track
     # As well as the early and late times (range times) of the track 
     self._startTime = datetime.datetime(year=datetime.MAXYEAR,month=1,day=1)
     self._stopTime = datetime.datetime(year=datetime.MINYEAR,month=1,day=1)
     # Hopefully this number is large
     # enough, Python doesn't appear to have a MAX_FLT variable
     self._nearRange = float_info.max
     self._farRange = 0.0 
     self._frames = []
     self._frame = Frame()
     self._lastFile = ''
     return None
Example #13
0
    def __init__(self):
        super(Sensor, self).__init__()
        self.output = None
        self.frame = Frame()
        self.frame.configure()

        self.logger = logging.getLogger(self.logging_name)

        self.frameList = []
        self.descriptionOfVariables = {}
        self.dictionaryOfVariables = {
            'OUTPUT': ['self.output', 'str', 'optional']
        }
        return None
Example #14
0
    def __init__(self):
        super(Generic, self).__init__()
        self._hdf5File = None
        self.output = None
        self.frame = Frame()
        self.frame.configure()

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

        self.descriptionOfVariables = {}
        self.dictionaryOfVariables = {
            'HDF5': ['self._hdf5File','str','mandatory'],
            'OUTPUT': ['self.output','str','optional']}
        return None
Example #15
0
    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}
Example #16
0
    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 __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
Example #18
0
    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}
Example #19
0
    def __init__(self):
        Component.__init__(self)
        self.xml = None
        self.tiff = None
        self.output = None
        self.gdal_translate = None
        self.frame = Frame()
        self.frame.configure()

        self._xml_root = None
        self.descriptionOfVariables = {}
        self.dictionaryOfVariables = {
            'XML': ['self.xml', 'str', 'mandatory'],
            'TIFF': ['self.tiff', 'str', 'mandatory'],
            'OUTPUT': ['self.output', 'str', 'optional'],
            'GDAL_TRANSLATE': ['self.gdal_translate', 'str', 'optional']
        }
Example #20
0
    def __init__(self):
        Component.__init__(self)
        self.xml = None
        self.tiff = None
        self.orbitfile = None
        self.output = None
        self.frame = Frame()
        self.frame.configure()

        self._xml_root = None
        self.descriptionOfVariables = {}
        self.dictionaryOfVariables = {
            'XML': ['self.xml', 'str', 'mandatory'],
            'TIFF': ['self.tiff', 'str', 'mandatory'],
            'ORBITFILE': ['self.orbitfile', 'str', 'optional'],
            'OUTPUT': ['self.output', 'str', 'optional']
        }
Example #21
0
    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
Example #22
0
    def parse(self):
        """
            Parse both imagery and instrument files and create
            objects representing the platform, instrument and scene
        """

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

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

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

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

        self.populateMetadata()
Example #23
0
 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
Example #24
0
    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
Example #25
0
    def extractImage(self):
        """Extract the raw image data"""
        import os
        from ctypes import cdll, c_char_p
        extract_csk = cdll.LoadLibrary(os.path.dirname(__file__)+'/csk.so')
        # Prepare and run the C-based extractor

        #check if the input is a string. if so put it into one element list
        if(isinstance(self.hdf5FileList,str)):
            self.hdf5FileList = [self.hdf5FileList]

        for i in range(len(self.hdf5FileList)):
            #need to create a new instance every time
            self.frame = Frame()
            self.frame.configure()
            appendStr = '_' + str(i)
            # if more than one file to contatenate that create different outputs
            # but suffixing _i
            if(len(self.hdf5FileList) == 1):
                appendStr = ''
            outputNow = self.output + appendStr
            self.hdf5 = self.hdf5FileList[i]
            inFile_c = c_char_p(bytes(self.hdf5,'utf-8'))
            outFile_c = c_char_p(bytes(outputNow,'utf-8'))

            extract_csk.extract_csk(inFile_c,outFile_c)
            # Now, populate the metadata
            try:
                fp = h5py.File(self.hdf5,'r')
            except Exception as strerror:
                self.logger.error("IOError: %s\n" % strerror)
                return
            self.populateMetadata(file=fp)
            self.populateImage(outputNow)
            self._populateExtras(fp)

            fp.close()
            self.frameList.append(self.frame)
            createAuxFile(self.frame,outputNow + '.aux')
        self._imageFileList = self.hdf5FileList
        return tkfunc(self)
Example #26
0
    def __init__(self):
        Component.__init__(self)
        self._leaderFile = None
        self._imageFileList = ''
        self._leaderFileList = ''
        self._imageFile = None
        self._orbitDir = None # Use this for Delft Orbit files
        self._orbitFile = None # Use this for PDS Orbit files for now
        self._orbitType = None
        self.frameList = []
        self.output = None

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


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

        # Constants are from
        # J. J. Mohr and S. N. Madsen. Geometric calibration of ERS satellite
        # SAR images. IEEE T. Geosci. Remote, 39(4):842-850, Apr. 2001.
        self.constants = {'polarization': 'VV',
                          'antennaLength': 10,
                          'lookDirection': 'RIGHT',
                          'chirpPulseBandwidth': 15.50829e6,
                          'rangeSamplingRate': 18.962468e6,
                          'delayTime':6.622e-6,
                          'iBias': 15.5,
                          'qBias': 15.5}
        return None
Example #27
0
class ALOS(Sensor):
    """Code to read CEOSFormat leader files for ALOS SAR data.
    The tables used to create this parser are based on document number
    ER-IS-EPO-GS-5902.1 from the European
    Space Agency.
    """

    family = 'alos'
    logging_name = 'isce.sensor.ALOS'

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

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

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

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

    HEADER_LINES = 720

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

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

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

    #Kosal

    def getFrame(self):
        return self.frame

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

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

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

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

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

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

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

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

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

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

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

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

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

        self.frame.frameNumber = frame
        self.frame.setOrbitNumber(
            self.leaderFile.sceneHeaderRecord.metadata['Orbit number'])
        self.frame.setStartingRange(self.imageFile.startingRange)
        self.frame.setFarRange(farRange)
        self.frame.setProcessingFacility(
            self.leaderFile.sceneHeaderRecord.
            metadata['Processing facility identifier'])
        self.frame.setProcessingSystem(
            self.leaderFile.sceneHeaderRecord.
            metadata['Processing system identifier'])
        self.frame.setProcessingSoftwareVersion(
            self.leaderFile.sceneHeaderRecord.
            metadata['Processing version identifier'])
        self.frame.setPolarization(polarization)
        self.frame.setNumberOfLines(self.imageFile.length)
        self.frame.setNumberOfSamples(self.imageFile.width)

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

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

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

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

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

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

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

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

    def _populateDistortions(self):
        return None

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

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

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

        prf = self.frame.getInstrument().getPulseRepetitionFrequency()
        senStart = self.frame.getSensingStart()
        numPulses = self.frame.numberOfLines
        # the aux files has two entries per line. day of the year and microseconds in the day
        musec0 = (senStart.hour * 3600 + senStart.minute * 60 +
                  senStart.second) * 10**6 + senStart.microsecond
        maxMusec = (
            24 *
            3600) * 10**6  #use it to check if we went across  a day. very rare
        day0 = (datetime.datetime(senStart.year, senStart.month, senStart.day)
                - datetime.datetime(senStart.year, 1, 1)).days + 1
        outputArray = array.array('d', [0] * 2 * numPulses)
        self.frame.auxFile = outputNow + '.aux'
        fp = open(self.frame.auxFile, 'wb')
        j = -1
        for i1 in range(numPulses):
            j += 1
            musec = round((j / prf) * 10**6) + musec0
            if musec >= maxMusec:
                day0 += 1
                musec0 = musec % maxMusec
                musec = musec0
                j = 0
            outputArray[2 * i1] = day0
            outputArray[2 * i1 + 1] = musec

        outputArray.tofile(fp)
        fp.close()

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

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

    def extractImage(self):
        if (len(self._imageFileList) != len(self._leaderFileList)):
            self.logger.error(
                "Number of leader files different from number of image files.")
            raise RuntimeError
        self.frameList = []
        for i in range(len(self._imageFileList)):
            appendStr = "_" + str(i)
            #if only one file don't change the name
            if (len(self._imageFileList) == 1):
                appendStr = ''

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

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

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

    def _decodeSceneReferenceNumber(self, referenceNumber):
        return referenceNumber

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

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

        return qualityString

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

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

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

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

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

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

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

        res = np.abs(res)

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

        delta = datetime.timedelta(seconds=np.argmin(res) * 2.0e-5)
        print('TIME OFFSET: ', delta)
        self.frame.sensingStart += delta
        self.frame.sensingMid += delta
        self.frame.sensingStop += delta
        return None
class COSMO_SkyMed(Sensor):
    """
        A class to parse COSMO-SkyMed metadata
    """

    parameter_list = (HDF5, ) + Sensor.parameter_list
    logging_name = "isce.sensor.COSMO_SkyMed"
    family = 'cosmo_skymed'

    def __init__(self, family='', name=''):
        super().__init__(family if family else self.__class__.family,
                         name=name)
        self.hdf5 = None
        #used to allow refactoring on tkfunc
        self._imageFileList = None

        ###Specific doppler functions for CSK
        self.dopplerRangeTime = []
        self.dopplerAzimuthTime = []
        self.azimuthRefTime = None
        self.rangeRefTime = None
        self.rangeFirstTime = None
        self.rangeLastTime = None

        ## make this a class attribute, and a Sensor.Constant--not a dictionary.
        self.constants = {'iBias': 127.5, 'qBias': 127.5}
        return None

    ## Note: this breaks the ISCE convention of getters.
    def getFrame(self):
        return self.frame

    #jng  parse or parse_context never used
    def parse(self):
        try:
            fp = h5py.File(self.hdf5, 'r')
        except Exception as strerror:
            self.logger.error("IOError: %s\n" % strerror)
            return None

        self.populateMetadata(file=fp)
        fp.close()

    ## Use h5's context management-- TODO: debug and install as 'parse'
    def parse_context(self):
        try:
            with h5py.File(self.hdf5, 'r') as fp:
                self.populateMetadata(file=fp)
        except Exception as strerror:
            self.logger.error("IOError: %s\n" % strerror)

        return None

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

        if np.isnan(file['S01'].attrs['Equivalent First Column Time']) and (
                len(file['S01/B001'].attrs['Range First Times']) > 1):
            raise NotImplementedError(
                'Current CSK reader does not handle RAW data not adjusted for SWST shifts'
            )

        platform.setMission(
            file.attrs['Satellite ID'])  # Could use Mission ID as well
        platform.setPlanet(Planet(pname="Earth"))
        platform.setPointingDirection(
            self.lookMap[file.attrs['Look Side'].decode('utf-8')])
        platform.setAntennaLength(file.attrs['Antenna Length'])

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

        rangePixelSize = Const.c / (2 * file['S01'].attrs['Sampling Rate'])

        instrument.setRadarWavelength(file.attrs['Radar Wavelength'])
        instrument.setPulseRepetitionFrequency(file['S01'].attrs['PRF'])
        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.setInPhaseValue(self.constants['iBias'])
        instrument.setQuadratureValue(self.constants['qBias'])
        instrument.setBeamNumber(file.attrs['Multi-Beam ID'])

    def _populateFrame(self, file):
        rft = file['S01']['B001'].attrs['Range First Times'][0]
        slantRange = rft * Const.c / 2.0
        sensingStart = self._parseNanoSecondTimeStamp(
            file.attrs['Scene Sensing Start UTC'])
        sensingStop = self._parseNanoSecondTimeStamp(
            file.attrs['Scene Sensing Stop UTC'])
        centerTime = DTUtil.timeDeltaToSeconds(sensingStop -
                                               sensingStart) / 2.0
        sensingMid = sensingStart + datetime.timedelta(
            microseconds=int(centerTime * 1e6))

        self.frame.setStartingRange(slantRange)
        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']['B001'].shape[0])
        self.frame.setNumberOfSamples(file['S01']['B001'].shape[1])
        self.frame.setSensingStart(sensingStart)
        self.frame.setSensingMid(sensingMid)
        self.frame.setSensingStop(sensingStop)

        rangePixelSize = self.frame.getInstrument().getRangePixelSize()
        farRange = slantRange + self.frame.getNumberOfSamples() * 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 populateImage(self, filename):
        rawImage = isceobj.createRawImage()
        rawImage.setByteOrder('l')
        rawImage.setFilename(filename)
        rawImage.setAccessMode('read')
        rawImage.setWidth(2 * self.frame.getNumberOfSamples())
        rawImage.setXmax(2 * self.frame.getNumberOfSamples())
        rawImage.setXmin(0)
        self.getFrame().setImage(rawImage)

    def _populateExtras(self, file):
        """
        Populate some extra fields.
        """

        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']['B001'].attrs['Range First Times'][0]
        self.rangeLastTime = self.rangeFirstTime + (
            self.frame.getNumberOfSamples() -
            1) / self.frame.instrument.getRangeSamplingRate()

    def extractImage(self):
        """Extract the raw image data"""
        import os
        from ctypes import cdll, c_char_p
        extract_csk = cdll.LoadLibrary(os.path.dirname(__file__) + '/csk.so')
        # Prepare and run the C-based extractor

        for i in range(len(self.hdf5FileList)):
            #need to create a new instance every time
            self.frame = Frame()
            self.frame.configure()
            appendStr = '_' + str(i)
            # if more than one file to contatenate that create different outputs
            # but suffixing _i
            if (len(self.hdf5FileList) == 1):
                appendStr = ''
            outputNow = self.output + appendStr
            self.hdf5 = self.hdf5FileList[i]
            inFile_c = c_char_p(bytes(self.hdf5, 'utf-8'))
            outFile_c = c_char_p(bytes(outputNow, 'utf-8'))

            extract_csk.extract_csk(inFile_c, outFile_c)
            # Now, populate the metadata
            try:
                fp = h5py.File(self.hdf5, 'r')
            except Exception as strerror:
                self.logger.error("IOError: %s\n" % strerror)
                return
            self.populateMetadata(file=fp)
            self.populateImage(outputNow)
            self._populateExtras(fp)

            fp.close()
            self.frameList.append(self.frame)
            createAuxFile(self.frame, outputNow + '.aux')
        self._imageFileList = self.hdf5FileList
        return tkfunc(self)

    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 extractDoppler(self):
        """
        Return the doppler centroid as defined in the HDF5 file.
        """
        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])

        return quadratic
Example #29
0
class Sensor(Component):
    """
    Base class for storing Sensor data
    """
    parameter_list = (OUTPUT, )
    logging_name = None
    lookMap = {'RIGHT': -1, 'LEFT': 1}
    family = 'sensor'

    def __init__(self, family='', name=''):
        super(Sensor,
              self).__init__(family if family else self.__class__.family,
                             name=name)
        self.frame = Frame()
        self.frame.configure()

        self.logger = logging.getLogger(self.logging_name)

        self.frameList = []

        return None

    def getFrame(self):
        '''
        Return the frame object.
        '''
        return self.frame

    def parse(self):
        '''
        Dummy routine.
        '''
        raise NotImplementedError("In Sensor Base Class")

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

    def _populatePlatform(self, **kwargs):
        '''
        Dummy routine to populate platform information.
        '''
        raise NotImplementedError("In Sensor Base Class")

    def _populateInstrument(self, **kwargs):
        """
        Dummy routine to populate instrument information.
        """
        raise NotImplementedError("In Sensor Base Class")

    def _populateFrame(self, **kwargs):
        """
        Dummy routine to populate frame object.
        """
        raise NotImplementedError("In Sensor Base Class")

    def _populateOrbit(self, **kwargs):
        """
        Dummy routine to populate orbit information.
        """
        raise NotImplementedError("In Sensor Base Class")

    def extractImage(self):
        """
        Dummy routine to extract image.
        """
        raise NotImplementedError("In Sensor Base Class")

    def extractDoppler(self):
        """
        Dummy routine to extract doppler centroid information.
        """
        raise NotImplementedError("In Sensor Base Class")
Example #30
0
class Track(object):
    """A class to represent a collection of temporally continuous radar frame
    objects"""

    logging_name = "isce.Scene.Track"

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

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

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

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

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

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

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

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

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

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

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

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

        return startLine, outputs

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    pass