class ALOS(Component): """Code to read CEOSFormat leader files for ALOS SAR data. The tables used to create this parser are based on document number ER-IS-EPO-GS-5902.1 from the European Space Agency. """ family = 'alos' logging_name = 'isce.sensor.ALOS' parameter_list = (IMAGEFILE, LEADERFILE, OUTPUT, RESAMPLE_FLAG) # polarizationMap = ['H','V','H+V'] ## This is manifestly better than a method complete the lazy instantation ## of an instance attribute transmit = Distortion(complex(2.427029e-3, 1.293019e-2), complex(-1.147240e-2, -6.228230e-3), complex(9.572169e-1, 3.829563e-1)) receive = Distortion(complex(-6.263392e-3, 7.082863e-3), complex(-6.297074e-3, 8.026685e-3), complex(7.217117e-1, -2.367683e-2)) constants = Constants(iBias=15.5, qBias=15.5, pointingDirection=-1, antennaLength=8.9) HEADER_LINES = 720 RESAMPLE_FLAG = { '': 'do Nothing', 'single2dual': 'resample from single to dual pole', 'dual2single': 'resample from dual to single' } @logged def __init__(self, name=''): super(ALOS, self).__init__(family=self.__class__.family, name=name) self._leaderFile = None self._imageFile = None self.frame = None return None #2013-06-03 Kosal: the functions below overwrite the transmit property #initiated above ''' @property def transmit(self): return self.__class__.transmit @transmit.setter def transmit(self, x): raise TypeError( "ALOS.transmit is a protected class attribute and cannot be set" ) @property def receive(self): return self.__class__.receive @receive.setter def receive(self, x): raise TypeError( "ALOS.receive is a protected class attribute and cannot be set" ) ''' #Kosal def getFrame(self): return self.frame def setLeaderFile(self, ldr): self._leaderFile = ldr return def parse(self): self.leaderFile = LeaderFile(file=self._leaderFile) self.imageFile = ImageFile(self) try: self.leaderFile.parse() self.imageFile.parse() except IOError: return self.populateMetadata() def populateMetadata(self): """ Create the appropriate metadata objects from our CEOSFormat metadata """ self._populatePlatform() self._populateInstrument() self._populateFrame() # Header orbits self._populateOrbit() self._populateAttitude() self._populateDistortions() pass def _populatePlatform(self): platform = self.frame.getInstrument().getPlatform() platform.setMission(self.leaderFile.sceneHeaderRecord. metadata['Sensor platform mission identifier']) platform.setPointingDirection(self.constants.pointing_direction) platform.setAntennaLength(self.constants.antenna_length) platform.setPlanet(Planet('Earth')) def _populateInstrument(self): instrument = self.frame.getInstrument() rangePixelSize = None rangeSamplingRate = None chirpSlope = None bandwidth = None prf = None try: rangeSamplingRate = self.leaderFile.sceneHeaderRecord.metadata[ 'Range sampling rate'] * 1e6 pulseLength = self.leaderFile.sceneHeaderRecord.metadata[ 'Range pulse length'] * 1e-6 rangePixelSize = SPEED_OF_LIGHT / (2.0 * rangeSamplingRate) prf = self.leaderFile.sceneHeaderRecord.metadata[ 'Pulse Repetition Frequency'] beamNumber = self.leaderFile.sceneHeaderRecord.metadata[ 'Antenna beam number'] if self.imageFile.prf: prf = self.imageFile.prf else: self.logger.info("Using nominal PRF") bandwidth = self.leaderFile.calibrationRecord.metadata[ 'Band width'] * 1e6 #if (not bandwidth): # bandwidth = self.leaderFile.sceneHeaderRecord.metadata[ # 'Bandwidth per look in range'] chirpSlope = -(bandwidth / pulseLength) except AttributeError: self.logger.info("Some of the instrument parameters were not set") self.logger.debug("PRF: %s" % prf) self.logger.debug("Bandwidth: %s" % bandwidth) self.logger.debug("Pulse Length: %s" % pulseLength) self.logger.debug("Chirp Slope: %s" % chirpSlope) self.logger.debug("Range Pixel Size: %s" % rangePixelSize) self.logger.debug("Range Sampling Rate: %s" % rangeSamplingRate) self.logger.debug("Beam Number: %s" % beamNumber) instrument.setRadarWavelength( self.leaderFile.sceneHeaderRecord.metadata['Radar wavelength']) instrument.setIncidenceAngle( self.leaderFile.sceneHeaderRecord. metadata['Incidence angle at scene centre']) instrument.setPulseRepetitionFrequency(prf) instrument.setRangePixelSize(rangePixelSize) instrument.setRangeSamplingRate(rangeSamplingRate) instrument.setPulseLength(pulseLength) instrument.setChirpSlope(chirpSlope) instrument.setInPhaseValue(self.constants['iBias']) instrument.setQuadratureValue(self.constants['qBias']) instrument.setBeamNumber(beamNumber) return None def _populateFrame(self, polarization='HH', farRange=None): frame = self._decodeSceneReferenceNumber( self.leaderFile.sceneHeaderRecord. metadata['Scene reference number']) try: first_line_utc = self.imageFile.start_time last_line_utc = self.imageFile.stop_time centerTime = DTUtil.timeDeltaToSeconds(last_line_utc - first_line_utc) / 2.0 center_line_utc = first_line_utc + datetime.timedelta( microseconds=int(centerTime * 1e6)) self.frame.setSensingStart(first_line_utc) self.frame.setSensingMid(center_line_utc) self.frame.setSensingStop(last_line_utc) rangePixelSize = self.frame.getInstrument().getRangePixelSize() farRange = (self.imageFile.startingRange + self.imageFile.width * rangePixelSize) except TypeError as strerr: self.logger.warn(strerr) self.frame.frameNumber = frame self.frame.setOrbitNumber( self.leaderFile.sceneHeaderRecord.metadata['Orbit number']) self.frame.setStartingRange(self.imageFile.startingRange) self.frame.setFarRange(farRange) self.frame.setProcessingFacility( self.leaderFile.sceneHeaderRecord. metadata['Processing facility identifier']) self.frame.setProcessingSystem( self.leaderFile.sceneHeaderRecord. metadata['Processing system identifier']) self.frame.setProcessingSoftwareVersion( self.leaderFile.sceneHeaderRecord. metadata['Processing version identifier']) self.frame.setPolarization(polarization) self.frame.setNumberOfLines(self.imageFile.length) self.frame.setNumberOfSamples(self.imageFile.width) def _populateOrbit(self): orbit = self.frame.getOrbit() velocityScale = 1.0 if (self.leaderFile.sceneHeaderRecord. metadata['Processing facility identifier'] == 'ERSDAC'): # The ERSDAC header orbits are in mm/s velocityScale = 1000.0 orbit.setReferenceFrame(self.leaderFile.platformPositionRecord. metadata['Reference coordinate system']) orbit.setOrbitSource('Header') orbitQuality = self._decodeOrbitQuality( self.leaderFile.platformPositionRecord. metadata['Orbital elements designator']) orbit.setOrbitQuality(orbitQuality) t0 = datetime.datetime(year=self.leaderFile.platformPositionRecord. metadata['Year of data point'], month=self.leaderFile.platformPositionRecord. metadata['Month of data point'], day=self.leaderFile.platformPositionRecord. metadata['Day of data point']) t0 = t0 + datetime.timedelta( seconds=self.leaderFile.platformPositionRecord. metadata['Seconds of day']) for i in range(self.leaderFile.platformPositionRecord. metadata['Number of data points']): vec = OrbitStateVector() t = t0 + datetime.timedelta( seconds=i * self.leaderFile.platformPositionRecord. metadata['Time interval between DATA points']) vec.setTime(t) dataPoints = self.leaderFile.platformPositionRecord.metadata[ 'Positional Data Points'][i] vec.setPosition([ dataPoints['Position vector X'], dataPoints['Position vector Y'], dataPoints['Position vector Z'] ]) vec.setVelocity([ dataPoints['Velocity vector X'] / velocityScale, dataPoints['Velocity vector Y'] / velocityScale, dataPoints['Velocity vector Z'] / velocityScale ]) orbit.addStateVector(vec) def _populateAttitude(self): if (self.leaderFile.leaderFDR. metadata['Number of attitude data records'] != 1): return attitude = self.frame.getAttitude() attitude.setAttitudeSource("Header") year = int( self.leaderFile.sceneHeaderRecord.metadata['Scene centre time'] [0:4]) t0 = datetime.datetime(year=year, month=1, day=1) for i in range(self.leaderFile.platformAttitudeRecord. metadata['Number of attitude data points']): vec = AttitudeStateVector() dataPoints = self.leaderFile.platformAttitudeRecord.metadata[ 'Attitude Data Points'][i] t = t0 + datetime.timedelta( days=(dataPoints['Day of the year'] - 1), milliseconds=dataPoints['Millisecond of day']) vec.setTime(t) vec.setPitch(dataPoints['Pitch']) vec.setRoll(dataPoints['Roll']) vec.setYaw(dataPoints['Yaw']) attitude.addStateVector(vec) def _populateDistortions(self): return None def readOrbitPulse(self, leader, raw, width): from isceobj.Sensor import readOrbitPulse as ROP rawImage = isceobj.createRawImage() leaImage = isceobj.createStreamImage() auxImage = isceobj.createImage() rawImage.initImage(raw, 'read', width) rawImage.createImage() rawAccessor = rawImage.getImagePointer() leaImage.initImage(leader, 'read') leaImage.createImage() leaAccessor = leaImage.getImagePointer() widthAux = 2 auxName = raw + '.aux' self.frame.auxFile = auxName auxImage.initImage(auxName, 'write', widthAux, type='DOUBLE') auxImage.createImage() auxAccessor = auxImage.getImagePointer() length = rawImage.getLength() ROP.setNumberBitesPerLine_Py(width) ROP.setNumberLines_Py(length) ROP.readOrbitPulse_Py(leaAccessor, rawAccessor, auxAccessor) rawImage.finalizeImage() leaImage.finalizeImage() auxImage.finalizeImage() return None ## Can this even be done/ ## should the pointer be an __Int__? def readOrbitPulseDevelopement(self, leader, raw, width): from isceobj.Sensor import readOrbitPulse as ROP with isceobj.contextRawImage( width=width, accessMode='read', ) as rawImage: with isceobj.contextStreamImage( width=width, accessMode='read', ) as leaImage: with isceobj.contextImage( width=width, accessMode='write', ) as auxImage: rawAccessor = rawImage.getImagePointer() leaAccessor = leaImage.getImagePointer() widthAux = 2 auxName = raw + '.aux' self.frame.auxFile = auxName auxImage.initImage(auxName, 'write', widthAux, type='DOUBLE') auxImage.createImage() auxAccessor = auxImage.getImagePointer() length = rawImage.getLength() ROP.setNumberBitesPerLine_Py(width) ROP.setNumberLines_Py(length) ROP.readOrbitPulse_Py(leaAccessor, rawAccessor, auxAccessor) pass #rawImage.finalizeImage() pass #leaImage.finalizeImage() pass #auxImage.finalizeImage() return None def extractImage(self): # just in case there was only one image and it was passed as a str #instead of a list with only one element if (isinstance(self._imageFileList, str)): self._imageFileList = [self._imageFileList] self._leaderFileList = [self._leaderFileList] if (len(self._imageFileList) != len(self._leaderFileList)): self.logger.error( "Number of leader files different from number of image files.") raise RuntimeError self.frameList = [] for i in range(len(self._imageFileList)): appendStr = "_" + str(i) #if only one file don't change the name if (len(self._imageFileList) == 1): appendStr = '' self.frame = Frame() self.frame.configure() self._leaderFile = self._leaderFileList[i] self._imageFile = self._imageFileList[i] self.leaderFile = LeaderFile(file=self._leaderFile) self.imageFile = ImageFile(self) try: self.leaderFile.parse() self.imageFile.parse(calculateRawDimensions=False) outputNow = self.output + appendStr if not (self._resampleFlag == ''): filein = self.output + '__tmp__' self.imageFile.extractImage(filein) self.populateMetadata() objResample = None if (self._resampleFlag == 'single2dual'): objResample = ALOS_fbs2fbdPy() else: objResample = ALOS_fbd2fbsPy() objResample.wireInputPort('frame', object=self.frame) objResample.setInputFilename(filein) objResample.setOutputFilename(outputNow) objResample.run() objResample.updateFrame(self.frame) os.remove(filein) else: self.imageFile.extractImage(outputNow) self.populateMetadata() width = self.frame.getImage().getWidth() self.readOrbitPulse(self._leaderFile, outputNow, width) self.frameList.append(self.frame) except IOError: return pass ## refactor this with __init__.tkfunc return tkfunc(self) def _decodeSceneReferenceNumber(self, referenceNumber): return referenceNumber def _decodeOrbitQuality(self, quality): try: quality = int(quality) except ValueError: quality = None qualityString = '' if (quality == 0): qualityString = 'Preliminary' elif (quality == 1): qualityString = 'Decision' elif (quality == 2): qualityString = 'High Precision' else: qualityString = 'Unknown' return qualityString
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 Generic(Component): """ A class to parse generic SAR data stored in the HDF5 format """ logging_name = 'isce.sensor.Generic' def __init__(self): super(Generic, self).__init__() self._hdf5File = None self.output = None self.frame = Frame() self.frame.configure() self.logger = logging.getLogger('isce.sensor.Generic') self.descriptionOfVariables = {} self.dictionaryOfVariables = { 'HDF5': ['self._hdf5File', 'str', 'mandatory'], 'OUTPUT': ['self.output', 'str', 'optional'] } return None def getFrame(self): return self.frame def parse(self): try: fp = h5py.File(self._hdf5File, 'r') except Exception as strerror: self.logger.error("IOError: %s" % strerror) return self.populateMetadata(fp) fp.close() def populateMetadata(self, file): """ Create the appropriate metadata objects from our HDF5 file """ self._populatePlatform(file) self._populateInstrument(file) self._populateFrame(file) self._populateOrbit(file) def _populatePlatform(self, file): platform = self.frame.getInstrument().getPlatform() platform.setMission(file['Platform'].attrs['Mission']) platform.setPlanet(Planet(pname='Earth')) platform.setAntennaLength(file['Platform'].attrs['Antenna Length']) def _populateInstrument(self, file): instrument = self.frame.getInstrument() instrument.setRadarWavelength(file['Instrument'].attrs['Wavelength']) instrument.setPulseRepetitionFrequency( file['Instrument'].attrs['Pulse Repetition Frequency']) instrument.setRangePixelSize( file['Instrument'].attrs['Range Pixel Size']) instrument.setPulseLength(file['Instrument'].attrs['Pulse Length']) instrument.setChirpSlope(file['Instrument'].attrs['Chirp Slope']) instrument.setRangeSamplingRate( file['Instrument'].attrs['Range Sampling Frequency']) instrument.setInPhaseValue(file['Frame'].attrs['In Phase Bias']) instrument.setQuadratureValue(file['Frame'].attrs['Quadrature Bias']) def _populateFrame(self, file): size = file['Frame'].shape start = DTU.parseIsoDateTime(file['Frame'].attrs['Sensing Start']) stop = DTU.parseIsoDateTime(file['Frame'].attrs['Sensing Stop']) deltaT = DTU.timeDeltaToSeconds(stop - start) mid = start + datetime.timedelta(microseconds=int(deltaT / 2.0 * 1e6)) startingRange = file['Frame'].attrs['Starting Range'] rangePixelSize = file['Instrument'].attrs['Range Pixel Size'] farRange = startingRange + size[1] * rangePixelSize self.frame.setStartingRange(file['Frame'].attrs['Starting Range']) self.frame.setFarRange(farRange) self.frame.setNumberOfLines(size[0]) self.frame.setNumberOfSamples(2 * size[1]) self.frame.setSensingStart(start) self.frame.setSensingMid(mid) self.frame.setSensingStop(stop) def _populateOrbit(self, file): orbit = self.frame.getOrbit() orbit.setReferenceFrame('ECR') orbit.setOrbitSource(file['Orbit'].attrs['Source']) for i in range(len(file['Orbit']['Time'])): vec = StateVector() time = DTU.parseIsoDateTime(file['Orbit']['Time'][i]) vec.setTime(time) vec.setPosition(list(file['Orbit']['Position'][i])) vec.setVelocity(list(file['Orbit']['Velocity'][i])) orbit.addStateVector(vec) def extractImage(self): try: file = h5py.File(self._hdf5File, 'r') except Exception as strerror: self.logger.error("IOError: %s" % strerror) return size = file['Frame'].shape dtype = self._translateDataType(file['Frame'].attrs['Image Type']) length = size[0] width = size[1] data = numpy.memmap(self.output, dtype=dtype, mode='w+', shape=(length, width, 2)) data[:, :, :] = file['Frame'][:, :, :] del data rawImage = isceobj.createRawImage() rawImage.setByteOrder('l') rawImage.setAccessMode('r') rawImage.setFilename(self.output) rawImage.setWidth(2 * width) rawImage.setXmin(0) rawImage.setXmax(2 * width) self.frame.setImage(rawImage) self.populateMetadata(file) file.close() def write(self, output, compression=None): """ Given a frame object (appropriately populated) and an image, create an HDF5 from those objects. """ if (not self.frame): self.logger.error("Frame not set") raise AttributeError("Frame not set") h5file = h5py.File(output, 'w') self._writeMetadata(h5file, compression) def _writeMetadata(self, h5file, compression=None): self._writePlatform(h5file) self._writeInstrument(h5file) self._writeFrame(h5file, compression) self._writeOrbit(h5file) def _writePlatform(self, h5file): platform = self.frame.getInstrument().getPlatform() if (not platform): self.logger.error("Platform not set") raise AttributeError("Platform not set") group = h5file.create_group('Platform') group.attrs['Mission'] = platform.getMission() group.attrs['Planet'] = platform.getPlanet().name group.attrs['Antenna Length'] = platform.getAntennaLength() def _writeInstrument(self, h5file): instrument = self.frame.getInstrument() if (not instrument): self.logger.error("Instrument not set") raise AttributeError("Instrument not set") group = h5file.create_group('Instrument') group.attrs['Wavelength'] = instrument.getRadarWavelength() group.attrs[ 'Pulse Repetition Frequency'] = instrument.getPulseRepetitionFrequency( ) group.attrs['Range Pixel Size'] = instrument.getRangePixelSize() group.attrs['Pulse Length'] = instrument.getPulseLength() group.attrs['Chirp Slope'] = instrument.getChirpSlope() group.attrs[ 'Range Sampling Frequency'] = instrument.getRangeSamplingRate() group.attrs['In Phase Bias'] = instrument.getInPhaseValue() group.attrs['Quadrature Bias'] = instrument.getQuadratureValue() def _writeFrame(self, h5file, compression=None): group = self._writeImage(h5file, compression) group.attrs['Starting Range'] = self.frame.getStartingRange() group.attrs['Sensing Start'] = self.frame.getSensingStart().isoformat() group.attrs['Sensing Stop'] = self.frame.getSensingStop().isoformat() def _writeImage(self, h5file, compression=None): image = self.frame.getImage() if (not image): self.logger.error("Image not set") raise AttributeError("Image not set") filename = image.getFilename() length = image.getLength() width = image.getWidth() dtype = self._translateDataType(image.dataType) if (image.dataType == 'BYTE'): width = int(width / 2) self.logger.debug("Width: %s" % (width)) self.logger.debug("Length: %s" % (length)) data = numpy.memmap(filename, dtype=dtype, mode='r', shape=(length, 2 * width)) dset = h5file.create_dataset("Frame", (length, width, 2), dtype=dtype, compression=compression) dset.attrs['Image Type'] = image.dataType dset[:, :, 0] = data[:, ::2] dset[:, :, 1] = data[:, 1::2] del data return dset def _writeOrbit(self, h5file): # Add orbit information (time, position, velocity) = self._orbitToArray() group = h5file.create_group("Orbit") group.attrs['Source'] = self.frame.getOrbit().getOrbitSource() group.attrs['Reference Frame'] = self.frame.getOrbit( ).getReferenceFrame() timedset = h5file.create_dataset("Orbit/Time", time.shape, dtype=time.dtype) posdset = h5file.create_dataset("Orbit/Position", position.shape, dtype=numpy.float64) veldset = h5file.create_dataset("Orbit/Velocity", velocity.shape, dtype=numpy.float64) timedset[...] = time posdset[...] = position veldset[...] = velocity def _orbitToArray(self): orbit = self.frame.getOrbit() if (not orbit): self.logger.error("Orbit not set") raise AttributeError("Orbit not set") time = [] position = [] velocity = [] for sv in orbit: timeString = sv.getTime().isoformat() time.append(timeString) position.append(sv.getPosition()) velocity.append(sv.getVelocity()) return numpy.array(time), numpy.array(position), numpy.array(velocity) def _translateDataType(self, imageType): dtype = '' if (imageType == 'BYTE'): dtype = 'int8' elif (imageType == 'CFLOAT'): dtype = 'float32' elif (imageType == 'SHORT'): dtype = 'int16' else: self.logger.error("Unknown data type %s" % (imageType)) raise ValueError("Unknown data type %s" % (imageType)) return dtype