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 computePeg(self): shortOrb = Orbit() for i in range(-10, 10): time = self.tMid + datetime.timedelta( seconds=(old_div(i, self.prf))) sv = self.orbVec.interpolateOrbit(time, method='hermite') shortOrb.addStateVector(sv) objPeg = stdproc.createGetpeg() objPeg.wireInputPort(name='planet', object=self.planet) objPeg.wireInputPort(name='Orbit', object=shortOrb) stdWriter = create_writer("log", "", True, filename="orbitInfo.log") stdWriter.setFileTag("getpeg", "log") stdWriter.setFileTag("getpeg", "err") stdWriter.setFileTag("getpeg", "log") objPeg.setStdWriter(stdWriter) objPeg.estimatePeg() self.peg = objPeg.getPeg() self.rds = objPeg.getPegRadiusOfCurvature() self.hgt = objPeg.getAverageHeight() return
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 run(frame, catalog=None, sceneid='NO_ID'): """ Interpolate orbit. """ logger.info("Pulse Timing: %s" % sceneid) numberOfLines = frame.getNumberOfLines() prf = frame.getInstrument().getPulseRepetitionFrequency() pri = 1.0 / prf startTime = frame.getSensingStart() orbit = frame.getOrbit() pulseOrbit = Orbit() startTimeUTC0 = ( startTime - datetime.datetime(startTime.year, startTime.month, startTime.day)) timeVec = [ pri * i + startTimeUTC0.seconds + 10**-6 * startTimeUTC0.microseconds for i in range(numberOfLines) ] if catalog is not None: catalog.addItem("timeVector", timeVec, "runPulseTiming.%s" % sceneid) for i in range(numberOfLines): dt = i * pri time = startTime + datetime.timedelta(seconds=dt) sv = orbit.interpolateOrbit(time, method='hermite') pulseOrbit.addStateVector(sv) shift = timeVec[0] * prf return pulseOrbit, shift
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 readOrbit(self, platformPositionRecord): ''' reformat orbit from platformPositionRecord ''' orb=Orbit() orb.setOrbitSource('leaderfile') orb.setOrbitQuality(self.orbitElementsDesignator[platformPositionRecord.metadata['Orbital elements designator']]) t0 = datetime.datetime(year=platformPositionRecord.metadata['Year of data point'], month=platformPositionRecord.metadata['Month of data point'], day=platformPositionRecord.metadata['Day of data point']) t0 = t0 + datetime.timedelta(seconds=platformPositionRecord.metadata['Seconds of day']) #####Read in orbit in inertial coordinates deltaT = platformPositionRecord.metadata['Time interval between data points'] numPts = platformPositionRecord.metadata['Number of data points'] for i in range(numPts): vec = StateVector() t = t0 + datetime.timedelta(seconds=i*deltaT) vec.setTime(t) dataPoints = platformPositionRecord.metadata['Positional Data Points'][i] pos = [dataPoints['Position vector X'], dataPoints['Position vector Y'], dataPoints['Position vector Z']] vel = [dataPoints['Velocity vector X'], dataPoints['Velocity vector Y'], dataPoints['Velocity vector Z']] vec.setPosition(pos) vec.setVelocity(vel) orb.addStateVector(vec) return orb
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
class DOR(BaseEnvisatFile): """A class for parsing Envisat DORIS orbit files""" def __init__(self,fileName=None): BaseEnvisatFile.__init__(self) self.fileName = fileName self.fp = None self.orbit = Orbit() self.orbit.setOrbitSource('DORIS') self.orbit.setReferenceFrame('ECR') def parse(self): orbitDict = {} try: self.fp = open(self.fileName, 'rb') except IOError as errs: errno,strerr = errs print("IOError: %s" % strerr) return self.readMPH() self.readSPH() self.readStateVectors() self.fp.close() if (self.sph['dataSets'][0]['DS_NAME'] == 'DORIS PRELIMINARY ORBIT'): self.orbit.setOrbitQuality('Preliminary') elif (self.sph['dataSets'][0]['DS_NAME'] == 'DORIS PRECISE ORBIT'): self.orbit.setOrbitQuality('Precise') orbitDict.update(self.mph) orbitDict.update(self.sph) return orbitDict def readStateVectors(self): headerLength = self.mphLength + self.sphLength self.fp.seek(headerLength) for line in self.fp.readlines(): vals = line.decode('utf8').split() dateTime = self._parseDateTime(vals[0] + ' ' + vals[1]) position = list(map(float,vals[4:7])) velocity = list(map(float,vals[7:10])) sv = StateVector() sv.setTime(dateTime) sv.setPosition(position) sv.setVelocity(velocity) self.orbit.addStateVector(sv) def _parseDateTime(self,dtString): dateTime = datetime.datetime.strptime(dtString,'%d-%b-%Y %H:%M:%S.%f') return dateTime
def trimOrbit(self, startTime, stopTime): """Trim the list of state vectors to encompass the time span [startTime:stopTime]""" newOrbit = Orbit() 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 createOrbit(self): orbitAll = Orbit() for i in range(len(self._frames)): orbit = self._frames[i].getOrbit() #remember that everything is by reference, so the changes applied to orbitAll will be made to the Orbit #object in self.frame for sv in orbit._stateVectors: orbitAll.addStateVector(sv) # sort the orbit state vecotrs according to time orbitAll._stateVectors.sort(key=lambda sv: sv.time) self.removeDuplicateVectors(orbitAll._stateVectors) self._frame.setOrbit(orbitAll)
def 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 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
class Pulsetiming(Component): logging_name = "isce.stdproc.pulsetiming" def __init__(self): super(Pulsetiming, self).__init__() self.frame = None self.orbit = Orbit(source='Pulsetiming') return None def createPorts(self): framePort = Port(name='frame',method=self.addFrame) self._inputPorts.add(framePort) return None def getOrbit(self): return self.orbit def addFrame(self): frame = self.inputPorts['frame'] if frame: if isinstance(frame, Frame): self.frame = frame else: self.logger.error( "Object must be of type Frame, not %s" % (frame.__class__) ) raise TypeError pass return None # @port(Frame) # def addFrame(self): # return None def pulsetiming(self): self.activateInputPorts() numberOfLines = self.frame.getNumberOfLines() prf = self.frame.getInstrument().getPulseRepetitionFrequency() pri = 1.0/prf startTime = self.frame.getSensingStart() thisOrbit = self.frame.getOrbit() self.orbit.setReferenceFrame(thisOrbit.getReferenceFrame()) for i in range(numberOfLines): dt = i*pri time = startTime + datetime.timedelta(seconds=dt) sv = thisOrbit.interpolateOrbit(time,method='hermite') self.orbit.addStateVector(sv)
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 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 getPeg(self): shortOrb = Orbit() for i in range(-10, 10): time = self.dt + datetime.timedelta(seconds=(i / self.prf)) sv = self.orbit.interpolateOrbit(time, method='hermite') shortOrb.addStateVector(sv) objPeg = stdproc.createGetpeg() objPeg.wireInputPort(name='planet', object=self.planet) objPeg.wireInputPort(name='Orbit', object=shortOrb) stdWriter.setFileTag("getpeg", "log") stdWriter.setFileTag("getpeg", "err") stdWriter.setFileTag("getpeg", "out") objPeg.setStdWriter(stdWriter) objPeg.estimatePeg() self.peg = objPeg.getPeg() self.hgt = objPeg.getAverageHeight() self.rds = self.peg.getRadiusOfCurvature()
def loadHdrAsOrbit(fname, date=None): '''Read a hdr file and convert to ISCE orbit''' from isceobj.Orbit.Orbit import Orbit, StateVector if date is None: date = datetime.datetime.now().date() t0 = datetime.datetime(year=date.year, month=date.month, day=date.day) orb = Orbit() inData = np.loadtxt(fname) for line in inData: time = t0 + datetime.timedelta(seconds=line[0]) sv = StateVector() sv.setTime(time) sv.setPosition(line[1:4].tolist()) sv.setVelocity(line[4:7].tolist()) orb.addStateVector(sv) print(sv) return orb
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
def pulseTiming(frame, catalog, which): logger.info("Pulse Timing") numberOfLines = frame.getNumberOfLines() prf = frame.getInstrument().getPulseRepetitionFrequency() pri = 1.0 / prf startTime = frame.getSensingStart() orbit = frame.getOrbit() pulseOrbit = Orbit(name=which + 'orbit') startTimeUTC0 = ( startTime - datetime.datetime(startTime.year, startTime.month, startTime.day)) timeVec = [ pri * i + startTimeUTC0.seconds + 10**-6 * startTimeUTC0.microseconds for i in range(numberOfLines) ] catalog.addItem("timeVector", timeVec, "runPulseTiming.%s" % which) for i in range(numberOfLines): dt = i * pri time = startTime + datetime.timedelta(seconds=dt) sv = orbit.interpolateOrbit(time, method='hermite') pulseOrbit.addStateVector(sv) return pulseOrbit
def convert(self): '''Convert ECI orbit to ECEF orbit.''' date = self.orbit._stateVectors[0].getTime().date() bspName = 'inertial_orbit_' + date.strftime('%Y%m%d') + '.bsp' ####Convert ISCE orbit to SPICE orbit file sorb = ISCEOrbit(self.orbit) sorb.exportToSPK(bspName, frame=self.eci) ####Convert coordinates with corrections spk = SpiceOrbit(bspName) spk.initSpice() wgsOrbit = Orbit() wgsOrbit.setOrbitSource(self.orbit.getOrbitSource()) wgsOrbit.setOrbitQuality(self.orbit.getOrbitQuality()) for sv in self.orbit: tim = sv.getTime() spksv = spk.interpolateOrbit(tim, frame=self.ecef) wgsOrbit.addStateVector(spksv) return wgsOrbit
def pulseTiming(frame): #From runPulseTiming() in InsarProc numberOfLines = frame.getNumberOfLines() prf = frame.getInstrument().getPulseRepetitionFrequency() pri = 1.0 / prf startTime = frame.getSensingStart() orbit = frame.getOrbit() pulseOrbit = Orbit() startTimeUTC0 = ( startTime - datetime.datetime(startTime.year, startTime.month, startTime.day)) timeVec = [ pri * i + startTimeUTC0.seconds + 10**-6 * startTimeUTC0.microseconds for i in xrange(numberOfLines) ] for i in range(numberOfLines): dt = i * pri time = startTime + datetime.timedelta(seconds=dt) sv = orbit.interpolateOrbit(time, method='hermite') pulseOrbit.addStateVector(sv) return pulseOrbit
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']) except ZeroDivisionError: rangePixelSize = 0 print( 'Average terrain height: ', 1000 * self.leaderFile. sceneHeaderRecord.metadata['Average terrain height in km']) ins = self.frame.getInstrument() platform = ins.getPlatform() platform.setMission(self.leaderFile.sceneHeaderRecord. metadata['Sensor platform mission identifier']) platform.setAntennaLength(self.constants['antennaLength']) platform.setPlanet(Planet(pname='Earth')) ins.setRadarWavelength( self.leaderFile.sceneHeaderRecord.metadata['Radar wavelength']) ins.setIncidenceAngle(self.leaderFile.sceneHeaderRecord. metadata['Incidence angle at scene centre']) self.frame.getInstrument().setPulseRepetitionFrequency( self.leaderFile.sceneHeaderRecord. metadata['Pulse Repetition Frequency']) ins.setRangePixelSize(rangePixelSize) ins.setRangeSamplingRate( self.leaderFile.sceneHeaderRecord.metadata['Range sampling rate']) ins.setPulseLength( self.leaderFile.sceneHeaderRecord.metadata['Range pulse length']) chirpPulseBandwidth = self.leaderFile.processingRecord.metadata[ 'Pulse bandwidth code'] * 1e4 ins.setChirpSlope( chirpPulseBandwidth / self.leaderFile.sceneHeaderRecord.metadata['Range pulse length']) ins.setInPhaseValue(0.0) ins.setQuadratureValue(0.0) self.lineDirection = self.leaderFile.sceneHeaderRecord.metadata[ 'Time direction indicator along line direction'].strip() self.pixelDirection = self.leaderFile.sceneHeaderRecord.metadata[ 'Time direction indicator along pixel direction'].strip() ######RISAT-1 sensor orientation convention is opposite to ours lookSide = self.leaderFile.processingRecord.metadata[ 'Sensor orientation'] if lookSide == 'RIGHT': platform.setPointingDirection(1) elif lookSide == 'LEFT': platform.setPointingDirection(-1) else: raise Exception('Unknown look side') print('Leader file look side: ', lookSide) 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.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=2000 + 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() deltaT = self.leaderFile.platformPositionRecord.metadata[ 'Time interval between DATA points'] numPts = self.leaderFile.platformPositionRecord.metadata[ 'Number of data points'] for i in range(numPts): vec = StateVector() t = t0 + datetime.timedelta(seconds=i * deltaT) vec.setTime(t) dataPoints = self.leaderFile.platformPositionRecord.metadata[ 'Positional Data Points'][i] pos = [ dataPoints['Position vector X'], dataPoints['Position vector Y'], dataPoints['Position vector Z'] ] vel = [ dataPoints['Velocity vector X'], dataPoints['Velocity vector Y'], dataPoints['Velocity vector Z'] ] vec.setPosition(pos) vec.setVelocity(vel) orb.addStateVector(vec) #####Convert orbits from ECI to ECR frame t0 = orb._stateVectors[0]._time ang = self.leaderFile.platformPositionRecord.metadata[ 'Greenwich mean hour angle'] cOrb = ECI2ECR(orb, GAST=ang, epoch=t0) iOrb = cOrb.convert() #####Extend the orbits by a few points #####Expect large azimuth shifts - absolutely needed #####Since CEOS contains state vectors that barely covers scene extent planet = self.frame.instrument.platform.planet orbExt = OrbitExtender() orbExt.configure() orbExt._newPoints = 4 newOrb = orbExt.extendOrbit(iOrb) orb = self.frame.getOrbit() for sv in newOrb: orb.addStateVector(sv) self.doppler_coeff = [ self.leaderFile.sceneHeaderRecord. metadata['Cross track Doppler frequency centroid constant term'], self.leaderFile.sceneHeaderRecord. metadata['Cross track Doppler frequency centroid linear term'], self.leaderFile.sceneHeaderRecord. metadata['Cross track Doppler frequency centroid quadratic term'] ] self.azfmrate_coeff = [ self.leaderFile.sceneHeaderRecord. metadata['Cross track Doppler frequency rate constant term'], self.leaderFile.sceneHeaderRecord. metadata['Cross track Doppler frequency rate linear term'], self.leaderFile.sceneHeaderRecord. metadata['Cross track Doppler frequency rate quadratic term'] ]
class Orbit2sch(Component): parameter_list = (ORBIT_POSITION, ORBIT_VELOCITY, PLANET_GM, ELLIPSOID_MAJOR_SEMIAXIS, ELLIPSOID_ECCENTRICITY_SQUARED, COMPUTE_PEG_INFO_FLAG, PEG_LATITUDE, PEG_LONGITUDE, AVERAGE_HEIGHT, PEG_HEADING, SCH_GRAVITATIONAL_ACCELERATION, SCH_POSITION, SCH_VELOCITY) ## An imperative flag? REFACTOR. computePegInfoFlag = -1 #false by default planetGM = CN.EarthGM ellipsoidMajorSemiAxis = CN.EarthMajorSemiAxis ellipsoidEccentricitySquared = CN.EarthEccentricitySquared def __init__(self, averageHeight=None, planet=None, orbit=None, peg=None): super(Orbit2sch, self).__init__() self.averageHeight = averageHeight if planet is not None: self.wireInputPort(name='planet', object=planet) if orbit is not orbit: self.wireInputPort(name='orbit', object=orbit) if peg is not None: self.wireInputPort(name='peg', object=peg) self._time = None self._orbit = None self.dim1_orbitPosition = None self.dim2_orbitPosition = None self.dim1_orbitVelocity = None self.dim2_orbitVelocity = None self.dim1_position = None self.dim2_position = None self.dim1_velocity = None self.dim2_velocity = None self.dim1_acceleration = None self.dim2_acceleration = None self.logger = logging.getLogger('isce.orbit2sch') return def createPorts(self): # Create input ports orbitPort = Port(name='orbit', method=self.addOrbit) planetPort = Port(name='planet', method=self.addPlanet) pegPort = Port(name='peg', method=self.addPeg) # Add the ports self.inputPorts.add(orbitPort) self.inputPorts.add(planetPort) self.inputPorts.add(pegPort) return None def orbit2sch(self): for port in self.inputPorts: port() self.dim1_orbitPosition = len(self.orbitPosition) self.dim2_orbitPosition = len(self.orbitPosition[0]) self.dim1_orbitVelocity = len(self.orbitVelocity) self.dim2_orbitVelocity = len(self.orbitVelocity[0]) self.dim1_position = self.dim1_orbitPosition self.dim2_position = self.dim2_orbitPosition self.dim1_velocity = self.dim1_orbitVelocity self.dim2_velocity = self.dim2_orbitVelocity self.dim1_acceleration = self.dim1_orbitPosition self.dim2_acceleration = self.dim2_orbitPosition self.allocateArrays() self.setState() orbit2sch.orbit2sch_Py() self.getState() self.deallocateArrays() self._orbit = Orbit(source='SCH') # self._orbit.setOrbitSource('Orbit2SCH') self._orbit.setReferenceFrame('SCH') # for i in range(len(self.position)): sv = StateVector() sv.setTime(self._time[i]) sv.setPosition(self.position[i]) sv.setVelocity(self.velocity[i]) self._orbit.addStateVector(sv) return def setState(self): orbit2sch.setStdWriter_Py(int(self.stdWriter)) if self.computePegInfoFlag == -1: orbit2sch.setPegLatitude_Py(float(self.pegLatitude)) orbit2sch.setPegLongitude_Py(float(self.pegLongitude)) orbit2sch.setPegHeading_Py(float(self.pegHeading)) orbit2sch.setAverageHeight_Py(float(self.averageHeight)) orbit2sch.setOrbitPosition_Py(self.orbitPosition, self.dim1_orbitPosition, self.dim2_orbitPosition) orbit2sch.setOrbitVelocity_Py(self.orbitVelocity, self.dim1_orbitVelocity, self.dim2_orbitVelocity) orbit2sch.setPlanetGM_Py(float(self.planetGM)) orbit2sch.setEllipsoidMajorSemiAxis_Py( float(self.ellipsoidMajorSemiAxis)) orbit2sch.setEllipsoidEccentricitySquared_Py( float(self.ellipsoidEccentricitySquared)) orbit2sch.setComputePegInfoFlag_Py(int(self.computePegInfoFlag)) return None def setOrbitPosition(self, var): self.orbitPosition = var return def setOrbitVelocity(self, var): self.orbitVelocity = var return def setPlanetGM(self, var): self.planetGM = float(var) return def setEllipsoidMajorSemiAxis(self, var): self.ellipsoidMajorSemiAxis = float(var) return def setEllipsoidEccentricitySquared(self, var): self.ellipsoidEccentricitySquared = float(var) return def setComputePegInfoFlag(self, var): self.computePegInfoFlag = int(var) return def setPegLatitude(self, var): self.pegLatitude = float(var) return def setPegLongitude(self, var): self.pegLongitude = float(var) return def setPegHeading(self, var): self.pegHeading = float(var) return def setAverageHeight(self, var): self.averageHeight = float(var) return def getState(self): self.position = orbit2sch.getSchPosition_Py(self.dim1_position, self.dim2_position) self.velocity = orbit2sch.getSchVelocity_Py(self.dim1_velocity, self.dim2_velocity) self.acceleration = orbit2sch.getSchGravitationalAcceleration_Py( self.dim1_acceleration, self.dim2_acceleration) return # def getStdWriter(self): # return self.position def getSchVelocity(self): return self.velocity def getSchGravitationalAcceleration(self): return self.acceleration def getOrbit(self): return self._orbit def allocateArrays(self): if self.dim1_orbitPosition is None: self.dim1_orbitPosition = len(self.orbitPosition) self.dim2_orbitPosition = len(self.orbitPosition[0]) if (not self.dim1_orbitPosition) or (not self.dim2_orbitPosition): raise ValueError("Error. Trying to allocate zero size array") orbit2sch.allocate_xyz_Py(self.dim1_orbitPosition, self.dim2_orbitPosition) if self.dim1_orbitVelocity is None: self.dim1_orbitVelocity = len(self.orbitVelocity) self.dim2_orbitVelocity = len(self.orbitVelocity[0]) if (not self.dim1_orbitVelocity) or (not self.dim2_orbitVelocity): raise ValueError("Error. Trying to allocate zero size array") orbit2sch.allocate_vxyz_Py(self.dim1_orbitVelocity, self.dim2_orbitVelocity) if self.dim1_position is None: self.dim1_position = len(self.position) self.dim2_position = len(self.position[0]) if (not self.dim1_position) or (not self.dim2_position): ("Error. Trying to allocate zero size array") raise Exception orbit2sch.allocate_sch_Py(self.dim1_position, self.dim2_position) if self.dim1_velocity is None: self.dim1_velocity = len(self.velocity) self.dim2_velocity = len(self.velocity[0]) if (not self.dim1_velocity) or (not self.dim2_velocity): print("Error. Trying to allocate zero size array") raise Exception orbit2sch.allocate_vsch_Py(self.dim1_velocity, self.dim2_velocity) if self.dim1_acceleration is None: self.dim1_acceleration = len(self.acceleration) self.dim2_acceleration = len(self.acceleration[0]) if (not self.dim1_acceleration) or (not self.dim2_acceleration): print("Error. Trying to allocate zero size array") raise Exception orbit2sch.allocate_asch_Py(self.dim1_acceleration, self.dim2_acceleration) return def deallocateArrays(self): orbit2sch.deallocate_xyz_Py() orbit2sch.deallocate_vxyz_Py() orbit2sch.deallocate_sch_Py() orbit2sch.deallocate_vsch_Py() orbit2sch.deallocate_asch_Py() return @property def orbit(self): return self._orbit @orbit.setter def orbit(self, orbit): self.orbit = orbit return None @property def time(self): return self._time @time.setter def time(self, time): self.time = time return None def addOrbit(self): orbit = self.inputPorts['orbit'] if orbit: try: time, self.orbitPosition, self.orbitVelocity, offset = orbit.to_tuple( ) self._time = [] for t in time: self._time.append(offset + datetime.timedelta(seconds=t)) except AttributeError: self.logger.error( "orbit port should look like an orbit, not: %s" % (orbit.__class__)) raise AttributeError pass return None def addPlanet(self): planet = self._inputPorts.getPort('planet').getObject() if (planet): try: self.planetGM = planet.get_GM() self.ellipsoidMajorSemiAxis = planet.get_elp().get_a() self.ellipsoidEccentricitySquared = planet.get_elp().get_e2() except AttributeError: self.logger.error( "Object %s requires get_GM(), get_elp().get_a() and get_elp().get_e2() methods" % (planet.__class__)) raise AttributeError def addPeg(self): peg = self._inputPorts.getPort('peg').getObject() if (peg): try: self.pegLatitude = math.radians(peg.getLatitude()) self.pegLongitude = math.radians(peg.getLongitude()) self.pegHeading = math.radians(peg.getHeading()) self.logger.debug("Peg Object: %s" % (str(peg))) except AttributeError: self.logger.error( "Object %s requires getLatitude(), getLongitude() and getHeading() methods" % (peg.__class__)) raise AttributeError pass pass pass
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
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
class OrbitInfo(object): '''Class for storing metadata about a SAR scene.''' def __init__(self, fm): '''Initialize with a FrameMetadata object''' self._lookDict = {'right': -1, 'left': 1} self.direction = fm.direction self.fd = fm.doppler self.tStart = fm.sensingStart self.tStop = fm.sensingStop self.lookSide = self._lookDict[fm.lookDirection] self.prf = fm.prf self.rng = fm.startingRange self.coherenceThreshold = 0.2 self.orbVec = None self.tMid = self.tStart + sum( [self.tStop - self.tStart, datetime.timedelta()], datetime.timedelta()) / 2 self.pos = None self.vel = None self.peg = None self.rds = None self.hgt = None self.clook = None self.slook = None self.baseline = { 'horz': fm.horizontalBaseline, 'vert': fm.verticalBaseline, 'total': 0 } self.coherence = None self.planet = Planet(pname='Earth') self.unpackOrbitVectors(fm.orbit) self.computePeg() self.computeLookAngle() def getBaseline(self): return self.baseline def getCoherence(self): return self.coherence def unpackOrbitVectors(self, orb): self.orbVec = Orbit(source='json', quality='good') self.orbVec._referenceFrame = 'WGS-84' relTims = orb[0] satPos = orb[1] satVel = orb[2] refTime = orb[3] for kk in range(len(satPos)): vecTime = refTime + datetime.timedelta(seconds=relTims[kk]) tempVec = StateVector(time=vecTime, position=satPos[kk], velocity=satVel[kk]) self.orbVec.addStateVector(tempVec) stateVec = self.orbVec.interpolateOrbit(self.tMid, 'hermite') self.pos = stateVec.getPosition() self.vel = stateVec.getVelocity() return def computeLookAngle(self): self.clook = (2 * self.hgt * self.rds + self.hgt**2 + self.rng**2) / (2 * self.rng * (self.rds + self.hgt)) self.slook = numpy.sqrt(1 - self.clook**2) # print('Estimated Look Angle: %3.2f degrees'%(np.arccos(self.clook)*180.0/np.pi)) return def computePeg(self): shortOrb = Orbit() for i in range(-10, 10): time = self.tMid + datetime.timedelta(seconds=(i / self.prf)) sv = self.orbVec.interpolateOrbit(time, method='hermite') shortOrb.addStateVector(sv) objPeg = stdproc.createGetpeg() objPeg.wireInputPort(name='planet', object=self.planet) objPeg.wireInputPort(name='Orbit', object=shortOrb) stdWriter = create_writer("log", "", True, filename="orbitInfo.log") stdWriter.setFileTag("getpeg", "log") stdWriter.setFileTag("getpeg", "err") stdWriter.setFileTag("getpeg", "log") objPeg.setStdWriter(stdWriter) objPeg.estimatePeg() self.peg = objPeg.getPeg() self.rds = objPeg.getPegRadiusOfCurvature() self.hgt = objPeg.getAverageHeight() return def computeBaseline(self, slave): ''' Compute baseline between current object and another orbit object. This is meant to be used during data ingest. ''' mpos = numpy.array(self.pos) mvel = numpy.array(self.vel) #######From the ROI-PAC scripts rvec = mpos / numpy.linalg.norm(mpos) crp = numpy.cross(rvec, mvel) / numpy.linalg.norm(mvel) crp = crp / numpy.linalg.norm(crp) vvec = numpy.cross(crp, rvec) mvel = numpy.linalg.norm(mvel) spos = numpy.array(slave.pos) svel = numpy.array(slave.vel) svel = numpy.linalg.norm(svel) dx = spos - mpos z_offset = slave.prf * numpy.dot(dx, vvec) / mvel slave_time = slave.tMid - datetime.timedelta(seconds=z_offset / slave.prf) ####Remove these checks to deal with scenes from same track but not exactly overlaid # if slave_time < slave.tStart: # raise Exception('Out of bounds. Try the previous frame in time.') # elif slave.tStop < slave_time: # raise Exception('Out of bounds. Try the next frame in time.') try: svector = slave.orbVec.interpolateOrbit(slave_time, method='hermite') except: raise Exception( 'Error in interpolating orbits. Possibly using non geo-located images.' ) spos = numpy.array(svector.getPosition()) svel = numpy.array(svector.getVelocity()) svel = numpy.linalg.norm(svel) dx = spos - mpos hb = numpy.dot(dx, crp) vb = numpy.dot(dx, rvec) csb = self.lookSide * hb * self.clook + vb * self.slook self.baseline = {'horz': hb, 'vert': vb, 'total': csb} def computeCoherence(self, slave, Bcrit=400., Tau=180.0, Doppler=0.4): ''' This is meant to be estimate the coherence. This is for estimating which pairs to process. I assume that baseline dict is already available in the json input. baseline dict is w.r.t master and slave baseline is already precomputed w.r.t master. Typically: process a pair if Rho > 0.3 ''' Bperp = numpy.abs( self.lookSide * (self.baseline['horz'] - slave.horizontalBaseline) * self.clook + (self.baseline['vert'] - slave.verticalBaseline) * self.slook) Btemp = numpy.abs(self.tStart.toordinal() - slave.sensingStart.toordinal()) * 1.0 Bdop = numpy.abs( (self.fd * self.prf - slave.doppler * slave.prf) / self.prf) geomRho = (1 - numpy.clip(Bperp / Bcrit, 0., 1.)) tempRho = numpy.exp(-1.0 * Btemp / Tau) dopRho = Bdop < Doppler self.coherence = geomRho * tempRho * dopRho def computeCoherenceNoRef(self, slave, Bcrit=400., Tau=180.0, Doppler=0.4): ''' This is meant to be estimate the coherence. This is for estimating which pairs to process. Ignores baseline values in json and computes baseline between given pair. Master is not involved. Typically: process a pair if Rho > 0.3 ''' self.computeBaseline(OrbitInfo(slave)) Bperp = numpy.abs(self.lookSide * self.baseline['horz'] * self.clook + self.baseline['vert'] * self.slook) Btemp = numpy.abs(self.tStart.toordinal() - slave.sensingStart.toordinal()) * 1.0 Bdop = numpy.abs( (self.fd * self.prf - slave.doppler * slave.prf) / self.prf) print(('Bperp: %f (m) , Btemp: %f days, Bdop: %f (frac PRF)' % (Bperp, Btemp, Bdop))) geomRho = (1 - numpy.clip(Bperp / Bcrit, 0., 1.)) tempRho = numpy.exp(-1.0 * Btemp / Tau) dopRho = Bdop < Doppler self.coherence = geomRho * tempRho * dopRho print(('Expected Coherence: %f' % (self.coherence))) def isCoherent(self, slave, Bcrit=400., Tau=180, Doppler=0.4, threshold=0.3): #### Change this line to self.computeCoherence to go back to original. self.computeCoherenceNoRef(slave, Bcrit, Tau, Doppler) ret = False if (self.coherence >= threshold): ret = True return ret
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.setOrbitSource('ODR') self._ephemeris.setReferenceFrame('ECR') self.grs80 = Ellipsoid.Ellipsoid( *AstronomicalHandbook.PlanetsData.ellipsoid['Earth']['GRS-80']) 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.setTime(t0) sv.setPosition([x0, y0, z0]) sv.setVelocity([0.0, 0.0, 0.0]) self._ephemeris.addStateVector(sv) self._calculateVelocities() def _calculateVelocities(self): for sv in self._ephemeris: 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.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
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
####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 #####We compare the two interpolation schemes ####Orig WGS84 -> Line-by-line WGS84 -> Line-by-line SCH ####Orig WGS84 -> Orig SCH -> Line-by-line SCH ###Get the orbit information into Arrays (told,xold,vold,relold) = schOrbit._unpackOrbit() (tnew,xnew,vnew,relnew) = pulseOrbit._unpackOrbit()