def extractOrbit(self): ''' Extract orbit information from xml node. ''' node = self._xml_root.find('generalAnnotation/orbitList') print('Extracting orbit from annotation XML file') frameOrbit = Orbit() frameOrbit.configure() 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) return frameOrbit
def extractOrbit(self): ''' Extract orbit information from xml node. ''' node = self._xml_root.find('generalAnnotation/orbitList') frameOrbit = Orbit() frameOrbit.configure() 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) print(vec) orbExt = OrbitExtender(planet=Planet(pname='Earth')) orbExt.configure() newOrb = orbExt.extendOrbit(frameOrbit) return newOrb
def get_orbit(): from isceobj.Orbit.Orbit import Orbit """Return orbit object.""" orb = Orbit() orb.configure() return orb
def getMergedOrbit(product): from isceobj.Orbit.Orbit import Orbit ###Create merged orbit orb = Orbit() orb.configure() #Add first orbit to begin with for sv in product.orbit: orb.addStateVector(sv) return orb
def trimOrbit(self, startTime, stopTime): """Trim the list of state vectors to encompass the time span [startTime:stopTime]""" newOrbit = Orbit() newOrbit.configure() newOrbit.setOrbitSource('ODR') newOrbit.setReferenceFrame('ECR') for sv in self._ephemeris: if ((sv.getTime() > startTime) and (sv.getTime() < stopTime)): newOrbit.addStateVector(sv) return newOrbit
def convert(self): ''' Convert ECI orbit to ECEF orbit. ''' ECROrbit = Orbit() ECROrbit.configure() for sv in self.orbit: svtime = sv.getTime() position = sv.getPosition() velocity = sv.getVelocity() ####Compute GMST from GAST - Eq 5.13 dtiff = (svtime - self.referenceEpoch).total_seconds() theta = self.referenceGAST + self.Omega * dtiff costh = np.cos(theta) sinth = np.sin(theta) ###Position transformation A = np.zeros((3, 3)) A[0, 0] = costh A[0, 1] = sinth A[1, 0] = -sinth A[1, 1] = costh A[2, 2] = 1 ###Velocity transformation Adot = np.zeros((3, 3)) Adot[0, 0] = -self.Omega * sinth Adot[0, 1] = self.Omega * costh Adot[1, 0] = -self.Omega * costh Adot[1, 1] = -self.Omega * sinth ###Compute ECR state vector newPos = np.dot(A, position) newVel = np.dot(Adot, position) + np.dot(A, velocity) ####Create state vector object newsv = StateVector() newsv.setTime(svtime) newsv.setPosition(newPos.tolist()) newsv.setVelocity(newVel.tolist()) ###Append to orbit ECROrbit.addStateVector(newsv) ECROrbit.setOrbitSource('Sidereal angle conversion') ECROrbit.setOrbitQuality(self.orbit.getOrbitQuality()) return ECROrbit
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 getOrbitFromXML(self): ''' Populate orbit. ''' orb = Orbit() orb.configure() for node in self._xml_root.find('platform/orbit'): if node.tag == 'stateVec': sv = StateVector() sv.configure() for z in node: if z.tag == 'timeUTC': timeStamp = self.convertToDateTime2(z.text) elif z.tag == 'posX': xPosition = float(z.text) elif z.tag == 'posY': yPosition = float(z.text) elif z.tag == 'posZ': zPosition = float(z.text) elif z.tag == 'velX': xVelocity = float(z.text) elif z.tag == 'velY': yVelocity = float(z.text) elif z.tag == 'velZ': zVelocity = float(z.text) sv.setTime(timeStamp) sv.setPosition([xPosition, yPosition, zPosition]) sv.setVelocity([xVelocity, yVelocity, zVelocity]) orb.addStateVector(sv) print('sv=',sv) orbExt = OrbitExtender(planet=Planet(pname='Earth')) orbExt.configure() newOrb = orbExt.extendOrbit(orb) return newOrb self.product.orbit.setOrbitSource('Header') for sv in newOrb: self.product.orbit.addStateVector(sv)
def extractPreciseOrbit(sentinel1, margin=60.0): ''' Extract precise orbit from given Orbit file. ''' try: try: fp = open(sentinel1.orbitFile, 'r') except IOError as strerr: print("IOError: %s" % strerr) traceback.print_exc() return False _xml_root = ET.ElementTree(file=fp).getroot() node = _xml_root.find('Data_Block/List_of_OSVs') print('Extracting orbit from Orbit File: ', sentinel1.orbitFile) orb = Orbit() orb.configure() margin = datetime.timedelta(seconds=margin) print("sentinel1.product.bursts : %s" % sentinel1.product.bursts) tstart = sentinel1.product.bursts[0].sensingStart - margin tend = sentinel1.product.bursts[-1].sensingStop + margin for child in node.getchildren(): timestamp = sentinel1.convertToDateTime(child.find('UTC').text[4:]) if (timestamp >= tstart) and (timestamp < tend): ###Warn if state vector quality is not nominal quality = child.find('Quality').text.strip() if quality != 'NOMINAL': print( 'WARNING: State Vector at time {0} tagged as {1} in orbit file {2}' .format(timestamp, quality, sentinel1.orbitFile)) print("Excluding the date data") return False except Exception as err: print("extractPreciseOrbit Error : %s" % str(err)) traceback.print_exc() return False return True
def getOrbitFromXML(self): ''' Populate orbit. ''' orb = Orbit() orb.configure() for node in self._xml_root.find( 'sourceAttributes/orbitAndAttitude/orbitInformation'): if node.tag == 'stateVector': sv = StateVector() sv.configure() for z in node.getchildren(): if z.tag == 'timeStamp': timeStamp = self.convertToDateTime(z.text) elif z.tag == 'xPosition': xPosition = float(z.text) elif z.tag == 'yPosition': yPosition = float(z.text) elif z.tag == 'zPosition': zPosition = float(z.text) elif z.tag == 'xVelocity': xVelocity = float(z.text) elif z.tag == 'yVelocity': yVelocity = float(z.text) elif z.tag == 'zVelocity': zVelocity = float(z.text) sv.setTime(timeStamp) sv.setPosition([xPosition, yPosition, zPosition]) sv.setVelocity([xVelocity, yVelocity, zVelocity]) orb.addStateVector(sv) orbExt = OrbitExtender(planet=Planet(pname='Earth')) orbExt.configure() newOrb = orbExt.extendOrbit(orb) return newOrb self.product.orbit.setOrbitSource('Header') for sv in newOrb: self.product.orbit.addStateVector(sv)
def getMergedOrbit(product): import isce from isceobj.Orbit.Orbit import Orbit ###Create merged orbit orb = Orbit() orb.configure() burst = product[0].bursts[0] #Add first burst orbit to begin with for sv in burst.orbit: orb.addStateVector(sv) for pp in product: ##Add all state vectors for bb in pp.bursts: for sv in bb.orbit: if (sv.time < orb.minTime) or (sv.time > orb.maxTime): orb.addStateVector(sv) return orb
print('*********************') schOrigOrbit = copy.copy(orbSch.orbit) del orbSch print('Original WGS84 vectors to SCH') print('Number of state vectors: %d'%len(schOrigOrbit._stateVectors)) print('Time interval: %s %s'%(str(schOrigOrbit._minTime), str(schOrigOrbit._maxTime))) print(str(schOrigOrbit._stateVectors[0])) ####Line-by-line interpolation of SCH orbits ####Using SCH orbits as inputs pulseOrbit = Orbit() pulseOrbit.configure() #######Loop over and compare against interpolated SCH for svOld in xyzOrbit._stateVectors: ####Get time from Line-by-Line WGS84 ####And interpolate SCH orbit at those epochs ####SCH intepolation using simple linear interpolation ####WGS84 interpolation would use keyword method="hermite" svNew = schOrigOrbit.interpolate(svOld.getTime()) pulseOrbit.addStateVector(svNew) ####Clear some variables del xyzOrbit del origOrbit del schOrigOrbit
class PDS(object): def __init__(self, file=None): self.filename = file self.firstEpoch = 0 self.lastEpoch = 0 self.orbit = Orbit() self.orbit.configure() self.orbit.setOrbitSource('PDS') def getOrbit(self): return self.orbit def parse(self): fp = open(self.filename, 'r') for line in fp.readlines(): if (line[0].isdigit()): self.__parseStateVectorLine(line) else: self.__parseRecordLine(line) fp.close() def __parseRecordLine(self, line): line = line.strip() if (line.startswith('START_TIME')): values = line.split('=') values[1] = values[1].strip('"') dateTime = values[1].split() self.firstEpoch = self.__parseDateTimeString( dateTime[0], dateTime[1]) elif (line.startswith('STOP_TIME')): values = line.split('=') values[1] = values[1].strip('"') dateTime = values[1].split() self.lastEpoch = self.__parseDateTimeString( dateTime[0], dateTime[1]) elif (line.startswith('LEAP_UTC')): pass elif (line.startswith('LEAP_SIGN')): pass elif (line.startswith('RECORD_SIZE')): pass elif (line.startswith('NUM_REC')): pass def __parseStateVectorLine(self, line): date = line[0:11] time = line[12:27] x = float(line[44:56]) y = float(line[57:69]) z = float(line[70:82]) vx = float(line[83:95]) vy = float(line[96:108]) vz = float(line[109:121]) dt = self.__parseDateTimeString(date, time) sv = StateVector() sv.configure() sv.setTime(dt) sv.setPosition([x, y, z]) sv.setVelocity([vx, vy, vz]) self.orbit.addStateVector(sv) def __parseDateTimeString(self, date, time): """ Fix idiosyncrasies in the date and time strings """ time = time.replace( '-', '0' ) # For some reason, there are occasionally - signs where there should be zeros dt = datetime.datetime.strptime(date + ' ' + time, '%d-%b-%Y %H:%M:%S.%f') return dt
class Formslc(Component): family = 'formslc' logging_name = 'isce.formslc' dont_pickle_me = () parameter_list = (NUMBER_GOOD_BYTES, NUMBER_BYTES_PER_LINE, FIRST_LINE, NUMBER_VALID_PULSES, FIRST_SAMPLE, NUMBER_PATCHES, START_RANGE_BIN, NUMBER_RANGE_BIN, NUMBER_AZIMUTH_LOOKS, RANGE_CHIRP_EXTENSION_POINTS, AZIMUTH_PATCH_SIZE, OVERLAP, RAN_FFTOV, RAN_FFTIQ, DEBUG_FLAG, CALTONE_LOCATION, PLANET_LOCAL_RADIUS, BODY_FIXED_VELOCITY, SPACECRAFT_HEIGHT, PRF, INPHASE_VALUE, QUADRATURE_VALUE, AZIMUTH_RESOLUTION, RANGE_SAMPLING_RATE, CHIRP_SLOPE, RANGE_PULSE_DURATION, RADAR_WAVELENGTH, RANGE_FIRST_SAMPLE, RANGE_SPECTRAL_WEIGHTING, SPECTRAL_SHIFT_FRACTION, IQ_FLIP, DESKEW_FLAG, SECONDARY_RANGE_MIGRATION_FLAG, POSITION, TIME, DOPPLER_CENTROID_COEFFICIENTS, MOCOMP_POSITION, MOCOMP_INDEX, STARTING_RANGE, SHIFT, ##KK,ML 2013-07-15 SENSING_START, SLC_SENSING_START, MOCOMP_RANGE, LOOK_SIDE ) facility_list = ( SLC_IMAGE, RAW_IMAGE, ORBIT, MOCOMP_ORBIT, ) ## maxAzPatchSize is defined in case the user specifies an unusually ## large number of valid pulses to save but no patch size on input. maxAzPatchSize = 32768 def formslc(self): for item in self.inputPorts: item() self.computeRangeParams() try: self.rawImage.setCaster('read','CFLOAT') self.rawImage.setExtraInfo() self.rawImage.createImage() self.rawAccessor = self.rawImage.getImagePointer() self.slcAccessor = self.slcImage.getImagePointer() except AttributeError: self.logger.error("Error in accessing image pointers") raise AttributeError self.computePatchParams() self.allocateArrays() self.setState() ###New changes cOrbit = self.inOrbit.exportToC() formslc.setOrbit_Py(cOrbit) formslc.setSensingStart_Py( DTU.seconds_since_midnight(self.sensingStart) ) ####Create an empty/dummy orbit of same length as input orbit mOrbit = copy.copy(self.inOrbit).exportToC() formslc.setMocompOrbit_Py(mOrbit) formslc.formslc_Py(self.rawAccessor, self.slcAccessor) ###Freeing Orbit combinedlibmodule.freeCOrbit(cOrbit) self.outOrbit = Orbit() self.outOrbit.configure() self.outOrbit.importFromC(mOrbit, datetime.datetime.combine(self.sensingStart.date(), datetime.time(0) ) ) combinedlibmodule.freeCOrbit(mOrbit) #the size of this vectors where unknown until the end of the run posSize = formslc.getMocompPositionSize_Py() self.dim1_mocompPosition = 2 self.dim2_mocompPosition = posSize self.dim1_mocompIndx = posSize self.getState() self.deallocateArrays() self.slcImage.finalizeImage() self.slcImage.renderHdr() return self.slcImage @staticmethod def nxPower(num): power=0 k=0 while power < num: k+=1 power=2**k return k def computeRangeParams(self): '''Ensure that the given range parameters are valid.''' from isceobj.Constants import SPEED_OF_LIGHT import isceobj chirpLength = int(self.rangeSamplingRate * self.rangePulseDuration) halfChirpLength = chirpLength // 2 #Add a half-chirp to the user requested extension. #To decrease the extension relative to the halfChirpLength #the user would have to set rangeCHirpExtensionPoints to a negative #value; however, the resulting value must be greater than 0. self.logger.info('Default near range chirp extension '+ '(half the chirp length): %d' % (halfChirpLength)) self.logger.info('Extra Chirp Extension requested: '+ '%d' % (self.rangeChirpExtensionPoints)) self.rangeChirpExtensionPoints = (self.rangeChirpExtensionPoints + halfChirpLength) if self.rangeChirpExtensionPoints >= 0: self.logger.info('Extending range line by '+ '%d pixels' % (self.rangeChirpExtensionPoints)) elif self.rangeChirpExtensionPoints < 0: raise ValueError('Range Chirp Extension cannot be negative.') #startRangeBin must be positive. #It is an index into the raw data range line if self.startRangeBin <= 0: raise ValueError('startRangeBin must be positive ') self.logger.info('Number of Range Bins: %d'%self.numberRangeBin) self.slcWidth = (self.numberRangeBin + self.rangeChirpExtensionPoints + halfChirpLength + self.startRangeBin - 1) delr = self.rangeSamplingRate #Will be set here and passed on to Fortran. - Piyush self.startingRange = (self.rangeFirstSample + (self.startRangeBin - 1 - self.rangeChirpExtensionPoints) * SPEED_OF_LIGHT*0.5/self.rangeSamplingRate) self.logger.info('Raw Starting Range: %f'%(self.rangeFirstSample)) self.logger.info('SLC Starting Range: %f'%(self.startingRange)) self.logger.info('SLC width: %f'%(self.slcWidth)) #Set width of the SLC image here . self.slcImage = isceobj.createSlcImage() self.logger.info('Debug fname : %s'%(self.rawImage.getFilename())) self.slcImage.setFilename( self.rawImage.getFilename().replace('.raw','.slc')) self.slcImage.setWidth(self.slcWidth) self.slcImage.setAccessMode('write') self.slcImage.createImage() ## set the patch size and number of valid pulses based on the computed ## synthetic aperture length def computePatchParams(self): from isceobj.Constants import SPEED_OF_LIGHT chunksize=1024 rawFileSize = self.rawImage.getLength() * self.rawImage.getWidth() linelength = int(self.rawImage.getXmax()) synthApertureSamps = ( self.radarWavelength* (self.startingRange + self.slcWidth*SPEED_OF_LIGHT*0.5/self.rangeSamplingRate)* self.prf/(self.antennaLength*self.bodyFixedVelocity)) nSAS = int((synthApertureSamps-1)/chunksize)+1 chunkedSAS = chunksize*nSAS nxP = self.nxPower(nSAS) azP = chunksize*2*(2**nxP) #Patchsize nV = azP-chunkedSAS #Numbervalid if self.azimuthPatchSize: if self.azimuthPatchSize != 2**self.nxPower(self.azimuthPatchSize): self.azimuthPatchSize = 2**self.nxPower(self.azimuthPatchSize) self.logger.info( "Patch size must equal power of 2. Resetting to %d" % self.azimuthPatchSize ) if self.azimuthPatchSize and self.numberValidPulses: if (self.azimuthPatchSize < self.numberValidPulses or self.azimuthPatchSize < chunkedSAS+chunksize): self.azimuthPatchSize = azP self.numberValidPulses = nV elif self.numberValidPulses > self.azimuthPatchSize-chunkedSAS: msg = ("Number of valid pulses specified is too large "+ "for full linear convolution. ") msg += ("Should be less than %d" % (self.azimuthPatchSize-chunkedSAS)) self.logger.info(msg) self.logger.info( "Continuing with specified value of %d" % self.numberValidPulses ) elif self.azimuthPatchSize and not self.numberValidPulses: if self.azimuthPatchSize < chunkedSAS+chunksize: self.azimuthPatchSize = azP self.numberValidPulses = nV else: self.numberValidPulses = self.azimuthPatchSize-chunkedSAS if self.numberValidPulses > self.azimuthPatchSize-chunkedSAS: msg = ("Number of valid pulses specified is too large "+ "for full linear convolution. ") msg += ("Should be less than %d" % (self.azimuthPatchSize-chunkedSAS)) self.logger.info(msg) self.logger.info( "Continuing with specified value of %d" % self.numberValidPulses ) elif not self.azimuthPatchSize and self.numberValidPulses: self.azimuthPatchSize=2**self.nxPower(self.numberValidPulses+ synthApertureSamps) if self.azimuthPatchSize > self.maxAzPatchSize: msg = ("%d is a rather large patch size. " % self.azimuthPatchSize) msg += ("Check that the number of valid pulses is in a "+ "reasonable range. Proceeding anyway...") self.logger.info(msg) elif not self.azimuthPatchSize and not self.numberValidPulses: self.azimuthPatchSize=azP self.numberValidPulses=nV overhead = self.azimuthPatchSize - self.numberValidPulses if not self.numberPatches: self.numberPatches = ( 1+int( (rawFileSize/float(linelength)-overhead)/ self.numberValidPulses ) ) def getState(self): self.mocompPosition = formslc.getMocompPosition_Py( self.dim1_mocompPosition, self.dim2_mocompPosition ) self.mocompIndx = formslc.getMocompIndex_Py(self.dim1_mocompIndx) self.startingRange = formslc.getStartingRange_Py() self.mocompRange = formslc.getMocompRange_Py() slcSensingStart = formslc.getSlcSensingStart_Py() self.slcSensingStart = datetime.datetime.combine( self.sensingStart.date(), datetime.time(0)) + datetime.timedelta(seconds=slcSensingStart) def setState(self): formslc.setStdWriter_Py(int(self.stdWriter)) formslc.setNumberGoodBytes_Py(int(self.numberGoodBytes)) formslc.setNumberBytesPerLine_Py(int(self.numberBytesPerLine)) formslc.setFirstLine_Py(int(self.firstLine)) formslc.setNumberValidPulses_Py(int(self.numberValidPulses)) formslc.setFirstSample_Py(int(self.firstSample)) formslc.setNumberPatches_Py(int(self.numberPatches)) formslc.setStartRangeBin_Py(int(self.startRangeBin)) formslc.setNumberRangeBin_Py(int(self.numberRangeBin)) formslc.setNumberAzimuthLooks_Py(int(self.numberAzimuthLooks)) formslc.setRangeChirpExtensionPoints_Py( int(self.rangeChirpExtensionPoints) ) formslc.setAzimuthPatchSize_Py(int(self.azimuthPatchSize)) formslc.setOverlap_Py(int(self.overlap)) formslc.setRanfftov_Py(int(self.ranfftov)) formslc.setRanfftiq_Py(int(self.ranfftiq)) formslc.setDebugFlag_Py(int(self.debugFlag)) formslc.setCaltoneLocation_Py(float(self.caltoneLocation)) formslc.setPlanetLocalRadius_Py(float(self.planetLocalRadius)) formslc.setBodyFixedVelocity_Py(float(self.bodyFixedVelocity)) formslc.setSpacecraftHeight_Py(float(self.spacecraftHeight)) formslc.setPRF_Py(float(self.prf)) formslc.setInPhaseValue_Py(float(self.inPhaseValue)) formslc.setQuadratureValue_Py(float(self.quadratureValue)) formslc.setAzimuthResolution_Py(float(self.azimuthResolution)) formslc.setRangeSamplingRate_Py(float(self.rangeSamplingRate)) formslc.setChirpSlope_Py(float(self.chirpSlope)) formslc.setRangePulseDuration_Py(float(self.rangePulseDuration)) formslc.setRadarWavelength_Py(float(self.radarWavelength)) formslc.setRangeFirstSample_Py(float(self.rangeFirstSample)) formslc.setRangeSpectralWeighting_Py( float(self.rangeSpectralWeighting)) formslc.setSpectralShiftFraction_Py(float(self.spectralShiftFraction)) formslc.setIMRC1_Py(int(self.imrc1Accessor)) formslc.setIMMocomp_Py(int(self.immocompAccessor)) formslc.setIMRCAS1_Py(int(self.imrcas1Accessor)) formslc.setIMRCRM1_Py(int(self.imrcrm1Accessor)) formslc.setTransDat_Py(int(self.transAccessor)) formslc.setIQFlip_Py(self.IQFlip) formslc.setDeskewFlag_Py(self.deskewFlag) formslc.setSecondaryRangeMigrationFlag_Py( self.secondaryRangeMigrationFlag ) formslc.setPosition_Py(self.position, self.dim1_position, self.dim2_position) formslc.setVelocity_Py(self.velocity, self.dim1_velocity, self.dim2_velocity) formslc.setTime_Py(self.time, self.dim1_time) formslc.setDopplerCentroidCoefficients_Py( self.dopplerCentroidCoefficients, self.dim1_dopplerCentroidCoefficients ) formslc.setPegPoint_Py(np.radians(self.pegLatitude), np.radians(self.pegLongitude), np.radians(self.pegHeading)) formslc.setPlanet_Py(self.spin, self.gm) formslc.setEllipsoid_Py(self.a, self.e2) formslc.setSlcWidth_Py(self.slcWidth) formslc.setStartingRange_Py(self.startingRange) formslc.setLookSide_Py(self.lookSide) formslc.setShift_Py(self.shift) ##KK,ML 2013-07-15 def getMocompPosition(self, index=None): return self.mocompPosition[index] if index else self.mocompPosition def getMocompIndex(self): return self.mocompIndx def getStartingRange(self): return self.startingRange def setRawImage(self, raw): self.rawImage = raw def setSlcImage(self, slc): self.slcImage = slc def setNumberGoodBytes(self, var): self.numberGoodBytes = int(var) def setNumberBytesPerLine(self, var): self.numberBytesPerLine = int(var) def setFirstLine(self, var): self.firstLine = int(var) def setLookSide(self, var): self.lookSide = int(var) @set_if_true def setNumberValidPulses(self, var): self.numberValidPulses = int(var) def setFirstSample(self, var): self.firstSample = int(var) @set_if_true def setNumberPatches(self,var): self.numberPatches = int(var) def setStartRangeBin(self, var): self.startRangeBin = int(var) def setStartingRange(self, var): self.startingRange = float(var) def setNumberRangeBin(self, var): self.numberRangeBin = int(var) def setNumberAzimuthLooks(self, var): self.numberAzimuthLooks = int(var) def setRangeChirpExtensionPoints(self, var): self.rangeChirpExtensionPoints = int(var) @set_if_true def setAzimuthPatchSize(self, var): self.azimuthPatchSize = int(var) def setOverlap(self, var): self.overlap = int(var) def setRanfftov(self, var): self.ranfftov = int(var) def setRanfftiq(self, var): self.ranfftiq = int(var) def setDebugFlag(self, var): self.debugFlag = int(var) def setCaltoneLocation(self, var): self.caltoneLocation = float(var) def setPlanetLocalRadius(self, var): self.planetLocalRadius = float(var) def setBodyFixedVelocity(self, var): self.bodyFixedVelocity = float(var) def setSpacecraftHeight(self, var): self.spacecraftHeight = float(var) def setPRF(self, var): self.prf = float(var) def setInPhaseValue(self, var): self.inPhaseValue = float(var) def setQuadratureValue(self, var): self.quadratureValue = float(var) def setAzimuthResolution(self, var): self.azimuthResolution = float(var) def setRangeSamplingRate(self, var): self.rangeSamplingRate = float(var) def setChirpSlope(self, var): self.chirpSlope = float(var) def setRangePulseDuration(self, var): self.rangePulseDuration = float(var) def setRadarWavelength(self, var): self.radarWavelength = float(var) def setRangeFirstSample(self, var): self.rangeFirstSample = float(var) def setRangeSpectralWeighting(self, var): self.rangeSpectralWeighting = float(var) def setSpectralShiftFraction(self, var): self.spectralShiftFraction = float(var) def setIQFlip(self, var): self.IQFlip = str(var) def setDeskewFlag(self, var): self.deskewFlag = str(var) def setSecondaryRangeMigrationFlag(self, var): self.secondaryRangeMigrationFlag = str(var) def setPosition(self, var): self.position = var def setVelocity(self, var): self.velocity = var def setTime(self, var): self.time = var def setSlcWidth(self, var): self.slcWidth = var def setDopplerCentroidCoefficients(self, var): self.dopplerCentroidCoefficients = var ##KK,ML 2013-0-15 def setShift(self, var): self.shift = var ##KK,ML def _testArraySize(self,*args): """Test for array dimesions that are zero or smaller""" for dimension in args: if (dimension <= 0): self.logger.error("Error, trying to allocate zero size array") raise ValueError def allocateArrays(self): # Set array sizes from their arrays try: self.dim1_position = len(self.position) self.dim2_position = len(self.position[0]) self.dim1_velocity = len(self.velocity) self.dim2_velocity = len(self.velocity[0]) self.dim1_time = len(self.time) self.dim1_dopplerCentroidCoefficients = len( self.dopplerCentroidCoefficients) except TypeError: self.logger.error("Some input arrays were not set") raise TypeError # Test that the arrays have a size greater than zero self._testArraySize(self.dim1_position,self.dim2_position) self._testArraySize(self.dim1_velocity,self.dim2_velocity) self._testArraySize(self.dim1_time) self._testArraySize(self.dim1_dopplerCentroidCoefficients) # Allocate the arrays formslc.allocate_sch_Py(self.dim1_position, self.dim2_position) formslc.allocate_vsch_Py(self.dim1_velocity, self.dim2_velocity) formslc.allocate_time_Py(self.dim1_time) formslc.allocate_dopplerCoefficients_Py( self.dim1_dopplerCentroidCoefficients) def deallocateArrays(self): formslc.deallocate_sch_Py() formslc.deallocate_vsch_Py() formslc.deallocate_time_Py() formslc.deallocate_dopplerCoefficients_Py() pass def addRawImage(self): image = self.inputPorts['rawImage'] if image: if isinstance(image, Image): self.rawImage = image self.numberBytesPerLine = 2*self.rawImage.getWidth() self.numberGoodBytes = 2*self.rawImage.getNumberGoodSamples() self.firstSample = self.rawImage.getXmin() else: self.logger.error( "Object %s must be an instance of Image" % image ) raise TypeError def addOrbit(self): orbit = self.inputPorts['orbit'] if orbit: try: time,position,velocity,offset = orbit._unpackOrbit() self.time = time self.position = position self.velocity = velocity except AttributeError: self.logger.error( "Object %s requires an _unpackOrbit() method" % orbit.__class__ ) raise AttributeError def addFrame(self): frame = self.inputPorts['frame'] if frame: try: self.rangeFirstSample = frame.getStartingRange() self.rangeLastSample = frame.getFarRange() instrument = frame.getInstrument() self.inPhaseValue = instrument.getInPhaseValue() self.quadratureValue = instrument.getQuadratureValue() self.rangeSamplingRate = instrument.getRangeSamplingRate() self.chirpSlope = instrument.getChirpSlope() self.rangePulseDuration = instrument.getPulseLength() self.radarWavelength = instrument.getRadarWavelength() self.prf = instrument.getPulseRepetitionFrequency() self.antennaLength = instrument.getPlatform().getAntennaLength() if self.azimuthResolution is None: self.azimuthResolution = self.antennaLength/2.0 self.numberRangeBin = frame.numberRangeBins self.inOrbit = frame.orbit self.sensingStart = frame.sensingStart except AttributeError as strerr: self.logger.error(strerr) raise AttributeError def addPlanet(self): planet = self.inputPorts['planet'] if planet: try: self.spin = planet.spin self.gm = planet.GM ellipsoid = planet.ellipsoid self.a = ellipsoid.a self.e2 = ellipsoid.e2 except AttributeError as strerr: self.logger.error(strerr) raise AttributeError def addPeg(self): peg = self.inputPorts['peg'] if peg: try: self.pegLatitude = peg.getLatitude() self.pegLongitude = peg.getLongitude() self.pegHeading = peg.getHeading() self.planetLocalRadius = peg.getRadiusOfCurvature() except AttributeError as strerr: self.logger.error(strerr) raise AttributeError def addDoppler(self): doppler = self.inputPorts['doppler'] if doppler: try: self.dopplerCentroidCoefficients = ( doppler.getDopplerCoefficients(inHz=True) ) for num in range(len(self.dopplerCentroidCoefficients)): self.dopplerCentroidCoefficients[num] /= self.prf self.dim1_dopplerCentroidCoefficients = len( self.dopplerCentroidCoefficients ) except AttributeError as strerr: self.logger.error(strerr) raise AttributeError ''' def _facilities(self): self.slcImage = self.facility('slcImage', public_name='slcImage', module='isceobj.Image', factory='createSlcImage', mandatory=True, doc='Single Look Complex Image object' ) self.rawImage = self.facility('rawImage', public_name='rawImage', module='isceobj.Image', factory='createRawIQImage', mandatory=True, doc='Raw Image object' ) ''' def createPorts(self): ## 2012/2/12: now using PortIterator.__setitem__ self.inputPorts['rawImage'] = self.addRawImage self.inputPorts['orbit'] = self.addOrbit self.inputPorts['frame'] = self.addFrame self.inputPorts['peg'] = self.addPeg self.inputPorts['planet'] = self.addPlanet self.inputPorts['doppler'] = self.addDoppler return None def adaptToRender(self): import copy # make a copy of the stateVectors to restore it after dumping self._times = [copy.copy(self.sensingStart),copy.copy(self.slcSensingStart)] self.sensingStart = self.sensingStart.strftime(self._fmt) self.slcSensingStart = self.slcSensingStart.strftime(self._fmt) def restoreAfterRendering(self): self.sensingStart = self._times[0] self.slcSensingStart = self._times[1] def initProperties(self,catalog): keys = ['SENSING_START','SLC_SENSING_START'] for k in keys: kl = k.lower() if kl in catalog: v = catalog[kl] attrname = getattr(globals()[k],'attrname') val = datetime.datetime.strptime(v,self._fmt) setattr(self,attrname,val) catalog.pop(kl) super().initProperties(catalog) def __init__(self, name=''): super(Formslc, self).__init__(self.__class__.family, name) self.configure() #Non-parameter defaults self.slcImage = None self.rawImage = None # Planet information # the code does not actually uses the ones set to -9999, ## but they are passed so they # need to be set self.a = -9999 self.e2 = -9999 self.spin = -9999 self.gm = -9999 # Peg Information self.pegLatitude = -9999#see comment above self.pegLongitude = -9999 self.pegHeading = -9999 # Orbit Information self.dim1_position = None self.dim2_position = None self.velocity = [] self.dim1_velocity = None self.dim2_velocity = None self.dim1_time = None # Doppler Information self.dim1_dopplerCentroidCoefficients = None # Accessors self.imrc1Accessor = 0 self.immocompAccessor = 0 self.imrcas1Accessor = 0 self.imrcrm1Accessor = 0 self.transAccessor = 0 self.rawAccessor = 0 self.slcAccessor = 0 self.slcWidth = 0 ####Short orbits self.inOrbit = None self.outOrbit = None self.sensingStart = None self.slcSensingStart = None ####For dumping and loading self._times = [] self._fmt = '%Y-%m-%dT%H:%M:%S.%f' return None
def get_orbit(): """Return orbit object.""" orb = Orbit() orb.configure() return orb
class MocompTSX(Component): def mocomptsx(self): for port in self.inputPorts: port() try: self.inAccessor = self.slcInImage.getImagePointer() except AttributeError: self.logger.error("Error in accessing image pointers") raise AttributeError("Error in accessing image pointers") if self.stdWriter is None: self.createStdWriter() self.createOutSlcImage() self.outAccessor = self.slcOutImage.getImagePointer() self.allocateArrays() self.setState() ###New changes cOrbit = self.inOrbit.exportToC() mocompTSX.setOrbit_Py(cOrbit) mocompTSX.setSensingStart_Py( DTU.seconds_since_midnight(self.sensingStart)) ####Create an empty/dummy orbit of same length as input orbit mOrbit = copy.copy(self.inOrbit).exportToC() mocompTSX.setMocompOrbit_Py(mOrbit) mocompTSX.mocompTSX_Py(self.inAccessor, self.outAccessor) ###Freeing Orbit combinedlibmodule.freeCOrbit(cOrbit) self.outOrbit = Orbit() self.outOrbit.configure() self.outOrbit.importFromC( mOrbit, datetime.datetime.combine(self.sensingStart.date(), datetime.time(0))) combinedlibmodule.freeCOrbit(mOrbit) self.mocompPositionSize = mocompTSX.getMocompPositionSize_Py() self.dim1_mocompPosition = 2 self.dim2_mocompPosition = self.mocompPositionSize self.dim1_mocompIndex = self.mocompPositionSize self.getState() self.deallocateArrays() self.slcOutImage.finalizeImage() self.slcOutImage.renderHdr() return self.slcOutImage def createStdWriter(self): from iscesys.StdOEL.StdOELPy import create_writer self._stdWriter = create_writer("log", "", True, "insar.log").set_file_tags( "mocompTSX", "log", "err", "out") return None ## TODO: use slcInImage's method to make new image. def createOutSlcImage(self): """ Create the output SCL image based on the input image information. If self.slcOutImageName is not set that the default is the input image name preceded by 'mocomp'. """ import isceobj self.slcOutImage = isceobj.createSlcImage() IU.copyAttributes(self.slcInImage, self.slcOutImage) if self.slcOutImageName: name = self.slcOutImageName else: name = self.slcInImage.getFilename().capitalize( ) + '.mocomp' #ML 2014-08-21 self.slcOutImage.setFilename(name) self.slcOutImage.setAccessMode('write') self.slcOutImage.createImage() return None def setState(self): mocompTSX.setStdWriter_Py(int(self.stdWriter)) mocompTSX.setNumberRangeBins_Py(int(self.numberRangeBins)) mocompTSX.setNumberAzLines_Py(int(self.numberAzLines)) mocompTSX.setDopplerCentroidCoefficients_Py( self.dopplerCentroidCoefficients, self.dim1_dopplerCentroidCoefficients) mocompTSX.setTime_Py(self.time, self.dim1_time) mocompTSX.setPosition_Py(self.position, self.dim1_position, self.dim2_position) mocompTSX.setPlanetLocalRadius_Py(float(self.planetLocalRadius)) mocompTSX.setBodyFixedVelocity_Py(float(self.bodyFixedVelocity)) mocompTSX.setSpacecraftHeight_Py(float(self.spacecraftHeight)) mocompTSX.setPRF_Py(float(self.prf)) mocompTSX.setRangeSamplingRate_Py(float(self.rangeSamplingRate)) mocompTSX.setRadarWavelength_Py(float(self.radarWavelength)) mocompTSX.setRangeFisrtSample_Py(float(self.rangeFirstSample)) mocompTSX.setLookSide_Py(int(self.lookSide)) #new stuff for estMocomporbit mocompTSX.setPlanet_Py(self.spin, self.gm) mocompTSX.setEllipsoid_Py(self.a, self.e2) mocompTSX.setPegPoint_Py(numpy.radians(self.pegLatitude), numpy.radians(self.pegLongitude), numpy.radians(self.pegHeading)) return None def setSlcInImage(self, img): self.slcInImage = img def setSlcOutImageName(self, name): self.slcOutImageName = name def setNumberRangeBins(self, var): self.numberRangeBins = int(var) return def setNumberAzLines(self, var): self.numberAzLines = int(var) return def setLookSide(self, var): self.lookSide = int(var) return def setDopplerCentroidCoefficients(self, var): self.dopplerCentroidCoefficients = var return def setTime(self, var): self.time = var return def setPosition(self, var): self.position = var return def setPlanetLocalRadius(self, var): self.planetLocalRadius = float(var) return def setBodyFixedVelocity(self, var): self.bodyFixedVelocity = float(var) return def setSpacecraftHeight(self, var): self.spacecraftHeight = float(var) return def setPRF(self, var): self.prf = float(var) return def setRangeSamplingRate(self, var): self.rangeSamplingRate = float(var) return def setRadarWavelength(self, var): self.radarWavelength = float(var) return def setRangeFisrtSample(self, var): self.rangeFirstSample = float(var) return def getState(self): self.mocompIndex = mocompTSX.getMocompIndex_Py(self.dim1_mocompIndex) self.mocompPosition = mocompTSX.getMocompPosition_Py( self.dim1_mocompPosition, self.dim2_mocompPosition) self.startingRange = mocompTSX.getStartingRange_Py() self.mocompRange = mocompTSX.getMocompRange_Py() slcSensingStart = mocompTSX.getSlcSensingStart_Py() self.slcSensingStart = datetime.datetime.combine( self.sensingStart.date(), datetime.time(0)) + datetime.timedelta(seconds=slcSensingStart) return None def getMocompIndex(self): return self.mocompIndex def getMocompPosition(self, index=None): return self.mocompPosition[index] if index else self.mocompPosition def getMocompPositionSize(self): return self.mocompPositionSize def getMocompImage(self): return self.slcOutImage def allocateArrays(self): if (self.dim1_dopplerCentroidCoefficients == None): self.dim1_dopplerCentroidCoefficients = len( self.dopplerCentroidCoefficients) if (not self.dim1_dopplerCentroidCoefficients): print("Error. Trying to allocate zero size array") raise Exception mocompTSX.allocate_dopplerCentroidCoefficients_Py( self.dim1_dopplerCentroidCoefficients) if (self.dim1_time == None): self.dim1_time = len(self.time) if (not self.dim1_time): print("Error. Trying to allocate zero size array") raise Exception mocompTSX.allocate_time_Py(self.dim1_time) if (self.dim1_position == None): self.dim1_position = len(self.position) self.dim2_position = len(self.position[0]) if (not self.dim1_position) or (not self.dim2_position): print("Error. Trying to allocate zero size array") raise Exception mocompTSX.allocate_sch_Py(self.dim1_position, self.dim2_position) return None def deallocateArrays(self): mocompTSX.deallocate_dopplerCentroidCoefficients_Py() mocompTSX.deallocate_time_Py() mocompTSX.deallocate_sch_Py() return None def addOrbit(self): orbit = self._inputPorts.getPort('orbit').getObject() if (orbit): try: (time, position, velocity, offset) = orbit._unpackOrbit() self.time = time self.position = position except AttributeError: self.logger.error( "Object %s requires an _unpackOrbit() method" % (orbit.__class__)) raise AttributeError def addDoppler(self): doppler = self._inputPorts.getPort('doppler').getObject() if (doppler): try: self.dopplerCentroidCoefficients = doppler.getDopplerCoefficients( inHz=False) self.dim1_dopplerCentroidCoefficients = len( self.dopplerCentroidCoefficients) except AttributeError as strerr: self.logger.error(strerr) raise AttributeError def addSlcInImage(self): image = self._inputPorts.getPort('slcInImage').getObject() #check only if it is an instance of Image which is the base class if (image): if (isinstance(image, Image)): self.slcInImage = image self.numberRangeBins = self.slcInImage.getWidth() self.numberAzLines = self.slcInImage.getLength() else: self.logger.error("Object %s must be an instance of Image" % (image)) def addFrame(self): frame = self._inputPorts.getPort('frame').getObject() if (frame): try: self.rangeFirstSample = frame.getStartingRange() instrument = frame.getInstrument() self.rangeSamplingRate = instrument.getRangeSamplingRate() self.radarWavelength = instrument.getRadarWavelength() self.prf = instrument.getPulseRepetitionFrequency() #new stuff for estMocompOrbit self.sensingStart = frame.sensingStart self.inOrbit = frame.orbit except AttributeError as strerr: self.logger.error(strerr) raise AttributeError def addPeg(self): peg = self._inputPorts.getPort('peg').getObject() if (peg): try: self.pegLatitude = peg.getLatitude() self.pegLongitude = peg.getLongitude() self.pegHeading = peg.getHeading() self.planetLocalRadius = peg.getRadiusOfCurvature() except AttributeError as strerr: self.logger.error(strerr) raise AttributeError pass return None def addPlanet(self): planet = self.inputPorts['planet'] if planet: try: self.spin = planet.spin self.gm = planet.GM ellipsoid = planet.ellipsoid self.a = ellipsoid.a self.e2 = ellipsoid.e2 except AttributeError as strerr: self.logger.error(strerr) raise AttributeError logging_name = 'isce.mocompTSX' def __init__(self): super(MocompTSX, self).__init__() self.inAccessor = None self.outAccessor = None self.numberRangeBins = None self.numberAzLines = None self.dopplerCentroidCoefficients = [] self.dim1_dopplerCentroidCoefficients = None self.time = [] self.dim1_time = None self.position = [] self.dim1_position = None self.dim2_position = None self.planetLocalRadius = None self.bodyFixedVelocity = None self.spacecraftHeight = None self.prf = None self.rangeSamplingRate = None self.radarWavelength = None self.rangeFirstSample = None self.startingRange = None self.mocompIndex = [] self.dim1_mocompIndex = None self.mocompPositionSize = None self.slcOutImageName = "" self.slcInImage = None self.slcOutImage = None self.lookSide = -1 #Right looking by default # self.logger = logging.getLogger('isce.mocompTSX') # self.createPorts() self.dictionaryOfVariables = { 'STD_WRITER': ['stdWriter', 'int', 'optional'], 'NUMBER_RANGE_BINS': ['numberRangeBins', 'int', 'optional'], 'NUMBER_AZ_LINES': ['numberAzLines', 'int', 'optional'], 'DOPPLER_CENTROID_COEFFICIENTS': ['dopplerCentroidCoefficients', 'float', 'mandatory'], 'TIME': ['time', 'float', 'mandatory'], 'POSITION': ['position', '', 'mandatory'], 'PLANET_LOCAL_RADIUS': ['planetLocalRadius', 'float', 'mandatory'], 'BODY_FIXED_VELOCITY': ['bodyFixedVelocity', 'float', 'mandatory'], 'SPACECRAFT_HEIGHT': ['spacecraftHeight', 'float', 'mandatory'], 'PRF': ['prf', 'float', 'mandatory'], 'RANGE_SAMPLING_RATE': ['rangeSamplingRate', 'float', 'mandatory'], 'RADAR_WAVELENGTH': ['radarWavelength', 'float', 'mandatory'], 'RANGE_FIRST_SAMPLE': ['rangeFirstSample', 'float', 'mandatory'] } self.dictionaryOfOutputVariables = { 'MOCOMP_INDEX': 'mocompIndex', 'MOCOMP_POSITION': 'mocompPosition', 'MOCOMP_POSITION_SIZE': 'mocompPositionSize' } self.descriptionOfVariables = {} self.mandatoryVariables = [] self.optionalVariables = [] self.initOptionalAndMandatoryLists() return None def createPorts(self): slcInImagePort = Port(name='slcInImage', method=self.addSlcInImage) pegPort = Port(name='peg', method=self.addPeg) framePort = Port(name='frame', method=self.addFrame) dopplerPort = Port(name='doppler', method=self.addDoppler) orbitPort = Port(name='orbit', method=self.addOrbit) planetPort = Port(name='planet', method=self.addPlanet) self._inputPorts.add(slcInImagePort) self._inputPorts.add(pegPort) self._inputPorts.add(dopplerPort) self._inputPorts.add(framePort) self._inputPorts.add(orbitPort) self._inputPorts.add(planetPort) return None
class PRC(object): """A class to parse orbit data from D-PAF""" logging_name = "isce.orbit.PRC.PRC" @logged def __init__(self, file=None): self.filename = file self.firstEpoch = 0 self.lastEpoch = 0 self.tdtOffset = 0 self.orbit = Orbit() self.orbit.configure() self.orbit.setOrbitQuality('Precise') self.orbit.setOrbitSource('PRC') return None def getOrbit(self): return self.orbit def parse(self): #People still seem to be using the old .Z format #Adding support for it - PSA if os.path.splitext(self.filename)[1] == '.Z': from subprocess import Popen, PIPE fp = Popen(["zcat", self.filename], stdout=PIPE).stdout else: fp = open(self.filename, 'r') data = fp.read() fp.close() numLines = int(len(data) / 130) for i in range(numLines): line = data[i * 130:(i + 1) * 130] self.__parseLine(line) def __parseLine(self, line): """Parse a line from a PRC orbit file""" referenceFrame = line[0:6].decode('utf-8') if (referenceFrame == 'STATE '): self.__parseStateLine(line) if (referenceFrame == 'STTERR'): self.__parseTerrestrialLine(line) def __parseTerrestrialLine(self, line): j2000Day = float(line[14:20]) / 10.0 + 0.5 tdt = float(line[20:31]) / 1e6 x = float(line[31:43]) / 1e3 y = float(line[43:55]) / 1e3 z = float(line[55:67]) / 1e3 vx = float(line[67:78]) / 1e6 vy = float(line[78:89]) / 1e6 vz = float(line[89:100]) / 1e6 quality = line[127] tdt = tdt - self.tdtOffset dt = self.__j2000ToDatetime(j2000Day, tdt) sv = StateVector() sv.configure() sv.setTime(dt) sv.setPosition([x, y, z]) sv.setVelocity([vx, vy, vz]) self.orbit.addStateVector(sv) def __parseStateLine(self, line): self.firstEpoch = self.__j2000ToDatetime(float(line[6:12]) / 10.0, 0.0) self.lastEpoch = self.__j2000ToDatetime(float(line[12:18]) / 10.0, 0.0) self.tdtOffset = float(line[47:52]) self.tdtOffset = self.tdtOffset / 1e3 def __j2000ToDatetime(self, j2000Day, tdt): """Convert the number of days since 1 Jan. 2000 to a datetime object""" j2000 = datetime.datetime(year=2000, month=1, day=1) dt = j2000 + datetime.timedelta(days=j2000Day, seconds=tdt) return dt pass
class ODR(object): """A class to parse Orbital Data Records (ODR) generated by Delft""" logging_name = 'isceobj.Orbit.ODR' @logged def __init__(self, file=None): self._file = file self._format = None self._satellite = None self._arcNumber = None self._cycleLength = None self._numberOfRecords = None self._version = None self._ephemeris = Orbit() self._ephemeris.configure() self._ephemeris.setOrbitSource('ODR') self._ephemeris.setReferenceFrame('ECR') self.grs80 = Ellipsoid.Ellipsoid( a=AstronomicalHandbook.PlanetsData.ellipsoid['Earth']['GRS-80'].a, e2=AstronomicalHandbook.PlanetsData.ellipsoid['Earth'] ['GRS-80'].e2) return None #jng added the start and stop time. The computation of the velocities seems pretty time comsuming, so limit the orbit data extraction only to startTime nad stopTime def parseHeader(self, startTime=None, stopTime=None): fp = None try: fp = open(self._file, 'rb') except IOError as strerr: self.logger.error(strerr) buffer = fp.read(16) # Header 1 (format, satellite, dataStartTimeSeconds) = struct.unpack('>4s8si', buffer) buffer = fp.read(16) # Header 2 (cycleLength, number, numberOfRecords, version) = struct.unpack('>4i', buffer) self._format = format.decode('utf-8') self._satellite = satellite.decode('utf-8') self._arcNumber = number self._cycleLength = cycleLength * 1e3 # In cycle length in days self._numberOfRecords = numberOfRecords self._version = version positions = [] for i in range(numberOfRecords): buffer = fp.read(16) if not startTime == None: position = self.parseDataRecords(buffer) if position['time'] < startTime: continue if not stopTime == None: position = self.parseDataRecords(buffer) if position['time'] > stopTime: continue positions.append(self.parseDataRecords(buffer)) self.createStateVectors(positions) fp.close() def parseDataRecords(self, buffer): """Parse the individual data records for this ODR file""" (timeSeconds, latitude, longitude, height) = struct.unpack('>4i', buffer) time = self._utcSecondsToDatetime(timeSeconds) if (self._format == '@ODR'): latitude = latitude * 1e-6 longitude = longitude * 1e-6 elif (self._format == 'xODR'): latitude = latitude * 1e-7 longitude = longitude * 1e-7 height = height * 1e-3 xyz = self._convertToXYZ(latitude, longitude, height) return ({'time': time, 'x': xyz[0], 'y': xyz[1], 'z': xyz[2]}) def createStateVectors(self, positions): """Calculate the satellite velocity from the position data and create StateVector objects""" for i in range(len(positions)): t0 = positions[i]['time'] x0 = positions[i]['x'] y0 = positions[i]['y'] z0 = positions[i]['z'] sv = StateVector() sv.configure() sv.setTime(t0) sv.setPosition([x0, y0, z0]) sv.setVelocity([0.0, 0.0, 0.0]) self._ephemeris.addStateVector(sv) self._calculateVelocities() def _calculateVelocities(self): ##PSA: Need enough state vectors before and after to make sure interpolation is reasonable ##Call to trimOrbit is always needed to get rid of padding state vectors for sv in self._ephemeris[5:-5]: t0 = sv.getTime() t1 = t0 + datetime.timedelta(seconds=-0.5) t2 = t0 + datetime.timedelta(seconds=0.5) try: sv1 = self._ephemeris.interpolateOrbit(t1, method='legendre') sv2 = self._ephemeris.interpolateOrbit(t2, method='legendre') except ValueError: continue if (not sv1) or (not sv2): continue v1 = sv1.getPosition() v2 = sv2.getPosition() vx = (v2[0] - v1[0]) vy = (v2[1] - v1[1]) vz = (v2[2] - v1[2]) sv.setVelocity([vx, vy, vz]) def trimOrbit(self, startTime, stopTime): """Trim the list of state vectors to encompass the time span [startTime:stopTime]""" newOrbit = Orbit() newOrbit.configure() newOrbit.setOrbitSource('ODR') newOrbit.setReferenceFrame('ECR') for sv in self._ephemeris: if ((sv.getTime() > startTime) and (sv.getTime() < stopTime)): newOrbit.addStateVector(sv) return newOrbit def getEphemeris(self): return self._ephemeris def _convertToXYZ(self, latitude, longitude, height): # The latitude, longitude and height are referenced to the center of mass of the satellite above the GRS80 ellipsoid xyz = self.grs80.llh_to_xyz([latitude, longitude, height]) return xyz def _utcSecondsToDatetime(self, seconds): """All of the ODR records are in UTC seconds from 1 Jan. 1985""" dataTime = datetime.datetime(year=1985, month=1, day=1) dataTime = dataTime + datetime.timedelta(seconds=seconds) return dataTime