class Sentinel1A(Component): """ A Class representing RadarSAT 2 data """ 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 getFrame(self): return self.frame def parse(self): try: fp = open(self.xml, 'r') except IOError as strerr: print("IOError: %s" % strerr) return self._xml_root = ElementTree(file=fp).getroot() # self.product.set_from_etnode(self._xml_root) self.populateMetadata() fp.close() def grab_from_xml(self, path): try: res = self._xml_root.find(path).text except: raise Exception('Tag= %s not found' % (path)) if res is None: raise Exception('Tag = %s not found' % (path)) return res def convertToDateTime(self, string): dt = datetime.datetime.strptime(string, "%Y-%m-%dT%H:%M:%S.%f") return dt def populateMetadata(self): """ Create metadata objects from the metadata files """ ####Set each parameter one - by - one mission = self.grab_from_xml('adsHeader/missionId') swath = self.grab_from_xml('adsHeader/swath') polarization = self.grab_from_xml('adsHeader/polarisation') frequency = float( self.grab_from_xml( 'generalAnnotation/productInformation/radarFrequency')) passDirection = self.grab_from_xml( 'generalAnnotation/productInformation/pass') rangePixelSize = float( self.grab_from_xml( 'imageAnnotation/imageInformation/rangePixelSpacing')) azimuthPixelSize = float( self.grab_from_xml( 'imageAnnotation/imageInformation/azimuthPixelSpacing')) rangeSamplingRate = Const.c / (2.0 * rangePixelSize) prf = 1.0 / float( self.grab_from_xml( 'imageAnnotation/imageInformation/azimuthTimeInterval')) lines = int( self.grab_from_xml( 'imageAnnotation/imageInformation/numberOfLines')) samples = int( self.grab_from_xml( 'imageAnnotation/imageInformation/numberOfSamples')) startingRange = float( self.grab_from_xml( 'imageAnnotation/imageInformation/slantRangeTime') ) * Const.c / 2.0 incidenceAngle = float( self.grab_from_xml( 'imageAnnotation/imageInformation/incidenceAngleMidSwath')) dataStartTime = self.convertToDateTime( self.grab_from_xml( 'imageAnnotation/imageInformation/productFirstLineUtcTime')) dataStopTime = self.convertToDateTime( self.grab_from_xml( 'imageAnnotation/imageInformation/productLastLineUtcTime')) pulseLength = float( self.grab_from_xml( 'generalAnnotation/downlinkInformationList/downlinkInformation/downlinkValues/txPulseLength' )) chirpSlope = float( self.grab_from_xml( 'generalAnnotation/downlinkInformationList/downlinkInformation/downlinkValues/txPulseRampRate' )) pulseBandwidth = pulseLength * chirpSlope ####Sentinel is always right looking lookSide = -1 facility = 'EU' version = '1.0' # height = self.product.imageGenerationParameters.sarProcessingInformation._satelliteHeight ####Populate platform platform = self.frame.getInstrument().getPlatform() platform.setPlanet(Planet(pname="Earth")) platform.setMission(mission) platform.setPointingDirection(lookSide) platform.setAntennaLength(2 * azimuthPixelSize) ####Populate instrument instrument = self.frame.getInstrument() instrument.setRadarFrequency(frequency) instrument.setPulseRepetitionFrequency(prf) instrument.setPulseLength(pulseLength) instrument.setChirpSlope(pulseBandwidth / pulseLength) instrument.setIncidenceAngle(incidenceAngle) #self.frame.getInstrument().setRangeBias(0) instrument.setRangePixelSize(rangePixelSize) instrument.setRangeSamplingRate(rangeSamplingRate) instrument.setBeamNumber(swath) instrument.setPulseLength(pulseLength) #Populate Frame #self.frame.setSatelliteHeight(height) self.frame.setSensingStart(dataStartTime) self.frame.setSensingStop(dataStopTime) diffTime = DTUtil.timeDeltaToSeconds(dataStopTime - dataStartTime) / 2.0 sensingMid = dataStartTime + datetime.timedelta( microseconds=int(diffTime * 1e6)) self.frame.setSensingMid(sensingMid) self.frame.setPassDirection(passDirection) self.frame.setPolarization(polarization) self.frame.setStartingRange(startingRange) self.frame.setFarRange(startingRange + (samples - 1) * rangePixelSize) self.frame.setNumberOfLines(lines) self.frame.setNumberOfSamples(samples) self.frame.setProcessingFacility(facility) self.frame.setProcessingSoftwareVersion(version) self.frame.setPassDirection(passDirection) ResOrbFlag = self.extractResOrbit() if ResOrbFlag == 0: print( "cannot find POD Restituted Orbit, using orbit coming along with SLC" ) self.extractOrbit() ###################################################################################### def extractResOrbit(self): #read ESA's POD Restituted Orbit by Cunren Liang, APR. 2, 2015. import pathlib useResOrbFlag = 0 ResOrbDir = os.environ.get('RESORB') if ResOrbDir != None: print("Trying to find POD Restituted Orbit...") #get start time and stop time of the SLC data from data xml file dataStartTime = self.convertToDateTime( self.grab_from_xml( 'imageAnnotation/imageInformation/productFirstLineUtcTime') ) dataStopTime = self.convertToDateTime( self.grab_from_xml( 'imageAnnotation/imageInformation/productLastLineUtcTime')) #RESORB has an orbit every 10 sec, extend the start and stop time by 50 sec. dataStartTimeExt = dataStartTime - datetime.timedelta(0, 50) dataStopTimeExt = dataStopTime + datetime.timedelta(0, 50) ########################### #deal with orbit directory ########################### orbList = pathlib.Path(ResOrbDir).glob('**/*.EOF') for orb in orbList: #save full path orb = str(orb) orbx = orb #get orbit file name orb = os.path.basename(os.path.normpath(orb)) #print("{0}".format(orb)) #get start and stop time of the orbit file orbStartTime = datetime.datetime.strptime( orb[42:57], "%Y%m%dT%H%M%S") orbStopTime = datetime.datetime.strptime( orb[58:73], "%Y%m%dT%H%M%S") #print("{0}, {1}".format(orbStartTime, orbStopTime)) if dataStartTimeExt >= orbStartTime and dataStopTimeExt <= orbStopTime: try: orbfp = open(orbx, 'r') except IOError as strerr: print("IOError: %s" % strerr) return useResOrbFlag orbxml = ElementTree(file=orbfp).getroot() print('using orbit file: {0}'.format(orbx)) frameOrbit = Orbit() frameOrbit.setOrbitSource('Restituted') #find the orbit data from the file, and use them node = orbxml.find('Data_Block/List_of_OSVs' ) #note upper case and lower case for child in node.getchildren(): timestamp = self.convertToDateTime( child.find('UTC').text[4:]) if timestamp < dataStartTimeExt: continue if timestamp > dataStopTimeExt: break pos = [] vel = [] for tag in ['X', 'Y', 'Z']: pos.append(float(child.find(tag).text)) vel.append(float(child.find('V' + tag).text)) vec = StateVector() vec.setTime(timestamp) vec.setPosition(pos) vec.setVelocity(vel) frameOrbit.addStateVector(vec) #there is no need to extend the orbit any longer #planet = self.frame.instrument.platform.planet #orbExt = OrbitExtender(planet=planet) #orbExt.configure() #newOrb = orbExt.extendOrbit(frameOrbit) self.frame.getOrbit().setOrbitSource('Restituted') for sv in frameOrbit: self.frame.getOrbit().addStateVector(sv) orbfp.close() useResOrbFlag = 1 break return useResOrbFlag ###################################################################################### def extractOrbit(self): ''' Extract orbit information from xml node. ''' node = self._xml_root.find('generalAnnotation/orbitList') frameOrbit = Orbit() frameOrbit.setOrbitSource('Header') for child in node.getchildren(): timestamp = self.convertToDateTime(child.find('time').text) pos = [] vel = [] posnode = child.find('position') velnode = child.find('velocity') for tag in ['x', 'y', 'z']: pos.append(float(posnode.find(tag).text)) for tag in ['x', 'y', 'z']: vel.append(float(velnode.find(tag).text)) vec = StateVector() vec.setTime(timestamp) vec.setPosition(pos) vec.setVelocity(vel) frameOrbit.addStateVector(vec) planet = self.frame.instrument.platform.planet orbExt = OrbitExtender(planet=planet) orbExt.configure() newOrb = orbExt.extendOrbit(frameOrbit) self.frame.getOrbit().setOrbitSource('Header') for sv in newOrb: self.frame.getOrbit().addStateVector(sv) return def extractPreciseOrbit(self): ''' Extract precise orbit from given Orbit file. ''' try: fp = open(self.orbitfile, 'r') except IOError as strerr: print("IOError: %s" % strerr) return _xml_root = ElementTree(file=fp).getroot() node = _xml_root.find('Data_Block/List_of_OSVs') orb = Orbit() orb.configure() margin = datetime.timedelta(seconds=40.0) tstart = self.frame.getSensingStart() - margin tend = self.frame.getSensingStop() + margin for child in node.getchildren(): timestamp = self.convertToDateTime(child.find('UTC').text[4:]) if (timestamp >= tstart) and (timestamp < tend): pos = [] vel = [] for tag in ['VX', 'VY', 'VZ']: vel.append(float(child.find(tag).text)) for tag in ['X', 'Y', 'Z']: pos.append(float(child.find(tag).text)) vec = StateVector() vec.setTime(timestamp) vec.setPosition(pos) vec.setVelocity(vel) orb.addStateVector(vec) fp.close() self.frame.getOrbit().setOrbitSource('Header') for sv in orb: self.frame.getOrbit().addStateVector(sv) return def extractImage(self): """ Use gdal python bindings to extract image """ try: from osgeo import gdal except ImportError: raise Exception( 'GDAL python bindings not found. Need this for RSAT2/ TandemX / Sentinel1A.' ) self.parse() width = self.frame.getNumberOfSamples() lgth = self.frame.getNumberOfLines() src = gdal.Open(self.tiff.strip(), gdal.GA_ReadOnly) band = src.GetRasterBand(1) fid = open(self.output, 'wb') for ii in range(lgth): data = band.ReadAsArray(0, ii, width, 1) data.tofile(fid) fid.close() src = None band = None #### slcImage = isceobj.createSlcImage() slcImage.setByteOrder('l') slcImage.setFilename(self.output) slcImage.setAccessMode('read') slcImage.setWidth(self.frame.getNumberOfSamples()) slcImage.setLength(self.frame.getNumberOfLines()) slcImage.setXmin(0) slcImage.setXmax(self.frame.getNumberOfSamples()) self.frame.setImage(slcImage) def extractDoppler(self): ''' self.parse() Extract doppler information as needed by mocomp ''' # ins = self.frame.getInstrument() # dc = self.product.imageGenerationParameters.dopplerCentroid quadratic = {} # r0 = self.frame.startingRange # fs = ins.getRangeSamplingRate() # tNear = 2*r0/Const.c # tMid = tNear + 0.5*self.frame.getNumberOfSamples()/fs # t0 = dc.dopplerCentroidReferenceTime # poly = dc.dopplerCentroidCoefficients # fd_mid = 0.0 # for kk in range(len(poly)): # fd_mid += poly[kk] * (tMid - t0)**kk # quadratic['a'] = fd_mid / ins.getPulseRepetitionFrequency() quadratic['a'] = 0. quadratic['b'] = 0. quadratic['c'] = 0. return quadratic
class Radarsat2(Sensor): """ A Class representing RADARSAT 2 data """ family = 'radarsat2' parameter_list = (XML, TIFF) + Sensor.parameter_list def __init__(self, family='', name=''): super().__init__(family if family else self.__class__.family, name=name) self.product = _Product() self.frame = Frame() self.frame.configure() def getFrame(self): return self.frame def parse(self): try: fp = open(self.xml, 'r') except IOError as strerr: print("IOError: %s" % strerr) return self._xml_root = ElementTree(file=fp).getroot() self.product.set_from_etnode(self._xml_root) self.populateMetadata() fp.close() def populateMetadata(self): """ Create metadata objects from the metadata files """ mission = self.product.sourceAttributes.satellite swath = self.product.sourceAttributes.radarParameters.beams frequency = self.product.sourceAttributes.radarParameters.radarCenterFrequency orig_prf = self.product.sourceAttributes.radarParameters.prf # original PRF not necessarily effective PRF rangePixelSize = self.product.imageAttributes.rasterAttributes.sampledPixelSpacing rangeSamplingRate = Const.c / (2 * rangePixelSize) pulseLength = self.product.sourceAttributes.radarParameters.pulseLengths[ 0] pulseBandwidth = self.product.sourceAttributes.radarParameters.pulseBandwidths[ 0] polarization = self.product.sourceAttributes.radarParameters.polarizations lookSide = lookMap[self.product.sourceAttributes.radarParameters. antennaPointing.upper()] facility = self.product.imageGenerationParameters.generalProcessingInformation._processingFacility version = self.product.imageGenerationParameters.generalProcessingInformation.softwareVersion lines = self.product.imageAttributes.rasterAttributes.numberOfLines samples = self.product.imageAttributes.rasterAttributes.numberOfSamplesPerLine startingRange = self.product.imageGenerationParameters.slantRangeToGroundRange.slantRangeTimeToFirstRangeSample * ( Const.c / 2) incidenceAngle = (self.product.imageGenerationParameters. sarProcessingInformation.incidenceAngleNearRange + self.product.imageGenerationParameters. sarProcessingInformation.incidenceAngleFarRange) / 2 # some RS2 scenes have oversampled SLC images because processed azimuth bandwidth larger than PRF EJF 2015/08/15 azimuthPixelSize = self.product.imageAttributes.rasterAttributes.sampledLineSpacing # ground spacing in meters totalProcessedAzimuthBandwidth = self.product.imageGenerationParameters.sarProcessingInformation.totalProcessedAzimuthBandwidth prf = orig_prf * np.ceil( totalProcessedAzimuthBandwidth / orig_prf ) # effective PRF can be double original, suggested by Piyush print("effective PRF %f, original PRF %f" % (prf, orig_prf)) lineFlip = (self.product.imageAttributes.rasterAttributes. lineTimeOrdering.upper() == 'DECREASING') if lineFlip: dataStopTime = self.product.imageGenerationParameters.sarProcessingInformation.zeroDopplerTimeFirstLine dataStartTime = self.product.imageGenerationParameters.sarProcessingInformation.zeroDopplerTimeLastLine else: dataStartTime = self.product.imageGenerationParameters.sarProcessingInformation.zeroDopplerTimeFirstLine dataStopTime = self.product.imageGenerationParameters.sarProcessingInformation.zeroDopplerTimeLastLine passDirection = self.product.sourceAttributes.orbitAndAttitude.orbitInformation.passDirection height = self.product.imageGenerationParameters.sarProcessingInformation._satelliteHeight ####Populate platform platform = self.frame.getInstrument().getPlatform() platform.setPlanet(Planet(pname="Earth")) platform.setMission(mission) platform.setPointingDirection(lookSide) platform.setAntennaLength(15.0) ####Populate instrument instrument = self.frame.getInstrument() instrument.setRadarFrequency(frequency) instrument.setPulseRepetitionFrequency(prf) instrument.setPulseLength(pulseLength) instrument.setChirpSlope(pulseBandwidth / pulseLength) instrument.setIncidenceAngle(incidenceAngle) #self.frame.getInstrument().setRangeBias(0) instrument.setRangePixelSize(rangePixelSize) instrument.setRangeSamplingRate(rangeSamplingRate) instrument.setBeamNumber(swath) instrument.setPulseLength(pulseLength) #Populate Frame #self.frame.setSatelliteHeight(height) self.frame.setSensingStart(dataStartTime) self.frame.setSensingStop(dataStopTime) diffTime = DTUtil.timeDeltaToSeconds(dataStopTime - dataStartTime) / 2.0 sensingMid = dataStartTime + datetime.timedelta( microseconds=int(diffTime * 1e6)) self.frame.setSensingMid(sensingMid) self.frame.setPassDirection(passDirection) self.frame.setPolarization(polarization) self.frame.setStartingRange(startingRange) self.frame.setFarRange(startingRange + (samples - 1) * rangePixelSize) self.frame.setNumberOfLines(lines) self.frame.setNumberOfSamples(samples) self.frame.setProcessingFacility(facility) self.frame.setProcessingSoftwareVersion(version) # Initialize orbit objects # Read into temp orbit first. # Radarsat 2 needs orbit extensions. tempOrbit = Orbit() self.frame.getOrbit().setOrbitSource( 'Header: ' + self.product.sourceAttributes.orbitAndAttitude. orbitInformation.orbitDataFile) self.frame.setPassDirection(passDirection) stateVectors = self.product.sourceAttributes.orbitAndAttitude.orbitInformation.stateVectors for i in range(len(stateVectors)): position = [ stateVectors[i].xPosition, stateVectors[i].yPosition, stateVectors[i].zPosition ] velocity = [ stateVectors[i].xVelocity, stateVectors[i].yVelocity, stateVectors[i].zVelocity ] vec = StateVector() vec.setTime(stateVectors[i].timeStamp) vec.setPosition(position) vec.setVelocity(velocity) tempOrbit.addStateVector(vec) planet = self.frame.instrument.platform.planet orbExt = OrbitExtender(planet=planet) orbExt.configure() newOrb = orbExt.extendOrbit(tempOrbit) for sv in newOrb: self.frame.getOrbit().addStateVector(sv) # save the Doppler centroid coefficients, converting units from product.xml file # units in the file are quadratic coefficients in Hz, Hz/sec, and Hz/(sec^2) # ISCE expects Hz, Hz/(range sample), Hz((range sample)^2 # note that RS2 Doppler values are estimated at time dc.dopplerCentroidReferenceTime, # so the values might need to be adjusted for ISCE usage # added EJF 2015/08/17 dc = self.product.imageGenerationParameters.dopplerCentroid poly = dc.dopplerCentroidCoefficients # need to convert units poly[1] = poly[1] / rangeSamplingRate poly[2] = poly[2] / rangeSamplingRate**2 self.doppler_coeff = poly # similarly save Doppler azimuth fm rate values, converting units # units in the file are quadratic coefficients in Hz, Hz/sec, and Hz/(sec^2) # Guessing that ISCE expects Hz, Hz/(range sample), Hz((range sample)^2 # note that RS2 Doppler values are estimated at time dc.dopplerRateReferenceTime, # so the values might need to be adjusted for ISCE usage # added EJF 2015/08/17 dr = self.product.imageGenerationParameters.dopplerRateValues fmpoly = dr.dopplerRateValuesCoefficients # need to convert units fmpoly[1] = fmpoly[1] / rangeSamplingRate fmpoly[2] = fmpoly[2] / rangeSamplingRate**2 self.azfmrate_coeff = fmpoly # now calculate effective PRF from the azimuth line spacing after we have the orbit info EJF 2015/08/15 # this does not work because azimuth spacing is on ground. Instead use bandwidth ratio calculated above EJF # SCHvelocity = self.frame.getSchVelocity() # SCHvelocity = 7550.75 # hard code orbit velocity for now m/s # prf = SCHvelocity/azimuthPixelSize # instrument.setPulseRepetitionFrequency(prf) def extractImage(self, verbose=True): ''' Use gdal to extract the slc. ''' try: from osgeo import gdal except ImportError: raise Exception( 'GDAL python bindings not found. Need this for RSAT2 / TandemX / Sentinel1A.' ) self.parse() width = self.frame.getNumberOfSamples() lgth = self.frame.getNumberOfLines() lineFlip = (self.product.imageAttributes.rasterAttributes. lineTimeOrdering.upper() == 'DECREASING') pixFlip = (self.product.imageAttributes.rasterAttributes. pixelTimeOrdering.upper() == 'DECREASING') src = gdal.Open(self.tiff.strip(), gdal.GA_ReadOnly) cJ = np.complex64(1.0j) ####Images are small enough that we can do it all in one go - Piyush real = src.GetRasterBand(1).ReadAsArray(0, 0, width, lgth) imag = src.GetRasterBand(2).ReadAsArray(0, 0, width, lgth) if (real is None) or (imag is None): raise Exception( 'Input Radarsat2 SLC seems to not be a 2 band Int16 image.') data = real + cJ * imag real = None imag = None src = None if lineFlip: if verbose: print('Vertically Flipping data') data = np.flipud(data) if pixFlip: if verbose: print('Horizontally Flipping data') data = np.fliplr(data) data.tofile(self.output) #### slcImage = isceobj.createSlcImage() slcImage.setByteOrder('l') slcImage.setFilename(self.output) slcImage.setAccessMode('read') slcImage.setWidth(width) slcImage.setLength(lgth) slcImage.setXmin(0) slcImage.setXmax(width) # slcImage.renderHdr() self.frame.setImage(slcImage) def extractDoppler(self): ''' self.parse() Extract doppler information as needed by mocomp ''' ins = self.frame.getInstrument() dc = self.product.imageGenerationParameters.dopplerCentroid quadratic = {} r0 = self.frame.startingRange fs = ins.getRangeSamplingRate() tNear = 2 * r0 / Const.c tMid = tNear + 0.5 * self.frame.getNumberOfSamples() / fs t0 = dc.dopplerCentroidReferenceTime poly = dc.dopplerCentroidCoefficients fd_mid = 0.0 for kk in range(len(poly)): fd_mid += poly[kk] * (tMid - t0)**kk ####For insarApp quadratic['a'] = fd_mid / ins.getPulseRepetitionFrequency() quadratic['b'] = 0. quadratic['c'] = 0. ####For roiApp ####More accurate from isceobj.Util import Poly1D coeffs = poly dr = self.frame.getInstrument().getRangePixelSize() rref = 0.5 * Const.c * t0 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 Radarsat1(Sensor): """ Code to read CEOSFormat leader files for Radarsat-1 SAR data. The tables used to create this parser are based on document number ER-IS-EPO-GS-5902.1 from the European Space Agency. """ family = 'radarsat1' logging_name = 'isce.sensor.radarsat1' parameter_list = (LEADERFILE, IMAGEFILE, PARFILE) + Sensor.parameter_list auxLength = 50 @logged def __init__(self, name=''): super().__init__(family=self.__class__.family, name=name) self.imageFile = None self.leaderFile = None #####Soecific doppler functions for RSAT1 self.doppler_ref_range = None self.doppler_ref_azi = None self.doppler_predict = None self.doppler_DAR = None self.doppler_coeff = None self.frame = Frame() self.frame.configure() self.constants = {'polarization': 'HH', 'antennaLength': 15} def getFrame(self): return self.frame def parse(self): self.leaderFile = LeaderFile(self, file=self._leaderFile) self.leaderFile.parse() self.imageFile = ImageFile(self, file=self._imageFile) self.imageFile.parse() self.populateMetadata() if self._parFile: self.parseParFile() else: self.populateCEOSOrbit() def populateMetadata(self): """ Create the appropriate metadata objects from our CEOSFormat metadata """ frame = self._decodeSceneReferenceNumber( self.leaderFile.sceneHeaderRecord. metadata['Scene reference number']) try: rangePixelSize = Const.c / (2 * self.leaderFile.sceneHeaderRecord. metadata['Range sampling rate'] * 1e6) except ZeroDivisionError: rangePixelSize = 0 ins = self.frame.getInstrument() platform = ins.getPlatform() platform.setMission(self.leaderFile.sceneHeaderRecord. metadata['Sensor platform mission identifier']) platform.setAntennaLength(self.constants['antennaLength']) platform.setPointingDirection(-1) platform.setPlanet(Planet(pname='Earth')) ins.setRadarWavelength( self.leaderFile.sceneHeaderRecord.metadata['Radar wavelength']) ins.setIncidenceAngle(self.leaderFile.sceneHeaderRecord. metadata['Incidence angle at scene centre']) ##RSAT-1 does not have PRF for raw data in leader file. # self.frame.getInstrument().setPulseRepetitionFrequency(self.leaderFile.sceneHeaderRecord.metadata['Pulse Repetition Frequency']) ins.setRangePixelSize(rangePixelSize) ins.setPulseLength( self.leaderFile.sceneHeaderRecord.metadata['Range pulse length'] * 1e-6) chirpPulseBandwidth = 15.50829e6 # Is this really not in the CEOSFormat Header? ins.setChirpSlope( chirpPulseBandwidth / (self.leaderFile.sceneHeaderRecord.metadata['Range pulse length'] * 1e-6)) ins.setInPhaseValue(7.5) ins.setQuadratureValue(7.5) self.frame.setFrameNumber(frame) self.frame.setOrbitNumber( self.leaderFile.sceneHeaderRecord.metadata['Orbit number']) self.frame.setProcessingFacility( self.leaderFile.sceneHeaderRecord. metadata['Processing facility identifier']) self.frame.setProcessingSystem( self.leaderFile.sceneHeaderRecord. metadata['Processing system identifier']) self.frame.setProcessingSoftwareVersion( self.leaderFile.sceneHeaderRecord. metadata['Processing version identifier']) self.frame.setPolarization(self.constants['polarization']) self.frame.setNumberOfLines( self.imageFile.imageFDR.metadata['Number of lines per data set']) self.frame.setNumberOfSamples( self.imageFile.imageFDR. metadata['Number of pixels per line per SAR channel']) self.frame.getOrbit().setOrbitSource('Header') self.frame.getOrbit().setOrbitQuality( self.leaderFile.platformPositionRecord. metadata['Orbital elements designator']) def populateCEOSOrbit(self): from isceobj.Orbit.Inertial import ECI2ECR t0 = datetime.datetime(year=self.leaderFile.platformPositionRecord. metadata['Year of data point'], month=self.leaderFile.platformPositionRecord. metadata['Month of data point'], day=self.leaderFile.platformPositionRecord. metadata['Day of data point']) t0 = t0 + datetime.timedelta( seconds=self.leaderFile.platformPositionRecord. metadata['Seconds of day']) #####Read in orbit in inertial coordinates orb = Orbit() for i in range(self.leaderFile.platformPositionRecord. metadata['Number of data points']): vec = StateVector() t = t0 + datetime.timedelta( seconds=(i * self.leaderFile.platformPositionRecord. metadata['Time interval between DATA points'])) vec.setTime(t) dataPoints = self.leaderFile.platformPositionRecord.metadata[ 'Positional Data Points'][i] vec.setPosition([ dataPoints['Position vector X'], dataPoints['Position vector Y'], dataPoints['Position vector Z'] ]) vec.setVelocity([ dataPoints['Velocity vector X'] / 1000., dataPoints['Velocity vector Y'] / 1000., dataPoints['Velocity vector Z'] / 1000. ]) orb.addStateVector(vec) #####Convert orbits from ECI to ECEF frame. t0 = orb._stateVectors[0]._time ang = self.leaderFile.platformPositionRecord.metadata[ 'Greenwich mean hour angle'] cOrb = ECI2ECR(orb, GAST=ang, epoch=t0) wgsorb = cOrb.convert() orb = self.frame.getOrbit() for sv in wgsorb: orb.addStateVector(sv) print(sv) def extractImage(self): import isceobj if (self.imageFile is None) or (self.leaderFile is None): self.parse() try: out = open(self.output, 'wb') except IOError as strerr: self.logger.error("IOError: %s" % strerr) self.imageFile.extractImage(output=out) out.close() ####RSAT1 is weird. Contains all useful info in RAW data and not leader. ins = self.frame.getInstrument() ins.setPulseRepetitionFrequency(self.imageFile.prf) ins.setPulseLength(self.imageFile.pulseLength) ins.setRangeSamplingRate(self.imageFile.rangeSamplingRate) ins.setRangePixelSize(Const.c / (2 * self.imageFile.rangeSamplingRate)) ins.setChirpSlope(self.imageFile.chirpSlope) ###### self.frame.setSensingStart(self.imageFile.sensingStart) sensingStop = self.imageFile.sensingStart + datetime.timedelta( seconds=((self.frame.getNumberOfLines() - 1) / self.imageFile.prf)) sensingMid = self.imageFile.sensingStart + datetime.timedelta( seconds=0.5 * (sensingStop - self.imageFile.sensingStart).total_seconds()) self.frame.setSensingStop(sensingStop) self.frame.setSensingMid(sensingMid) self.frame.setNumberOfSamples(self.imageFile.width) self.frame.setStartingRange(self.imageFile.startingRange) farRange = self.imageFile.startingRange + ins.getRangePixelSize( ) * self.imageFile.width * 0.5 self.frame.setFarRange(farRange) rawImage = isceobj.createRawImage() rawImage.setByteOrder('l') rawImage.setAccessMode('read') rawImage.setFilename(self.output) rawImage.setWidth(self.imageFile.width) rawImage.setXmin(0) rawImage.setXmax(self.imageFile.width) rawImage.renderHdr() self.frame.setImage(rawImage) def parseParFile(self): '''Parse the par file if any is available.''' if self._parFile not in (None, ''): par = ParFile(self._parFile) ####Update orbit svs = par['prep_block']['sensor']['ephemeris']['sv_block'][ 'state_vector'] datefmt = '%Y%m%d%H%M%S%f' for entry in svs: sv = StateVector() sv.setPosition( [float(entry['x']), float(entry['y']), float(entry['z'])]) sv.setVelocity([ float(entry['xv']), float(entry['yv']), float(entry['zv']) ]) sv.setTime(datetime.datetime.strptime(entry['Date'], datefmt)) self.frame.orbit.addStateVector(sv) self.frame.orbit._stateVectors = sorted( self.frame.orbit._stateVectors, key=lambda x: x.getTime()) doppinfo = par['prep_block']['sensor']['beam'][ 'DopplerCentroidParameters'] #######Selectively update some values. #######Currently used only for doppler centroids. self.doppler_ref_range = float(doppinfo['reference_range']) self.doppler_ref_azi = datetime.datetime.strptime( doppinfo['reference_date'], '%Y%m%d%H%M%S%f') self.doppler_predict = float(doppinfo['Predict_doppler']) self.doppler_DAR = float(doppinfo['DAR_doppler']) coeff = doppinfo['doppler_centroid_coefficients'] rngOrder = int(coeff['number_of_coefficients_first_dimension']) - 1 azOrder = int(coeff['number_of_coefficients_second_dimension']) - 1 self.doppler_coeff = Poly2D.Poly2D() self.doppler_coeff.initPoly(rangeOrder=rngOrder, azimuthOrder=azOrder) self.doppler_coeff.setMeanRange(self.doppler_ref_range) self.doppler_coeff.setMeanAzimuth( secondsSinceMidnight(self.doppler_ref_azi)) parms = [] for ii in range(azOrder + 1): row = [] for jj in range(rngOrder + 1): key = 'a%d%d' % (ii, jj) val = float(coeff[key]) row.append(val) parms.append(row) self.doppler_coeff.setCoeffs(parms) def extractDoppler(self): ''' Evaluate the doppler polynomial and return the average value for now. ''' rmin = self.frame.getStartingRange() rmax = self.frame.getFarRange() rmid = 0.5 * (rmin + rmax) delr = Const.c / (2 * self.frame.instrument.rangeSamplingRate) azmid = secondsSinceMidnight(self.frame.getSensingMid()) print(rmid, self.doppler_coeff.getMeanRange()) print(azmid, self.doppler_coeff.getMeanAzimuth()) if self.doppler_coeff is None: raise Exception( 'ASF PARFILE was not provided. Cannot determine default doppler.' ) dopav = self.doppler_coeff(azmid, rmid) prf = self.frame.getInstrument().getPulseRepetitionFrequency() quadratic = {} quadratic['a'] = dopav / prf quadratic['b'] = 0. quadratic['c'] = 0. ######Set up the doppler centroid computation just like CSK at mid azimuth order = self.doppler_coeff._rangeOrder rng = np.linspace(rmin, rmax, num=(order + 2)) pix = (rng - rmin) / delr val = [self.doppler_coeff(azmid, x) for x in rng] print(rng, val) print(delr, pix) fit = np.polyfit(pix, val, order) self.frame._dopplerVsPixel = list(fit[::-1]) # self.frame._dopplerVsPixel = [dopav,0.,0.,0.] return quadratic def _decodeSceneReferenceNumber(self, referenceNumber): return referenceNumber
class Sentinel1A(Component): """ A Class representing RadarSAT 2 data """ 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 getFrame(self): return self.frame def parse(self): try: fp = open(self.xml, 'r') except IOError as strerr: print("IOError: %s" % strerr) return self._xml_root = ElementTree(file=fp).getroot() # self.product.set_from_etnode(self._xml_root) self.populateMetadata() fp.close() def grab_from_xml(self, path): try: res = self._xml_root.find(path).text except: raise Exception('Tag= %s not found' % (path)) if res is None: raise Exception('Tag = %s not found' % (path)) return res def convertToDateTime(self, string): dt = datetime.datetime.strptime(string, "%Y-%m-%dT%H:%M:%S.%f") return dt def populateMetadata(self): """ Create metadata objects from the metadata files """ ####Set each parameter one - by - one mission = self.grab_from_xml('adsHeader/missionId') swath = self.grab_from_xml('adsHeader/swath') polarization = self.grab_from_xml('adsHeader/polarisation') frequency = float( self.grab_from_xml( 'generalAnnotation/productInformation/radarFrequency')) passDirection = self.grab_from_xml( 'generalAnnotation/productInformation/pass') rangePixelSize = float( self.grab_from_xml( 'imageAnnotation/imageInformation/rangePixelSpacing')) azimuthPixelSize = float( self.grab_from_xml( 'imageAnnotation/imageInformation/azimuthPixelSpacing')) rangeSamplingRate = Const.c / (2.0 * rangePixelSize) prf = 1.0 / float( self.grab_from_xml( 'imageAnnotation/imageInformation/azimuthTimeInterval')) lines = int( self.grab_from_xml( 'imageAnnotation/imageInformation/numberOfLines')) samples = int( self.grab_from_xml( 'imageAnnotation/imageInformation/numberOfSamples')) startingRange = float( self.grab_from_xml( 'imageAnnotation/imageInformation/slantRangeTime') ) * Const.c / 2.0 incidenceAngle = float( self.grab_from_xml( 'imageAnnotation/imageInformation/incidenceAngleMidSwath')) dataStartTime = self.convertToDateTime( self.grab_from_xml( 'imageAnnotation/imageInformation/productFirstLineUtcTime')) dataStopTime = self.convertToDateTime( self.grab_from_xml( 'imageAnnotation/imageInformation/productLastLineUtcTime')) pulseLength = float( self.grab_from_xml( 'generalAnnotation/downlinkInformationList/downlinkInformation/downlinkValues/txPulseLength' )) chirpSlope = float( self.grab_from_xml( 'generalAnnotation/downlinkInformationList/downlinkInformation/downlinkValues/txPulseRampRate' )) pulseBandwidth = pulseLength * chirpSlope ####Sentinel is always right looking lookSide = -1 facility = 'EU' version = '1.0' # height = self.product.imageGenerationParameters.sarProcessingInformation._satelliteHeight ####Populate platform platform = self.frame.getInstrument().getPlatform() platform.setPlanet(Planet("Earth")) platform.setMission(mission) platform.setPointingDirection(lookSide) platform.setAntennaLength(2 * azimuthPixelSize) ####Populate instrument instrument = self.frame.getInstrument() instrument.setRadarFrequency(frequency) instrument.setPulseRepetitionFrequency(prf) instrument.setPulseLength(pulseLength) instrument.setChirpSlope(pulseBandwidth / pulseLength) instrument.setIncidenceAngle(incidenceAngle) #self.frame.getInstrument().setRangeBias(0) instrument.setRangePixelSize(rangePixelSize) instrument.setRangeSamplingRate(rangeSamplingRate) instrument.setBeamNumber(swath) instrument.setPulseLength(pulseLength) #Populate Frame #self.frame.setSatelliteHeight(height) self.frame.setSensingStart(dataStartTime) self.frame.setSensingStop(dataStopTime) diffTime = DTUtil.timeDeltaToSeconds(dataStopTime - dataStartTime) / 2.0 sensingMid = dataStartTime + datetime.timedelta( microseconds=int(diffTime * 1e6)) self.frame.setSensingMid(sensingMid) self.frame.setPassDirection(passDirection) self.frame.setPolarization(polarization) self.frame.setStartingRange(startingRange) self.frame.setFarRange(startingRange + (samples - 1) * rangePixelSize) self.frame.setNumberOfLines(lines) self.frame.setNumberOfSamples(samples) self.frame.setProcessingFacility(facility) self.frame.setProcessingSoftwareVersion(version) self.frame.setPassDirection(passDirection) self.extractOrbit() def extractOrbit(self): ''' Extract orbit information from xml node. ''' node = self._xml_root.find('generalAnnotation/orbitList') frameOrbit = self.frame.getOrbit() frameOrbit.setOrbitSource('Header') for child in node.getchildren(): timestamp = self.convertToDateTime(child.find('time').text) pos = [] vel = [] posnode = child.find('position') velnode = child.find('velocity') for tag in ['x', 'y', 'z']: pos.append(float(posnode.find(tag).text)) for tag in ['x', 'y', 'z']: vel.append(float(velnode.find(tag).text)) vec = StateVector() vec.setTime(timestamp) vec.setPosition(pos) vec.setVelocity(vel) frameOrbit.addStateVector(vec) def extractImage(self): """ Use gdal_translate to extract the slc """ import tempfile import subprocess if (not self.gdal_translate): raise TypeError( "The path to executable gdal_translate was not specified") if (not os.path.exists(self.gdal_translate)): raise OSError("Could not find gdal_translate in directory %s" % os.path.dirname(self.gdal_translate)) self.parse() # Use GDAL to convert the geoTIFF file to an raster image # There should be a way to do this using the GDAL python api curdir = os.getcwd() tempdir = tempfile.mkdtemp(dir=curdir) # os.rmdir(tempdir) # Wasteful, but if the directory exists, gdal_translate freaks out #instring = 'RADARSAT_2_CALIB:UNCALIB:%s' % self.xml #process = subprocess.Popen([self.gdal_translate,'-of','MFF2','-ot','CFloat32',instring,tempdir]) if (self.tiff is None) or (not os.path.exists(self.tiff)): raise Exception( 'Path to input tiff file: %s is wrong or file doesnt exist.' % (self.tiff)) process = subprocess.Popen([ self.gdal_translate, self.tiff.strip(), '-of', 'ENVI', '-ot', 'CFloat32', '-co', 'INTERLEAVE=BIP', os.path.join(tempdir, 'image_data') ]) process.wait() # Move the output of the gdal_translate call to a reasonable file name width = self.frame.getNumberOfSamples() lgth = self.frame.getNumberOfLines() os.rename(os.path.join(tempdir, 'image_data'), self.output) # os.unlink(os.path.join(tempdir,'attrib')) os.unlink(os.path.join(tempdir, 'image_data.hdr')) os.rmdir(tempdir) #### slcImage = isceobj.createSlcImage() slcImage.setByteOrder('l') slcImage.setFilename(self.output) slcImage.setAccessMode('read') slcImage.setWidth(self.frame.getNumberOfSamples()) slcImage.setLength(self.frame.getNumberOfLines()) slcImage.setXmin(0) slcImage.setXmax(self.frame.getNumberOfSamples()) self.frame.setImage(slcImage) def extractDoppler(self): ''' self.parse() Extract doppler information as needed by mocomp ''' # ins = self.frame.getInstrument() # dc = self.product.imageGenerationParameters.dopplerCentroid quadratic = {} # r0 = self.frame.startingRange # fs = ins.getRangeSamplingRate() # tNear = 2*r0/Const.c # tMid = tNear + 0.5*self.frame.getNumberOfSamples()/fs # t0 = dc.dopplerCentroidReferenceTime # poly = dc.dopplerCentroidCoefficients # fd_mid = 0.0 # for kk in range(len(poly)): # fd_mid += poly[kk] * (tMid - t0)**kk # quadratic['a'] = fd_mid / ins.getPulseRepetitionFrequency() quadratic['a'] = 0. quadratic['b'] = 0. quadratic['c'] = 0. return quadratic
class Radarsat1(Component): """ Code to read CEOSFormat leader files for Radarsat-1 SAR data. The tables used to create this parser are based on document number ER-IS-EPO-GS-5902.1 from the European Space Agency. """ auxLength = 50 def __init__(self): Component.__init__(self) self._leaderFile = None self._imageFile = None self._parFile = None self.output = None self.imageFile = None self.leaderFile = None #####Soecific doppler functions for RSAT1 self.doppler_ref_range = None self.doppler_ref_azi = None self.doppler_predict = None self.doppler_DAR = None self.doppler_coeff = None self.frame = Frame() self.frame.configure() self.constants = {'polarization': 'HH', 'antennaLength': 15} self.descriptionOfVariables = {} self.dictionaryOfVariables = { 'LEADERFILE': ['self._leaderFile', 'str', 'mandatory'], 'IMAGEFILE': ['self._imageFile', 'str', 'mandatory'], 'PARFILE': ['self._parFile', 'str', 'optional'], 'OUTPUT': ['self.output', 'str', 'optional'] } def getFrame(self): return self.frame def parse(self): self.leaderFile = LeaderFile(self, file=self._leaderFile) self.leaderFile.parse() self.imageFile = ImageFile(self, file=self._imageFile) self.imageFile.parse() self.populateMetadata() def populateMetadata(self): """ Create the appropriate metadata objects from our CEOSFormat metadata """ frame = self._decodeSceneReferenceNumber( self.leaderFile.sceneHeaderRecord. metadata['Scene reference number']) try: rangePixelSize = Const.c / (2 * self.leaderFile.sceneHeaderRecord. metadata['Range sampling rate'] * 1e6) except ZeroDivisionError: rangePixelSize = 0 ins = self.frame.getInstrument() platform = ins.getPlatform() platform.setMission(self.leaderFile.sceneHeaderRecord. metadata['Sensor platform mission identifier']) platform.setAntennaLength(self.constants['antennaLength']) platform.setPointingDirection(-1) platform.setPlanet(Planet('Earth')) ins.setRadarWavelength( self.leaderFile.sceneHeaderRecord.metadata['Radar wavelength']) ins.setIncidenceAngle(self.leaderFile.sceneHeaderRecord. metadata['Incidence angle at scene centre']) ##RSAT-1 does not have PRF for raw data in leader file. # self.frame.getInstrument().setPulseRepetitionFrequency(self.leaderFile.sceneHeaderRecord.metadata['Pulse Repetition Frequency']) ins.setRangePixelSize(rangePixelSize) ins.setPulseLength( self.leaderFile.sceneHeaderRecord.metadata['Range pulse length'] * 1e-6) chirpPulseBandwidth = 15.50829e6 # Is this really not in the CEOSFormat Header? ins.setChirpSlope( chirpPulseBandwidth / (self.leaderFile.sceneHeaderRecord.metadata['Range pulse length'] * 1e-6)) ins.setInPhaseValue(7.5) ins.setQuadratureValue(7.5) self.frame.setFrameNumber(frame) self.frame.setOrbitNumber( self.leaderFile.sceneHeaderRecord.metadata['Orbit number']) self.frame.setProcessingFacility( self.leaderFile.sceneHeaderRecord. metadata['Processing facility identifier']) self.frame.setProcessingSystem( self.leaderFile.sceneHeaderRecord. metadata['Processing system identifier']) self.frame.setProcessingSoftwareVersion( self.leaderFile.sceneHeaderRecord. metadata['Processing version identifier']) self.frame.setPolarization(self.constants['polarization']) self.frame.setNumberOfLines( self.imageFile.imageFDR.metadata['Number of lines per data set']) self.frame.setNumberOfSamples( self.imageFile.imageFDR. metadata['Number of pixels per line per SAR channel']) self.frame.getOrbit().setOrbitSource('Header') self.frame.getOrbit().setOrbitQuality( self.leaderFile.platformPositionRecord. metadata['Orbital elements designator']) t0 = datetime.datetime(year=self.leaderFile.platformPositionRecord. metadata['Year of data point'], month=self.leaderFile.platformPositionRecord. metadata['Month of data point'], day=self.leaderFile.platformPositionRecord. metadata['Day of data point']) t0 = t0 + datetime.timedelta( seconds=self.leaderFile.platformPositionRecord. metadata['Seconds of day']) #####Read in orbit in inertial coordinates orb = Orbit() for i in range(self.leaderFile.platformPositionRecord. metadata['Number of data points']): vec = StateVector() t = t0 + datetime.timedelta( seconds=(i * self.leaderFile.platformPositionRecord. metadata['Time interval between DATA points'])) vec.setTime(t) dataPoints = self.leaderFile.platformPositionRecord.metadata[ 'Positional Data Points'][i] vec.setPosition([ dataPoints['Position vector X'], dataPoints['Position vector Y'], dataPoints['Position vector Z'] ]) vec.setVelocity([ dataPoints['Velocity vector X'] / 1000., dataPoints['Velocity vector Y'] / 1000., dataPoints['Velocity vector Z'] / 1000. ]) orb.addStateVector(vec) #####Convert orbits from ECI to ECEF frame. convOrb = ECI2ECEF(orb, eci='ECI_TOD') wgsorb = convOrb.convert() orb = self.frame.getOrbit() for sv in wgsorb: orb.addStateVector(sv) self.parseParFile() def extractImage(self): import isceobj if (self.imageFile is None) or (self.leaderFile is None): self.parse() try: out = open(self.output, 'wb') except IOError as strerr: self.logger.error("IOError: %s" % strerr) self.imageFile.extractImage(output=out) out.close() ####RSAT1 is weird. Contains all useful info in RAW data and not leader. ins = self.frame.getInstrument() ins.setPulseRepetitionFrequency(self.imageFile.prf) ins.setPulseLength(self.imageFile.pulseLength) ins.setRangeSamplingRate(self.imageFile.rangeSamplingRate) ins.setRangePixelSize(Const.c / (2 * self.imageFile.rangeSamplingRate)) ins.setChirpSlope(self.imageFile.chirpSlope) ###### self.frame.setSensingStart(self.imageFile.sensingStart) sensingStop = self.imageFile.sensingStart + datetime.timedelta( seconds=((self.frame.getNumberOfLines() - 1) / self.imageFile.prf)) sensingMid = self.imageFile.sensingStart + datetime.timedelta( seconds=0.5 * (sensingStop - self.imageFile.sensingStart).total_seconds()) self.frame.setSensingStop(sensingStop) self.frame.setSensingMid(sensingMid) self.frame.setNumberOfSamples(self.imageFile.width) self.frame.setStartingRange(self.imageFile.startingRange) farRange = self.imageFile.startingRange + ins.getRangePixelSize( ) * self.imageFile.width * 0.5 self.frame.setFarRange(farRange) rawImage = isceobj.createRawImage() rawImage.setByteOrder('l') rawImage.setAccessMode('read') rawImage.setFilename(self.output) rawImage.setWidth(self.imageFile.width) rawImage.setXmin(0) rawImage.setXmax(self.imageFile.width) rawImage.renderHdr() self.frame.setImage(rawImage) def parseParFile(self): '''Parse the par file if any is available.''' if self._parFile not in (None, ''): par = ParFile(self._parFile) doppinfo = par['prep_block']['sensor']['beam'][ 'DopplerCentroidParameters'] #######Selectively update some values. #######Currently used only for doppler centroids. self.doppler_ref_range = float(doppinfo['reference_range']) self.doppler_ref_azi = datetime.datetime.strptime( doppinfo['reference_date'], '%Y%m%d%H%M%S%f') self.doppler_predict = float(doppinfo['Predict_doppler']) self.doppler_DAR = float(doppinfo['DAR_doppler']) coeff = doppinfo['doppler_centroid_coefficients'] rngOrder = int(coeff['number_of_coefficients_first_dimension']) azOrder = int(coeff['number_of_coefficients_second_dimension']) self.doppler_coeff = Polynomial(rangeOrder=rngOrder, azimuthOrder=azOrder) self.doppler_coeff.setMeanRange(self.doppler_ref_range) self.doppler_coeff.setMeanAzimuth( secondsSinceMidnight(self.doppler_ref_azi)) for ii in range(azOrder): for jj in range(rngOrder): key = 'a%d%d' % (ii, jj) val = float(coeff[key]) self.doppler_coeff.setCoeff(ii, jj, val) def extractDoppler(self): ''' Evaluate the doppler polynomial and return the average value for now. ''' rmin = self.frame.getStartingRange() rmax = self.frame.getFarRange() rmid = 0.5 * (rmin + rmax) azmid = secondsSinceMidnight(self.frame.getSensingMid()) print(rmid, self.doppler_coeff.getMeanRange()) print(azmid, self.doppler_coeff.getMeanAzimuth()) if self.doppler_coeff is None: raise Exception( 'ASF PARFILE was not provided. Cannot determine default doppler.' ) dopav = self.doppler_coeff(azmid, rmid) prf = self.frame.getInstrument().getPulseRepetitionFrequency() quadratic = {} quadratic['a'] = dopav / prf quadratic['b'] = 0. quadratic['c'] = 0. return quadratic def _decodeSceneReferenceNumber(self, referenceNumber): return referenceNumber
class UAVSAR_RPI(Sensor): """ A class representing a UAVSAR SLC. """ family = 'uavsar_rpi' logging_name = 'isce.Sensor.UAVSAR_RPI' lookMap = {'RIGHT': -1, 'LEFT': 1} parameter_list = (METADATAFILE, ) + Sensor.parameter_list def __init__(self, name=''): # print("UAVSAR_RPI: self.family, name = ", self.family, name) super().__init__(family=self.family, name=name) self.frame = Frame() self.frame.configure() return def _populatePlatform(self, **kwargs): # print("UAVSAR_RPI._populatePlatform") platform = self.frame.getInstrument().getPlatform() platform.setMission('UAVSAR') platform.setPointingDirection( self.lookMap[self.metadata['Radar Look Direction'].upper()]) platform.setPlanet(Planet(pname="Earth")) platform.setAntennaLength(1.5) # Thierry Michel return def _populateInstrument(self, **kwargs): # print("UAVSAR_RPI._populateInstrument") instrument = self.frame.getInstrument() instrument.setRadarWavelength(self.metadata['Center Wavelength']) fudgefactor = 1.0 / 1.0735059946800756 instrument.setPulseRepetitionFrequency( fudgefactor * 1.0 / self.metadata['Average Pulse Repetition Interval']) # print("instrument.getPulseRepetitionFrequency() = ", # instrument.getPulseRepetitionFrequency(), # type(instrument.getPulseRepetitionFrequency())) instrument.setRangePixelSize( self.metadata['Single Look Complex Data Range Spacing']) instrument.setAzimuthPixelSize( self.metadata['Single Look Complex Data Azimuth Spacing']) instrument.setPulseLength(self.metadata['Pulse Length']) instrument.setChirpSlope(-self.metadata['Bandwidth'] / self.metadata['Pulse Length']) from isceobj.Constants.Constants import SPEED_OF_LIGHT instrument.setRangeSamplingRate(SPEED_OF_LIGHT / 2.0 / instrument.getRangePixelSize()) instrument.setIncidenceAngle( 0.5 * (self.metadata['Average Look Angle in Near Range'] + self.metadata['Average Look Angle in Far Range'])) return def _populateFrame(self, **kwargs): # print("UAVSAR_RPI._populateFrame") if self.metadata['UAVSAR RPI Annotation File Version Number']: # print("UAVSAR_RPI._populateFrame, pair = True") if self.name.lower() == 'reference': sip1 = str(1) else: sip1 = str(2) print("UAVSAR_RPI._populateFrame, 1-based index = ", sip1) self._populateFrameFromPair(sip1) else: # print("UAVSAR_RPI._populateFrame, pair = False") self._populateFrameSolo() pass def _populateFrameFromPair(self, sip1): # print("UAVSAR_RPI._populateFrameFromPair: metadatafile = ", # self.metadataFile) #Get the Start, Mid, and Stop times import datetime tStart = datetime.datetime.strptime( self.metadata['Start Time of Acquisition for Pass ' + sip1], "%d-%b-%Y %H:%M:%S %Z") tStop = datetime.datetime.strptime( self.metadata['Stop Time of Acquisition for Pass ' + sip1], "%d-%b-%Y %H:%M:%S %Z") dtMid = DTU.timeDeltaToSeconds(tStop - tStart) / 2. # print("dtMid = ", dtMid) tMid = tStart + datetime.timedelta(microseconds=int(dtMid * 1e6)) # print("tStart = ", tStart) # print("tMid = ", tMid) # print("tStop = ", tStop) frame = self.frame frame.setSensingStart(tStart) frame.setSensingStop(tStop) frame.setSensingMid(tMid) frame.setNumberOfLines( int(self.metadata['Single Look Complex Data Azimuth Lines'])) frame.setNumberOfSamples( int(self.metadata['Single Look Complex Data Range Samples'])) frame.setPolarization(self.metadata['Polarization']) frame.C0 = self.metadata['Single Look Complex Data at Near Range'] frame.S0 = self.metadata['Single Look Complex Data Starting Azimuth'] frame.nearLookAngle = self.metadata['Average Look Angle in Near Range'] frame.farLookAngle = self.metadata['Average Look Angle in Far Range'] # print("frame.nearLookAngle = ", math.degrees(frame.nearLookAngle)) # frame.setStartingAzimuth(frame.S0) self.extractDoppler() frame.setStartingRange(self.startingRange) frame.platformHeight = self.platformHeight # print("platformHeight, startingRange = ", self.platformHeight, frame.getStartingRange()) width = frame.getNumberOfSamples() deltaRange = frame.instrument.getRangePixelSize() nearRange = frame.getStartingRange() midRange = nearRange + (width / 2.) * deltaRange frame.setFarRange(nearRange + width * deltaRange) frame.peg = self.peg # print("frame.peg = ", frame.peg) frame.procVelocity = self.velocity # print("frame.procVelocity = ", frame.procVelocity) from isceobj.Location.Coordinate import Coordinate frame.terrainHeight = self.terrainHeight frame.upperLeftCorner = Coordinate() frame.upperLeftCorner.setLatitude( math.degrees(self.metadata['Approximate Upper Left Latitude'])) frame.upperLeftCorner.setLongitude( math.degrees(self.metadata['Approximate Upper Left Longitude'])) frame.upperLeftCorner.setHeight(self.terrainHeight) frame.upperRightCorner = Coordinate() frame.upperRightCorner.setLatitude( math.degrees(self.metadata['Approximate Upper Right Latitude'])) frame.upperRightCorner.setLongitude( math.degrees(self.metadata['Approximate Upper Right Longitude'])) frame.upperRightCorner.setHeight(self.terrainHeight) frame.lowerRightCorner = Coordinate() frame.lowerRightCorner.setLatitude( math.degrees(self.metadata['Approximate Lower Right Latitude'])) frame.lowerRightCorner.setLongitude( math.degrees(self.metadata['Approximate Lower Right Longitude'])) frame.lowerRightCorner.setHeight(self.terrainHeight) frame.lowerLeftCorner = Coordinate() frame.lowerLeftCorner.setLatitude( math.degrees(self.metadata['Approximate Lower Left Latitude'])) frame.lowerLeftCorner.setLongitude( math.degrees(self.metadata['Approximate Lower Left Longitude'])) frame.lowerLeftCorner.setHeight(self.terrainHeight) frame.nearLookAngle = math.degrees( self.metadata['Average Look Angle in Near Range']) frame.farLookAngle = math.degrees( self.metadata['Average Look Angle in Far Range']) return def _populateFrameSolo(self): print("UAVSAR_RPI._populateFrameSolo") def _populateExtras(self): pass def _populateOrbit(self, **kwargs): """ Create the orbit as the reference orbit defined by the peg """ # print("UAVSAR_RPI._populateOrbit") numExtra = 10 deltaFactor = 200 dt = deltaFactor * 1.0 / self.frame.instrument.getPulseRepetitionFrequency( ) t0 = (self.frame.getSensingStart() - datetime.timedelta(microseconds=int(numExtra * dt * 1e6))) ds = deltaFactor * self.frame.instrument.getAzimuthPixelSize() s0 = self.platformStartingAzimuth - numExtra * ds # print("populateOrbit: t0, startingAzimuth, platformStartingAzimuth, s0, ds = ", # t0, self.frame.S0, self.platformStartingAzimuth, s0, ds) h = self.platformHeight v = [self.velocity, 0., 0.] # print("t0, dt = ", t0, dt) # print("s0, ds, h = ", s0, ds, h) # print("v = ", v[0]) platform = self.frame.getInstrument().getPlatform() elp = platform.getPlanet().get_elp() elp.setSCH(self.peg.latitude, self.peg.longitude, self.peg.heading) orbit = self.frame.getOrbit() orbit.setOrbitSource('Header') # print("_populateOrbit: self.frame.numberOfLines, numExtra = ", self.frame.getNumberOfLines(), numExtra) for i in range(self.frame.getNumberOfLines() + numExtra): vec = OrbitStateVector() t = t0 + datetime.timedelta(microseconds=int(i * dt * 1e6)) vec.setTime(t) posSCH = [s0 + i * ds * (elp.pegRadCur + h) / elp.pegRadCur, 0., h] velSCH = v posXYZ, velXYZ = elp.schdot_to_xyzdot(posSCH, velSCH) vec.setPosition(posXYZ) vec.setVelocity(velXYZ) orbit.addStateVector(vec) # if i%1000 == 0 or i>self.frame.getNumberOfLines()+numExtra-3 or i < 3: # print("vec = ", vec) return def populateMetadata(self): self._populatePlatform() self._populateInstrument() self._populateFrame() # self.extractDoppler() self._populateOrbit() def extractImage(self): from iscesys.Parsers import rdf self.metadata = rdf.parse(self.metadataFile) self.populateMetadata() slcImage = isceobj.createSlcImage() if self.name == 'reference' or self.name == 'scene1': self.slcname = self.metadata['Single Look Complex Data of Pass 1'] elif self.name == 'secondary' or self.name == 'scene2': self.slcname = self.metadata['Single Look Complex Data of Pass 2'] else: print("Unrecognized sensor.name = ", sensor.name) import sys sys.exit(0) slcImage.setFilename(self.slcname) slcImage.setXmin(0) slcImage.setXmax(self.frame.getNumberOfSamples()) slcImage.setWidth(self.frame.getNumberOfSamples()) slcImage.setAccessMode('r') self.frame.setImage(slcImage) return def extractDoppler(self): # print("UAVSAR_RPI._extractDoppler") #Recast the Near, Mid, and Far Reskew Doppler values #into three RDF records because they were not parsed #correctly by the RDF parser; it was parsed as a string. #Use the RDF parser on the individual Doppler values to #do the unit conversion properly. #The units, and values parsed from the metadataFile key = "Reskew Doppler Near Mid Far" u = self.metadata.data[key].units.split(',') v = map(float, self.metadata.data[key].value.split()) k = ["Reskew Doppler " + x for x in ("Near", "Mid", "Far")] #Use the interactive RDF accumulator to create an RDF object #for the near, mid, and far Doppler values from iscesys.Parsers.rdf import iRDF dop = iRDF.RDFAccumulator() for z in zip(k, u, v): dop("%s (%s) = %f" % z) self.dopplerVals = {} for r in dop.record_list: self.dopplerVals[r.key.split()[-1]] = r.field.value self.dopplerVals['Mid'] = self.dopplerVals['Mid'] self.dopplerVals['Far'] = self.dopplerVals['Far'] # print("UAVSAR_RPI: dopplerVals = ", self.dopplerVals) #quadratic model using Near, Mid, Far range doppler values #UAVSAR has a subroutine to compute doppler values at each pixel #that should be used instead. frame = self.frame instrument = frame.getInstrument() width = frame.getNumberOfSamples() deltaRange = instrument.getRangePixelSize() nearRangeBin = 0. midRangeBin = float(int((width - 1.0) / 2.0)) farRangeBin = width - 1.0 import numpy A = numpy.matrix([[1.0, nearRangeBin, nearRangeBin**2], [1.0, midRangeBin, midRangeBin**2], [1.0, farRangeBin, farRangeBin**2]]) d = numpy.matrix([ self.dopplerVals['Near'], self.dopplerVals['Mid'], self.dopplerVals['Far'] ]).transpose() coefs = (numpy.linalg.inv(A) * d).transpose().tolist()[0] prf = instrument.getPulseRepetitionFrequency() # print("UAVSAR_RPI.extractDoppler: self.dopplerVals = ", self.dopplerVals) # print("UAVSAR_RPI.extractDoppler: prf = ", prf) # print("UAVSAR_RPI.extractDoppler: A, d = ", A, d) # print("UAVSAR_RPI.extractDoppler: coefs = ", coefs) coefs = {'a': coefs[0] / prf, 'b': coefs[1] / prf, 'c': coefs[2] / prf} # print("UAVSAR_RPI.extractDoppler: coefs normalized by prf = ", coefs) #Set the coefs in frame._dopplerVsPixel because that is where DefaultDopp looks for them self.frame._dopplerVsPixel = coefs return coefs @property def terrainHeight(self): return self.metadata['Global Average Terrain Height'] @property def platformHeight(self): return self.metadata['Global Average Altitude'] @property def platformStartingAzimuth(self): # r, a = self.getStartingRangeAzimuth() # return a h = self.platformHeight peg = self.peg platform = self.frame.getInstrument().getPlatform() elp = platform.getPlanet().get_elp() elp.setSCH(peg.latitude, peg.longitude, peg.heading) rc = elp.pegRadCur range = self.startingRange wavl = self.frame.getInstrument().getRadarWavelength() fd = self.dopplerVals['Near'] v = self.velocity tanbeta = (fd * wavl / v) * range * (rc + h) / (range**2 - (rc + h)**2 - rc**2) beta = math.atan(tanbeta) # th = self.metadata['Global Average Terrain Height'] # sinTheta = math.sqrt( 1 - ((h-th)/range)**2 ) # squint = math.radians(self.squintAngle) # c0 = self.startingRange*sinTheta*math.cos(squint) # print("platformStartingAzimuth: c0 = ", c0) # gamma = c0/rc # cosbeta = -(range**2-(rc+h)**2-rc**2)/(2.*rc*(rc+h)*math.cos(gamma)) # sinbeta = -fd*range*wavl/(2.*rc*v*math.cos(gamma)) # beta = math.atan2(sinbeta,cosbeta) t = beta * (rc + h) / v pDS = v * t azimuth = self.frame.S0 #- pDS + 473. return azimuth @property def startingRange(self): # r, a = self.getStartingRangeAzimuth() # return r return self.metadata['Single Look Complex Data at Near Range'] @property def squintAngle(self): """ Update this to use the sphere rather than planar approximation. """ startingRange = self.startingRange h = self.platformHeight v = self.velocity prf = self.frame.getInstrument().getPulseRepetitionFrequency() wavelength = self.frame.getInstrument().getRadarWavelength() if h > startingRange: raise ValueError("Spacecraft Height too large (%s>%s)" % (h, startingRange)) sinTheta = math.sqrt(1 - (h / startingRange)**2) fd = self.dopplerVals['Near'] sinSquint = fd / (2.0 * v * sinTheta) * wavelength # print("calculateSquint: h = ", h) # print("calculateSquint: startingRange = ", startingRange) # print("calculateSquint: sinTheta = ", sinTheta) # print("calculateSquint: self.dopplerVals['Near'] = ", self.dopplerVals['Near']) # print("calculateSquint: prf = ", prf) # print("calculateSquint: fd = ", fd) # print("calculateSquint: v = ", v) # print("calculateSquint: wavelength = ", wavelength) # print("calculateSquint: sinSquint = ", sinSquint) if sinSquint**2 > 1: raise ValueError( "Error in One or More of the Squint Calculation Values\n" + "Doppler Centroid: %s\nVelocity: %s\nWavelength: %s\n" % (fd, v, wavelength)) self.squint = math.degrees( math.atan2(sinSquint, math.sqrt(1 - sinSquint**2))) #jng squint is also used later on from the frame, just add it here self.frame.squintAngle = math.radians(self.squint) # print("UAVSAR_RPI: self.frame.squintAngle = ", self.frame.squintAngle) return self.squint def getStartingRangeAzimuth(self): peg = self.peg platform = self.frame.getInstrument().getPlatform() elp = platform.getPlanet().get_elp() elp.setSCH(peg.latitude, peg.longitude, peg.heading) rc = elp.pegRadCur # assert(abs(rc-6370285.323386391) < 0.1) h = self.platformHeight # assert(abs(h-12494.4008) < 0.01) # c0 = self.frame.C0 # assert(abs(c0-13450.0141) < 0.01) fd = self.dopplerVals['Near'] # assert(abs(fd-84.21126622) < 0.01) wavl = self.frame.getInstrument().getRadarWavelength() # assert(abs((wavl-23.8403545e-2) /wavl) < 0.01) gamma = c0 / rc v = self.velocity # assert(abs(v-234.84106135055598) < 0.01) A = (fd * wavl / v)**2 * (1 + h / rc)**2 B = 1. + (1. + h / rc)**2 C = 2.0 * (1 + h / rc) * math.cos(gamma) # assert(abs(A-0.0073370197515515235) < 0.00001) # assert(abs(B-2.003926560005551) < 0.0001) # assert(abs(C-2.0039182464710574) < 0.0001) A2B = A / 2. - B D = (A / 2. - B)**2 - (B**2 - C**2) x2p = -(A / 2. - B) + math.sqrt(D) x2m = -(A / 2. - B) - math.sqrt(D) # assert(abs(x2m-8.328781731403723e-06) < 1.e-9) range = rc * math.sqrt(x2m) # assert(abs(range-18384.406963585432) < 0.1) sinbeta = -fd * range * wavl / (2. * rc * v * math.cos(gamma)) cosbeta = -(range**2 - (rc + h)**2 - rc**2) / (2. * rc * (rc + h) * math.cos(gamma)) # assert(abs(sinbeta**2+cosbeta**2 - 1.0) < 0.00001) beta = math.atan2(sinbeta, cosbeta) # assert(abs(beta+0.00012335892779153295) < 0.000001) t = beta * (rc + h) / v # assert(abs(t+3.3527904301617375) < 0.001) pDS = v * t # assert(abs(pDS+787.3728631051696) < 0.01) azimuth = self.frame.S0 #self.frame.getStartingAzimuth() #- pDS return range, azimuth @property def heightDt(self): """ Delta(height)/Delta(Time) from frame start-time to mid-time """ return 0.0 @property def velocity(self): platform = self.frame.getInstrument().getPlatform() elp = platform.getPlanet().get_elp() peg = self.peg elp.setSCH(peg.latitude, peg.longitude, peg.heading) rc = elp.pegRadCur scale = (elp.pegRadCur + self.platformHeight) / elp.pegRadCur ds_ground = self.frame.instrument.getAzimuthPixelSize() dt = 1.0 / self.frame.instrument.getPulseRepetitionFrequency() v = scale * ds_ground / dt return v @property def peg(self): peg = [ math.degrees(self.metadata['Peg Latitude']), math.degrees(self.metadata['Peg Longitude']), math.degrees(self.metadata['Peg Heading']) ] platform = self.frame.getInstrument().getPlatform() elp = platform.getPlanet().get_elp() elp.setSCH(*peg) rc = elp.pegRadCur from isceobj.Location.Peg import Peg return Peg(latitude=peg[0], longitude=peg[1], heading=peg[2], radiusOfCurvature=rc)
class UAVSAR_mlcStack(Component): """ A class representing a UAVSAR SLC. """ family = 'uavsar_mlcstack' logging_name = 'isce.Sensor.UAVSAR_mlcStack' lookMap = {'RIGHT': -1, 'LEFT': 1} parameter_list = (METADATAFILE, SEGMENT_INDEX) @logged 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 _populatePlatform(self, **kwargs): platform = self.frame.getInstrument().getPlatform() platform.setMission('UAVSAR') platform.setPointingDirection( self.lookMap[self.metadata['Look Direction'].upper()]) platform.setPlanet(Planet(pname="Earth")) platform.setAntennaLength(self.metadata['Antenna Length']) return def _populateInstrument(self, **kwargs): instrument = self.frame.getInstrument() instrument.setRadarWavelength(self.metadata['Center Wavelength']) instrument.setPulseRepetitionFrequency( 1.0 / self.metadata['Average Pulse Repetition Interval']) instrument.setRangePixelSize( self.metadata['1x1 SLC Range Pixel Spacing']) instrument.setAzimuthPixelSize( self.metadata['1x1 SLC Azimuth Pixel Spacing']) instrument.setPulseLength(self.metadata['Pulse Length']) instrument.setChirpSlope(-self.metadata['Bandwidth'] / self.metadata['Pulse Length']) from isceobj.Constants.Constants import SPEED_OF_LIGHT instrument.setRangeSamplingRate(SPEED_OF_LIGHT / 2.0 / instrument.getRangePixelSize()) instrument.setIncidenceAngle(0.5 * (self.metadata['Minimum Look Angle'] + self.metadata['Maximum Look Angle'])) return def _populateFrame(self): #Get the Start, Mid, and Stop times import datetime tStart = datetime.datetime.strptime( self.metadata['Start Time of Acquisition'], "%d-%b-%Y %H:%M:%S %Z") tStop = datetime.datetime.strptime( self.metadata['Stop Time of Acquisition'], "%d-%b-%Y %H:%M:%S %Z") dtMid = DTU.timeDeltaToSeconds(tStop - tStart) / 2. tMid = tStart + datetime.timedelta(microseconds=int(dtMid * 1e6)) frame = self.frame frame._frameNumber = 1 frame._trackNumber = 1 frame.setSensingStart(tStart) frame.setSensingStop(tStop) frame.setSensingMid(tMid) frame.setNumberOfLines(int(self.metadata['slc_1_1x1_mag.set_rows'])) frame.setNumberOfSamples(int(self.metadata['slc_1_1x1_mag.set_cols'])) frame.setPolarization(self.metadata['Polarization']) frame.C0 = self.metadata['slc_1_1x1_mag.col_addr'] frame.S0 = self.metadata['Segment {} Data Starting Azimuth'.format( self.segment_index)] frame.nearLookAngle = self.metadata['Minimum Look Angle'] frame.farLookAngle = self.metadata['Maximum Look Angle'] frame.setStartingRange(self.startingRange) frame.platformHeight = self.platformHeight width = frame.getNumberOfSamples() deltaRange = frame.instrument.getRangePixelSize() nearRange = frame.getStartingRange() midRange = nearRange + (width / 2.) * deltaRange frame.setFarRange(nearRange + width * deltaRange) #self.extractDoppler() frame._ellipsoid = self.elp frame.peg = self.peg frame.procVelocity = self.velocity from isceobj.Location.Coordinate import Coordinate frame.upperLeftCorner = Coordinate() #The corner latitude, longitudes are given as a pair #of values in degrees at each corner (without rdf unit specified) llC = [] for ic in range(1, 5): key = 'Segment {0} Data Approximate Corner {1}'.format( self.segment_index, ic) self.logger.info("key = {}".format(key)) self.logger.info("metadata[key] = {}".format( self.metadata[key], type(self.metadata[key]))) llC.append(list(map(float, self.metadata[key].split(',')))) frame.terrainHeight = self.terrainHeight frame.upperLeftCorner.setLatitude(llC[0][0]) frame.upperLeftCorner.setLongitude(llC[0][1]) frame.upperLeftCorner.setHeight(self.terrainHeight) frame.upperRightCorner = Coordinate() frame.upperRightCorner.setLatitude(llC[1][0]) frame.upperRightCorner.setLongitude(llC[1][1]) frame.upperRightCorner.setHeight(self.terrainHeight) frame.lowerRightCorner = Coordinate() frame.lowerRightCorner.setLatitude(llC[2][0]) frame.lowerRightCorner.setLongitude(llC[2][1]) frame.lowerRightCorner.setHeight(self.terrainHeight) frame.lowerLeftCorner = Coordinate() frame.lowerLeftCorner.setLatitude(llC[3][0]) frame.lowerLeftCorner.setLongitude(llC[3][1]) frame.lowerLeftCorner.setHeight(self.terrainHeight) frame.nearLookAngle = math.degrees(self.metadata['Minimum Look Angle']) frame.farLookAngle = math.degrees(self.metadata['Maximum Look Angle']) return def _populateFrameSolo(self): self.logger.info("UAVSAR_mlcStack._populateFrameSolo") def _populateExtras(self): pass def _populateOrbit(self, **kwargs): """ Create the orbit as the reference orbit defined by the peg """ numgroup = 1000 prf = self.frame.instrument.getPulseRepetitionFrequency() daz = self.frame.instrument.getAzimuthPixelSize() vel = daz * prf t0 = self.frame.getSensingStart() nlines = int((self.frame.getSensingStop() - t0).total_seconds() * prf) #make sure the elp property has been called elp = self.elp orbit = self.frame.getOrbit() orbit.setOrbitSource('Header') for i in range(-5 * numgroup, int(nlines / numgroup) * numgroup + 5 * numgroup, numgroup): delt = int(i * 1.0e6 / prf) torb = self.frame.getSensingStart() + datetime.timedelta( microseconds=delt) ###Need to compute offset ###While taking into account, rounding off in time ds = delt * 1.0e-6 * vel vec = OrbitStateVector() vec.setTime(torb) posSCH = [self.frame.S0 + ds, 0.0, self.platformHeight] velSCH = [self.velocity, 0., 0.] posXYZ, velXYZ = elp.schdot_to_xyzdot(posSCH, velSCH) vec.setPosition(posXYZ) vec.setVelocity(velXYZ) orbit.addStateVector(vec) return #t0 = (self.frame.getSensingStart() - #datetime.timedelta(microseconds=delta)) #ds = deltaFactor*self.frame.instrument.getAzimuthPixelSize() #s0 = self.platformStartingAzimuth - numExtra*ds #self.logger.info("populateOrbit: frame.sensingStart, frame.sensingStop = ", self.frame.getSensingStart(), #self.frame.getSensingStop()) #self.logger.info("populateOrbit: deltaFactor, numExtra, dt = ", deltaFactor, numExtra, dt) #self.logger.info("populateOrbit: t0, startingAzimuth, platformStartingAzimuth, s0, ds = ", #t0, self.frame.S0, self.platformStartingAzimuth, s0, ds) #h = self.platformHeight #v = [self.velocity, 0., 0.] #self.logger.info("t0, dt = ", t0, dt) #self.logger.info("s0, ds, h = ", s0, ds, h) #self.logger.info("elp.pegRadCur = ", self.elp.pegRadCur) #self.logger.info("v = ", v[0]) #platform = self.frame.getInstrument().getPlatform() #elp = self.elp #make sure the elp property has been called #orbit = self.frame.getOrbit() #orbit.setOrbitSource('Header') #for i in range(int(self.frame.getNumberOfLines()/deltaFactor)+1000*numExtra+1): #vec = OrbitStateVector() #t = t0 + datetime.timedelta(microseconds=int(i*dt*1e6)) #vec.setTime(t) #posSCH = [s0 + i*ds , 0., h] #velSCH = v #posXYZ, velXYZ = self.elp.schdot_to_xyzdot(posSCH, velSCH) #sch_pos, sch_vel = elp.xyzdot_to_schdot(posXYZ, velXYZ) #vec.setPosition(posXYZ) #vec.setVelocity(velXYZ) #orbit.addStateVector(vec) #return def populateMetadata(self): self._populatePlatform() self._populateInstrument() self._populateFrame() #self.extractDoppler() self._populateOrbit() def parse(self): from iscesys.Parsers import rdf self.metadata = rdf.parse(self.metadataFile) self.populateMetadata() def extractImage(self): self.parse() slcImage = isceobj.createSlcImage() self.slcname = self.metadata['slc_{}_1x1'.format(self.segment_index)] slcImage.setFilename(self.slcname) slcImage.setXmin(0) slcImage.setXmax(self.frame.getNumberOfSamples()) slcImage.setWidth(self.frame.getNumberOfSamples()) slcImage.setLength(self.frame.getNumberOfLines()) #add sk slcImage.setAccessMode('r') self.frame.setImage(slcImage) return def extractDoppler(self): """ Read doppler values from the doppler file and fit a polynomial """ frame = self.frame instrument = frame.getInstrument() rho0 = frame.getStartingRange() drho = instrument.getRangePixelSize( ) #full res value, not spacing in the dop file prf = instrument.getPulseRepetitionFrequency() self.logger.info("extractDoppler: rho0, drho, prf = {}, {}, {}".format( rho0, drho, prf)) dopfile = self.metadata['dop'] f = open(dopfile, 'r') x = f.readlines() #first line is a header import numpy z = numpy.array( [list(map(float, e)) for e in list(map(str.split, x[1:]))]) rho = z[:, 0] dop = z[:, 1] #rho0 = rho[0] #drho = (rho[1] - rho[0])/2.0 rhoi = [(r - rho0) / drho for r in rho] polydeg = 6 #2 #Quadratic is built in for now fit = numpy.polynomial.polynomial.polyfit(rhoi, dop, polydeg, rcond=1.e-9, full=True) coefs = fit[0] res2 = fit[1][0] #sum of squared residuals self.logger.info("coeffs = {}".format(coefs)) self.logger.info("rms residual = {}".format(numpy.sqrt(res2 / len(dop)))) o = open("dop.txt", 'w') for i, d in zip(rhoi, dop): val = polyval(coefs, i) res = d - val o.write("{0} {1} {2} {3}\n".format(i, d, val, res)) dopfile = self.metadata['dop'] self.dopplerVals = { 'Near': polyval(coefs, 0) } #need this temporarily in this module self.logger.info( "UAVSAR_mlcStack.extractDoppler: self.dopplerVals = {}".format( self.dopplerVals)) self.logger.info( "UAVSAR_mlcStack.extractDoppler: prf = {}".format(prf)) #The doppler file values are in units rad/m. divide by 2*pi rad/cycle to convert #to cycle/m. Then multiply by velocity to get Hz and divide by prf for dimensionless #doppler coefficients dop_scale = self.velocity / 2.0 / math.pi coefs = [x * dop_scale for x in coefs] #Set the coefs in frame._dopplerVsPixel because that is where DefaultDopp looks for them self.frame._dopplerVsPixel = coefs return coefs @property def terrainHeight(self): #The peg point incorporates the actual terrainHeight return 0.0 @property def platformHeight(self): h = self.metadata['Global Average Altitude'] #Reduce the platform height by the terrain height because the #peg radius of curvature includes the terrain height h -= self.metadata['Global Average Terrain Height'] return h @property def platformStartingAzimuth(self): azimuth = self.frame.S0 return azimuth @property def startingRange(self): return self.metadata['Image Starting Slant Range'] @property def squintAngle(self): """ Update this to use the sphere rather than planar approximation. """ startingRange = self.startingRange h = self.platformHeight v = self.velocity prf = self.frame.getInstrument().getPulseRepetitionFrequency() wavelength = self.frame.getInstrument().getRadarWavelength() if h > startingRange: raise ValueError("Spacecraft Height too large (%s>%s)" % (h, startingRange)) sinTheta = math.sqrt(1 - (h / startingRange)**2) fd = self.dopplerVals['Near'] sinSquint = fd / (2.0 * v * sinTheta) * wavelength if sinSquint**2 > 1: raise ValueError( "Error in One or More of the Squint Calculation Values\n" + "Doppler Centroid: %s\nVelocity: %s\nWavelength: %s\n" % (fd, v, wavelength)) self.squint = math.degrees( math.atan2(sinSquint, math.sqrt(1 - sinSquint**2))) #squint is also required in the frame. self.frame.squintAngle = math.radians(self.squint) return self.squint @property def heightDt(self): """ Delta(height)/Delta(Time) from frame start-time to mid-time """ return 0.0 @property def velocity(self): v = self.metadata['Average Along Track Velocity'] platform = self.frame.getInstrument().getPlatform() elp = self.elp peg = self.peg scale = (elp.pegRadCur + self.platformHeight) / elp.pegRadCur ds_ground = self.frame.instrument.getAzimuthPixelSize() dt = 1.0 / self.frame.instrument.getPulseRepetitionFrequency() v1 = scale * ds_ground / dt return v1 @property def elp(self): if not self._elp: planet = Planet(pname="Earth") self._elp = planet.get_elp() return self._elp @property def peg(self): if not self._peg: peg = [ math.degrees(self.metadata['Peg Latitude']), math.degrees(self.metadata['Peg Longitude']), math.degrees(self.metadata['Peg Heading']) ] th = self.metadata['Global Average Terrain Height'] platform = self.frame.getInstrument().getPlatform() self.elp.setSCH(peg[0], peg[1], peg[2], th) rc = self.elp.pegRadCur from isceobj.Location.Peg import Peg self._peg = Peg(latitude=peg[0], longitude=peg[1], heading=peg[2], radiusOfCurvature=rc) self.logger.info( "UAVSAR_mlcStack: peg radius of curvature = {}".format( self.elp.pegRadCur)) self.logger.info("UAVSAR_mlcStack: terrain height = {}".format(th)) return self._peg
class Radarsat2(Component): """ A Class representing RadarSAT 2 data """ def __init__(self): Component.__init__(self) self.xml = None self.tiff = None self.output = None self.product = _Product() self.frame = Frame() self.frame.configure() self.descriptionOfVariables = {} self.dictionaryOfVariables = {'XML': ['self.xml','str','mandatory'], 'TIFF': ['self.tiff','str','mandatory'], 'OUTPUT': ['self.output','str','optional']} def getFrame(self): return self.frame def parse(self): try: fp = open(self.xml,'r') except IOError as strerr: print("IOError: %s" % strerr) return self._xml_root = ElementTree(file=fp).getroot() self.product.set_from_etnode(self._xml_root) self.populateMetadata() fp.close() def populateMetadata(self): """ Create metadata objects from the metadata files """ mission = self.product.sourceAttributes.satellite swath = self.product.sourceAttributes.radarParameters.beams frequency = self.product.sourceAttributes.radarParameters.radarCenterFrequency prf = self.product.sourceAttributes.radarParameters.prf rangePixelSize = self.product.imageAttributes.rasterAttributes.sampledPixelSpacing rangeSamplingRate = Const.c/(2*rangePixelSize) pulseLength = self.product.sourceAttributes.radarParameters.pulseLengths[0] pulseBandwidth = self.product.sourceAttributes.radarParameters.pulseBandwidths[0] polarization = self.product.sourceAttributes.radarParameters.polarizations lookSide = lookMap[self.product.sourceAttributes.radarParameters.antennaPointing.upper()] facility = self.product.imageGenerationParameters.generalProcessingInformation._processingFacility version = self.product.imageGenerationParameters.generalProcessingInformation.softwareVersion lines = self.product.imageAttributes.rasterAttributes.numberOfLines samples = self.product.imageAttributes.rasterAttributes.numberOfSamplesPerLine startingRange = self.product.imageGenerationParameters.slantRangeToGroundRange.slantRangeTimeToFirstRangeSample * (Const.c/2) incidenceAngle = (self.product.imageGenerationParameters.sarProcessingInformation.incidenceAngleNearRange + self.product.imageGenerationParameters.sarProcessingInformation.incidenceAngleFarRange)/2 lineFlip = (self.product.imageAttributes.rasterAttributes.lineTimeOrdering.upper() == 'DECREASING') if lineFlip: dataStopTime = self.product.imageGenerationParameters.sarProcessingInformation.zeroDopplerTimeFirstLine dataStartTime = self.product.imageGenerationParameters.sarProcessingInformation.zeroDopplerTimeLastLine else: dataStartTime = self.product.imageGenerationParameters.sarProcessingInformation.zeroDopplerTimeFirstLine dataStopTime = self.product.imageGenerationParameters.sarProcessingInformation.zeroDopplerTimeLastLine passDirection = self.product.sourceAttributes.orbitAndAttitude.orbitInformation.passDirection height = self.product.imageGenerationParameters.sarProcessingInformation._satelliteHeight ####Populate platform platform = self.frame.getInstrument().getPlatform() platform.setPlanet(Planet("Earth")) platform.setMission(mission) platform.setPointingDirection(lookSide) platform.setAntennaLength(15.0) ####Populate instrument instrument = self.frame.getInstrument() instrument.setRadarFrequency(frequency) instrument.setPulseRepetitionFrequency(prf) instrument.setPulseLength(pulseLength) instrument.setChirpSlope(pulseBandwidth/pulseLength) instrument.setIncidenceAngle(incidenceAngle) #self.frame.getInstrument().setRangeBias(0) instrument.setRangePixelSize(rangePixelSize) instrument.setRangeSamplingRate(rangeSamplingRate) instrument.setBeamNumber(swath) instrument.setPulseLength(pulseLength) #Populate Frame #self.frame.setSatelliteHeight(height) self.frame.setSensingStart(dataStartTime) self.frame.setSensingStop(dataStopTime) diffTime = DTUtil.timeDeltaToSeconds(dataStopTime - dataStartTime)/2.0 sensingMid = dataStartTime + datetime.timedelta(microseconds=int(diffTime*1e6)) self.frame.setSensingMid(sensingMid) self.frame.setPassDirection(passDirection) self.frame.setPolarization(polarization) self.frame.setStartingRange(startingRange) self.frame.setFarRange(startingRange + (samples-1)*rangePixelSize) self.frame.setNumberOfLines(lines) self.frame.setNumberOfSamples(samples) self.frame.setProcessingFacility(facility) self.frame.setProcessingSoftwareVersion(version) # Initialize orbit objects # Read into temp orbit first. # Radarsat 2 needs orbit extensions. tempOrbit = Orbit() self.frame.getOrbit().setOrbitSource('Header: ' + self.product.sourceAttributes.orbitAndAttitude.orbitInformation.orbitDataFile) self.frame.setPassDirection(passDirection) stateVectors = self.product.sourceAttributes.orbitAndAttitude.orbitInformation.stateVectors for i in range(len(stateVectors)): position = [stateVectors[i].xPosition, stateVectors[i].yPosition, stateVectors[i].zPosition] velocity = [stateVectors[i].xVelocity, stateVectors[i].yVelocity, stateVectors[i].zVelocity] vec = StateVector() vec.setTime(stateVectors[i].timeStamp) vec.setPosition(position) vec.setVelocity(velocity) tempOrbit.addStateVector(vec) planet = self.frame.instrument.platform.planet orbExt = OrbitExtender(planet=planet) orbExt.configure() newOrb = orbExt.extendOrbit(tempOrbit) for sv in newOrb: self.frame.getOrbit().addStateVector(sv) def extractImage(self, verbose=True): ''' Use gdal to extract the slc. ''' try: from osgeo import gdal except ImportError: raise Exception('GDAL python bindings not found. Need this for RSAT2 / TandemX / Sentinel1A.') self.parse() width = self.frame.getNumberOfSamples() lgth = self.frame.getNumberOfLines() lineFlip = (self.product.imageAttributes.rasterAttributes.lineTimeOrdering.upper() == 'DECREASING') pixFlip = (self.product.imageAttributes.rasterAttributes.pixelTimeOrdering.upper() == 'DECREASING') src = gdal.Open(self.tiff.strip(), gdal.GA_ReadOnly) cJ = np.complex64(1.0j) ####Images are small enough that we can do it all in one go - Piyush real = src.GetRasterBand(1).ReadAsArray(0,0,width,lgth) imag = src.GetRasterBand(2).ReadAsArray(0,0,width,lgth) if (real is None) or (imag is None): raise Exception('Input Radarsat2 SLC seems to not be a 2 band Int16 image.') data = real+cJ*imag real = None imag = None src = None if lineFlip: if verbose: print('Vertically Flipping data') data = np.flipud(data) if pixFlip: if verbose: print('Horizontally Flipping data') data = np.fliplr(data) data.tofile(self.output) #### slcImage = isceobj.createSlcImage() slcImage.setByteOrder('l') slcImage.setFilename(self.output) slcImage.setAccessMode('read') slcImage.setWidth(width) slcImage.setLength(lgth) slcImage.setXmin(0) slcImage.setXmax(width) # slcImage.renderHdr() self.frame.setImage(slcImage) def extractDoppler(self): ''' self.parse() Extract doppler information as needed by mocomp ''' ins = self.frame.getInstrument() dc = self.product.imageGenerationParameters.dopplerCentroid quadratic = {} r0 = self.frame.startingRange fs = ins.getRangeSamplingRate() tNear = 2*r0/Const.c tMid = tNear + 0.5*self.frame.getNumberOfSamples()/fs t0 = dc.dopplerCentroidReferenceTime poly = dc.dopplerCentroidCoefficients fd_mid = 0.0 for kk in range(len(poly)): fd_mid += poly[kk] * (tMid - t0)**kk quadratic['a'] = fd_mid / ins.getPulseRepetitionFrequency() quadratic['b'] = 0. quadratic['c'] = 0. return quadratic
class Sentinel1(Sensor): """ A Class representing Sentinel1 StripMap data """ family = 's1sm' logging = 'isce.sensor.S1_SM' parameter_list = ( XML, TIFF, MANIFEST, SAFE, ORBIT_FILE, ORBIT_DIR, POLARIZATION, ) + Sensor.parameter_list def __init__(self, family='', name=''): super(Sentinel1, self).__init__(family if family else self.__class__.family, name=name) self.frame = Frame() self.frame.configure() self._xml_root = None def validateUserInputs(self): ''' Validate inputs from user. Populate tiff and xml from SAFE folder name. ''' import fnmatch import zipfile if not self.xml: if not self.safe: raise Exception('SAFE directory is not provided') ####First find annotation file ####Dont need swath number when driving with xml and tiff file if not self.xml: swathid = 's1?-s?-slc-{}'.format(self.polarization) dirname = self.safe if not self.xml: match = None if dirname.endswith('.zip'): pattern = os.path.join('*SAFE', 'annotation', swathid) + '*.xml' zf = zipfile.ZipFile(dirname, 'r') match = fnmatch.filter(zf.namelist(), pattern) zf.close() if (len(match) == 0): raise Exception( 'No annotation xml file found in zip file: {0}'.format( dirname)) ####Add /vsizip at the start to make it a zip file self.xml = '/vsizip/' + os.path.join(dirname, match[0]) else: pattern = os.path.join('annotation', swathid) + '*.xml' match = glob.glob(os.path.join(dirname, pattern)) if (len(match) == 0): raise Exception( 'No annotation xml file found in {0}'.format(dirname)) self.xml = match[0] if not self.xml: raise Exception('No annotation files found') print('Input XML file: ', self.xml) ####Find TIFF file if (not self.tiff) and (self.safe): match = None if dirname.endswith('.zip'): pattern = os.path.join('*SAFE', 'measurement', swathid) + '*.tiff' zf = zipfile.ZipFile(dirname, 'r') match = fnmatch.filter(zf.namelist(), pattern) zf.close() if (len(match) == 0): raise Exception( 'No tiff file found in zip file: {0}'.format(dirname)) ####Add /vsizip at the start to make it a zip file self.tiff = '/vsizip/' + os.path.join(dirname, match[0]) else: pattern = os.path.join('measurement', swathid) + '*.tiff' match = glob.glob(os.path.join(dirname, pattern)) if len(match) == 0: raise Exception( 'No tiff file found in directory: {0}'.format(dirname)) self.tiff = match[0] print('Input TIFF files: ', self.tiff) ####Find manifest files if self.safe: if dirname.endswith('.zip'): pattern = '*SAFE/manifest.safe' zf = zipfile.ZipFile(dirname, 'r') match = fnmatch.filter(zf.namelist(), pattern) zf.close() self.manifest = '/vsizip/' + os.path.join(dirname, match[0]) else: self.manifest = os.path.join(dirname, 'manifest.safe') print('Manifest files: ', self.manifest) return def getFrame(self): return self.frame def parse(self): ''' Actual parsing of the metadata for the product. ''' from isceobj.Sensor.TOPS.Sentinel1 import s1_findOrbitFile ###Check user inputs self.validateUserInputs() if self.xml.startswith('/vsizip'): import zipfile parts = self.xml.split(os.path.sep) if parts[2] == '': parts[2] = os.path.sep zipname = os.path.join(*(parts[2:-3])) fname = os.path.join(*(parts[-3:])) zf = zipfile.ZipFile(zipname, 'r') xmlstr = zf.read(fname) zf.close() else: with open(self.xml, 'r') as fid: xmlstr = fid.read() self._xml_root = ET.fromstring(xmlstr) self.populateMetadata() if self.manifest: self.populateIPFVersion() else: self.frame.setProcessingFacility('ESA') self.frame.setProcessingSoftwareVersion('IPFx.xx') if not self.orbitFile: if self.orbitDir: self.orbitFile = s1_findOrbitFile( self.orbitDir, self.frame.sensingStart, self.frame.sensingStop, mission=self.frame.getInstrument().getPlatform( ).getMission()) if self.orbitFile: orb = self.extractPreciseOrbit() self.frame.orbit.setOrbitSource(os.path.basename(self.orbitFile)) else: orb = self.extractOrbitFromAnnotation() self.frame.orbit.setOrbitSource('Annotation') for sv in orb: self.frame.orbit.addStateVector(sv) def grab_from_xml(self, path): try: res = self._xml_root.find(path).text except: raise Exception('Tag= %s not found' % (path)) if res is None: raise Exception('Tag = %s not found' % (path)) return res def convertToDateTime(self, string): dt = datetime.datetime.strptime(string, "%Y-%m-%dT%H:%M:%S.%f") return dt def populateMetadata(self): """ Create metadata objects from the metadata files """ ####Set each parameter one - by - one mission = self.grab_from_xml('adsHeader/missionId') swath = self.grab_from_xml('adsHeader/swath') polarization = self.grab_from_xml('adsHeader/polarisation') frequency = float( self.grab_from_xml( 'generalAnnotation/productInformation/radarFrequency')) passDirection = self.grab_from_xml( 'generalAnnotation/productInformation/pass') rangePixelSize = float( self.grab_from_xml( 'imageAnnotation/imageInformation/rangePixelSpacing')) azimuthPixelSize = float( self.grab_from_xml( 'imageAnnotation/imageInformation/azimuthPixelSpacing')) rangeSamplingRate = Const.c / (2.0 * rangePixelSize) prf = 1.0 / float( self.grab_from_xml( 'imageAnnotation/imageInformation/azimuthTimeInterval')) lines = int( self.grab_from_xml( 'imageAnnotation/imageInformation/numberOfLines')) samples = int( self.grab_from_xml( 'imageAnnotation/imageInformation/numberOfSamples')) startingRange = float( self.grab_from_xml( 'imageAnnotation/imageInformation/slantRangeTime') ) * Const.c / 2.0 incidenceAngle = float( self.grab_from_xml( 'imageAnnotation/imageInformation/incidenceAngleMidSwath')) dataStartTime = self.convertToDateTime( self.grab_from_xml( 'imageAnnotation/imageInformation/productFirstLineUtcTime')) dataStopTime = self.convertToDateTime( self.grab_from_xml( 'imageAnnotation/imageInformation/productLastLineUtcTime')) pulseLength = float( self.grab_from_xml( 'generalAnnotation/downlinkInformationList/downlinkInformation/downlinkValues/txPulseLength' )) chirpSlope = float( self.grab_from_xml( 'generalAnnotation/downlinkInformationList/downlinkInformation/downlinkValues/txPulseRampRate' )) pulseBandwidth = pulseLength * chirpSlope ####Sentinel is always right looking lookSide = -1 # height = self.product.imageGenerationParameters.sarProcessingInformation._satelliteHeight ####Populate platform platform = self.frame.getInstrument().getPlatform() platform.setPlanet(Planet(pname="Earth")) platform.setMission(mission) platform.setPointingDirection(lookSide) platform.setAntennaLength(2 * azimuthPixelSize) ####Populate instrument instrument = self.frame.getInstrument() instrument.setRadarFrequency(frequency) instrument.setPulseRepetitionFrequency(prf) instrument.setPulseLength(pulseLength) instrument.setChirpSlope(pulseBandwidth / pulseLength) instrument.setIncidenceAngle(incidenceAngle) #self.frame.getInstrument().setRangeBias(0) instrument.setRangePixelSize(rangePixelSize) instrument.setRangeSamplingRate(rangeSamplingRate) instrument.setBeamNumber(swath) instrument.setPulseLength(pulseLength) #Populate Frame #self.frame.setSatelliteHeight(height) self.frame.setSensingStart(dataStartTime) self.frame.setSensingStop(dataStopTime) diffTime = DTUtil.timeDeltaToSeconds(dataStopTime - dataStartTime) / 2.0 sensingMid = dataStartTime + datetime.timedelta( microseconds=int(diffTime * 1e6)) self.frame.setSensingMid(sensingMid) self.frame.setPassDirection(passDirection) self.frame.setPolarization(polarization) self.frame.setStartingRange(startingRange) self.frame.setFarRange(startingRange + (samples - 1) * rangePixelSize) self.frame.setNumberOfLines(lines) self.frame.setNumberOfSamples(samples) self.frame.setPassDirection(passDirection) def extractOrbitFromAnnotation(self): ''' Extract orbit information from xml node. ''' node = self._xml_root.find('generalAnnotation/orbitList') frameOrbit = Orbit() frameOrbit.setOrbitSource('Header') for child in node: timestamp = self.convertToDateTime(child.find('time').text) pos = [] vel = [] posnode = child.find('position') velnode = child.find('velocity') for tag in ['x', 'y', 'z']: pos.append(float(posnode.find(tag).text)) for tag in ['x', 'y', 'z']: vel.append(float(velnode.find(tag).text)) vec = StateVector() vec.setTime(timestamp) vec.setPosition(pos) vec.setVelocity(vel) frameOrbit.addStateVector(vec) planet = self.frame.instrument.platform.planet orbExt = OrbitExtender(planet=planet) orbExt.configure() newOrb = orbExt.extendOrbit(frameOrbit) return newOrb def extractPreciseOrbit(self): ''' Extract precise orbit from given Orbit file. ''' try: fp = open(self.orbitFile, 'r') except IOError as strerr: print("IOError: %s" % strerr) return _xml_root = ET.ElementTree(file=fp).getroot() node = _xml_root.find('Data_Block/List_of_OSVs') orb = Orbit() orb.configure() margin = datetime.timedelta(seconds=40.0) tstart = self.frame.getSensingStart() - margin tend = self.frame.getSensingStop() + margin for child in node: timestamp = self.convertToDateTime(child.find('UTC').text[4:]) if (timestamp >= tstart) and (timestamp < tend): pos = [] vel = [] for tag in ['VX', 'VY', 'VZ']: vel.append(float(child.find(tag).text)) for tag in ['X', 'Y', 'Z']: pos.append(float(child.find(tag).text)) vec = StateVector() vec.setTime(timestamp) vec.setPosition(pos) vec.setVelocity(vel) orb.addStateVector(vec) fp.close() return orb def extractImage(self): """ Use gdal python bindings to extract image """ try: from osgeo import gdal except ImportError: raise Exception( 'GDAL python bindings not found. Need this for RSAT2/ TandemX / Sentinel1A.' ) self.parse() width = self.frame.getNumberOfSamples() lgth = self.frame.getNumberOfLines() src = gdal.Open(self.tiff.strip(), gdal.GA_ReadOnly) band = src.GetRasterBand(1) fid = open(self.output, 'wb') for ii in range(lgth): data = band.ReadAsArray(0, ii, width, 1) data.tofile(fid) fid.close() src = None band = None #### slcImage = isceobj.createSlcImage() slcImage.setByteOrder('l') slcImage.setFilename(self.output) slcImage.setAccessMode('read') slcImage.setWidth(self.frame.getNumberOfSamples()) slcImage.setLength(self.frame.getNumberOfLines()) slcImage.setXmin(0) slcImage.setXmax(self.frame.getNumberOfSamples()) self.frame.setImage(slcImage) def extractDoppler(self): ''' self.parse() Extract doppler information as needed by mocomp ''' from isceobj.Util import Poly1D node = self._xml_root.find('dopplerCentroid/dcEstimateList') tdiff = 1.0e9 dpoly = None for index, burst in enumerate(node): refTime = self.convertToDateTime(burst.find('azimuthTime').text) delta = abs((refTime - self.frame.sensingMid).total_seconds()) if delta < tdiff: tdiff = delta r0 = 0.5 * Const.c * float(burst.find('t0').text) coeffs = [ float(val) for val in burst.find('dataDcPolynomial').text.split() ] poly = Poly1D.Poly1D() poly.initPoly(order=len(coeffs) - 1) poly.setMean(r0) poly.setNorm(0.5 * Const.c) poly.setCoeffs(coeffs) dpoly = poly if dpoly is None: raise Exception( 'Could not extract Doppler information for S1 scene') ###Part for insarApp ###Should be removed in the future rmid = self.frame.startingRange + 0.5 * self.frame.getNumberOfSamples( ) * self.frame.getInstrument().getRangePixelSize() quadratic = {} quadratic['a'] = dpoly( rmid) / self.frame.getInstrument().getPulseRepetitionFrequency() quadratic['b'] = 0. quadratic['c'] = 0. ###Actual Doppler Polynomial for accurate processing ###Will be used in roiApp pix = np.linspace(0, self.frame.getNumberOfSamples(), num=dpoly._order + 2) rngs = self.frame.startingRange + pix * self.frame.getInstrument( ).getRangePixelSize() evals = dpoly(rngs) fit = np.polyfit(pix, evals, dpoly._order) self.frame._dopplerVsPixel = list(fit[::-1]) print('Doppler Fit : ', fit[::-1]) return quadratic def populateIPFVersion(self): ''' Get IPF version from the manifest file. ''' try: if self.manifest.startswith('/vsizip'): import zipfile parts = self.manifest.split(os.path.sep) if parts[2] == '': parts[2] = os.path.sep zipname = os.path.join(*(parts[2:-2])) fname = os.path.join(*(parts[-2:])) print('MANS: ', zipname, fname) zf = zipfile.ZipFile(zipname, 'r') xmlstr = zf.read(fname) else: with open(self.manifest, 'r') as fid: xmlstr = fid.read() ####Setup namespace nsp = "{http://www.esa.int/safe/sentinel-1.0}" root = ET.fromstring(xmlstr) elem = root.find('.//metadataObject[@ID="processing"]') rdict = elem.find('.//xmlData/' + nsp + 'processing/' + nsp + 'facility').attrib self.frame.setProcessingFacility(rdict['site'] + ', ' + rdict['country']) rdict = elem.find('.//xmlData/' + nsp + 'processing/' + nsp + 'facility/' + nsp + 'software').attrib self.frame.setProcessingSoftwareVersion(rdict['name'] + ' ' + rdict['version']) except: ###Not a critical error ... continuing print( 'Could not read version number successfully from manifest file: ', self.manifest) pass return