def __init__(self): Component.__init__(self) self._leaderFile = None self._imageFile = None self._parFile = None self.output = None self.imageFile = None self.leaderFile = None #####Soecific doppler functions for RSAT1 self.doppler_ref_range = None self.doppler_ref_azi = None self.doppler_predict = None self.doppler_DAR = None self.doppler_coeff = None self.frame = Frame() self.frame.configure() self.constants = {'polarization': 'HH', 'antennaLength': 15} self.descriptionOfVariables = {} self.dictionaryOfVariables = { 'LEADERFILE': ['self._leaderFile', 'str', 'mandatory'], 'IMAGEFILE': ['self._imageFile', 'str', 'mandatory'], 'PARFILE': ['self._parFile', 'str', 'optional'], 'OUTPUT': ['self.output', 'str', 'optional'] }
def __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
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
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()
def extractImage(self): # just in case there was only one image and it was passed as a str #instead of a list with only one element if (isinstance(self._imageFileList, str)): self._imageFileList = [self._imageFileList] self._leaderFileList = [self._leaderFileList] if (len(self._imageFileList) != len(self._leaderFileList)): self.logger.error( "Number of leader files different from number of image files.") raise RuntimeError self.frameList = [] for i in range(len(self._imageFileList)): appendStr = "_" + str(i) #if only one file don't change the name if (len(self._imageFileList) == 1): appendStr = '' self.frame = Frame() self.frame.configure() self._leaderFile = self._leaderFileList[i] self._imageFile = self._imageFileList[i] self.leaderFile = LeaderFile(file=self._leaderFile) self.imageFile = ImageFile(self) try: self.leaderFile.parse() self.imageFile.parse(calculateRawDimensions=False) outputNow = self.output + appendStr if not (self._resampleFlag == ''): filein = self.output + '__tmp__' self.imageFile.extractImage(filein) self.populateMetadata() objResample = None if (self._resampleFlag == 'single2dual'): objResample = ALOS_fbs2fbdPy() else: objResample = ALOS_fbd2fbsPy() objResample.wireInputPort('frame', object=self.frame) objResample.setInputFilename(filein) objResample.setOutputFilename(outputNow) objResample.run() objResample.updateFrame(self.frame) os.remove(filein) else: self.imageFile.extractImage(outputNow) self.populateMetadata() width = self.frame.getImage().getWidth() self.readOrbitPulse(self._leaderFile, outputNow, width) self.frameList.append(self.frame) except IOError: return pass ## refactor this with __init__.tkfunc return tkfunc(self)
def __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 __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 parse(self): """ Parse both imagery and create objects representing the platform, instrument and scene """ self.frame = Frame() self.frame.configure() self._imageFile = ImageryFile(fileName=self._imageFileName) self._imageryFileData = self._imageFile.parse() self.populateMetadata()
def 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()
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 __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 __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
def __init__(self): super(Generic, self).__init__() self._hdf5File = None self.output = None self.frame = Frame() self.frame.configure() self.logger = logging.getLogger('isce.sensor.Generic') self.descriptionOfVariables = {} self.dictionaryOfVariables = { 'HDF5': ['self._hdf5File','str','mandatory'], 'OUTPUT': ['self.output','str','optional']} return None
def __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 __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
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 __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'] }
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'] }
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 parse(self): """ Parse both imagery and instrument files and create objects representing the platform, instrument and scene """ self.frame = Frame() self.frame.configure() self._imageFile = ImageryFile(fileName=self._imageFileName) self._imageryFileData = self._imageFile.parse() if self.instrumentFile in [None, '']: self.findInstrumentFile() instrumentFileParser = InstrumentFile(fileName=self.instrumentFile) self._instrumentFileData = instrumentFileParser.parse() self.populateMetadata()
def __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 __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 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)
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
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
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")
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