def runGeocodeOffset(self): '''geocode offset fied ''' if not self.doDenseOffset: return if not ((self._insar.modeCombination == 0) or (self._insar.modeCombination == 1)): return catalog = isceobj.Catalog.createCatalog(self._insar.procDoc.name) self.updateParamemetersFromUser() #use original track object to determine bbox if self.bbox == None: masterTrack = self._insar.loadTrack(master=True) bbox = getBboxGeo(masterTrack) else: bbox = self.bbox catalog.addItem('geocode bounding box', bbox, 'runGeocodeOffset') demFile = os.path.abspath(self._insar.demGeo) denseOffsetDir = 'dense_offset' if not os.path.exists(denseOffsetDir): os.makedirs(denseOffsetDir) os.chdir(denseOffsetDir) masterTrack = self._insar.loadProduct(self._insar.masterTrackParameter) #slaveTrack = self._insar.loadProduct(self._insar.slaveTrackParameter) ######################################################################################### #compute bounding box for geocoding #if self.bbox == None: # bbox = getBboxGeo(masterTrack) #else: # bbox = self.bbox #catalog.addItem('geocode bounding box', bbox, 'runGeocodeOffset') geocodeList = [self._insar.denseOffset, self._insar.denseOffsetSnr] if self.doOffsetFiltering: geocodeList.append(self._insar.denseOffsetFilt) for inputFile in geocodeList: interpMethod = 'nearest' geocode(masterTrack, demFile, inputFile, bbox, self.offsetSkipWidth, self.offsetSkipHeight, interpMethod, self._insar.offsetImageTopoffset, self._insar.offsetImageLeftoffset, addMultilookOffset=False) ######################################################################################### os.chdir('../') catalog.printToLog(logger, "runGeocodeOffset") self._insar.procDoc.addAllFromCatalog(catalog)
def runGeocode(self): '''geocode final products ''' if hasattr(self, 'doInSAR'): if not self.doInSAR: return catalog = isceobj.Catalog.createCatalog(self._insar.procDoc.name) self.updateParamemetersFromUser() referenceTrack = self._insar.loadTrack(reference=True) #secondaryTrack = self._insar.loadTrack(reference=False) demFile = os.path.abspath(self._insar.demGeo) insarDir = 'insar' os.makedirs(insarDir, exist_ok=True) os.chdir(insarDir) #compute bounding box for geocoding if self.bbox == None: bbox = getBboxGeo(referenceTrack) else: bbox = self.bbox catalog.addItem('geocode bounding box', bbox, 'runGeocode') if self.geocodeList == None: geocodeList = [self._insar.unwrappedInterferogram, self._insar.unwrappedMaskedInterferogram, self._insar.multilookCoherence, self._insar.multilookLos] if self.doIon: geocodeList.append(self._insar.multilookIon) else: geocodeList = [] for xxx in self.geocodeList: geocodeList += glob.glob(xxx) numberRangeLooks = self._insar.numberRangeLooks1 * self._insar.numberRangeLooks2 numberAzimuthLooks = self._insar.numberAzimuthLooks1 * self._insar.numberAzimuthLooks2 for inputFile in geocodeList: if self.geocodeInterpMethod == None: img = isceobj.createImage() img.load(inputFile + '.xml') if img.dataType.upper() == 'CFLOAT': interpMethod = 'sinc' else: interpMethod = 'bilinear' else: interpMethod = self.geocodeInterpMethod.lower() geocode(referenceTrack, demFile, inputFile, bbox, numberRangeLooks, numberAzimuthLooks, interpMethod, 0, 0) os.chdir('../') catalog.printToLog(logger, "runGeocode") self._insar.procDoc.addAllFromCatalog(catalog)
def runGeocodeSd(self): '''geocode final products ''' catalog = isceobj.Catalog.createCatalog(self._insar.procDoc.name) self.updateParamemetersFromUser() referenceTrack = self._insar.loadTrack(reference=True) #secondaryTrack = self._insar.loadTrack(reference=False) demFile = os.path.abspath(self._insar.demGeo) sdDir = 'sd' os.makedirs(sdDir, exist_ok=True) os.chdir(sdDir) if self.geocodeListSd == None: geocodeList = self._insar.multilookCoherenceSd + self._insar.azimuthDeformationSd + self._insar.maskedAzimuthDeformationSd else: geocodeList = [] for xxx in self.geocodeListSd: geocodeList += glob.glob(xxx) if self.bbox == None: bbox = getBboxGeo(referenceTrack) else: bbox = self.bbox catalog.addItem('geocode bounding box', bbox, 'runGeocodeSd') numberRangeLooks = self._insar.numberRangeLooks1 * self._insar.numberRangeLooksSd numberAzimuthLooks = self._insar.numberAzimuthLooks1 * self._insar.numberAzimuthLooksSd for inputFile in geocodeList: if self.geocodeInterpMethodSd == None: img = isceobj.createImage() img.load(inputFile + '.xml') if img.dataType.upper() == 'CFLOAT': interpMethod = 'sinc' else: interpMethod = 'bilinear' else: interpMethod = self.geocodeInterpMethodSd.lower() geocode(referenceTrack, demFile, inputFile, bbox, numberRangeLooks, numberAzimuthLooks, interpMethod, 0, 0) os.chdir('../') catalog.printToLog(logger, "runGeocodeSd") self._insar.procDoc.addAllFromCatalog(catalog)
def runPreprocessor(self): '''Extract images. ''' catalog = isceobj.Catalog.createCatalog(self._insar.procDoc.name) #find files #actually no need to use absolute path any longer, since we are able to find file from vrt now. 27-JAN-2020, CRL. #denseoffset may still need absolute path when making links self.masterDir = os.path.abspath(self.masterDir) self.slaveDir = os.path.abspath(self.slaveDir) ledFilesMaster = sorted(glob.glob(os.path.join(self.masterDir, 'LED-ALOS2*-*-*'))) imgFilesMaster = sorted(glob.glob(os.path.join(self.masterDir, 'IMG-{}-ALOS2*-*-*'.format(self.masterPolarization.upper())))) ledFilesSlave = sorted(glob.glob(os.path.join(self.slaveDir, 'LED-ALOS2*-*-*'))) imgFilesSlave = sorted(glob.glob(os.path.join(self.slaveDir, 'IMG-{}-ALOS2*-*-*'.format(self.slavePolarization.upper())))) firstFrameMaster = ledFilesMaster[0].split('-')[-3][-4:] firstFrameSlave = ledFilesSlave[0].split('-')[-3][-4:] firstFrameImagesMaster = sorted(glob.glob(os.path.join(self.masterDir, 'IMG-{}-ALOS2*{}-*-*'.format(self.masterPolarization.upper(), firstFrameMaster)))) firstFrameImagesSlave = sorted(glob.glob(os.path.join(self.slaveDir, 'IMG-{}-ALOS2*{}-*-*'.format(self.slavePolarization.upper(), firstFrameSlave)))) #determin operation mode masterMode = os.path.basename(ledFilesMaster[0]).split('-')[-1][0:3] slaveMode = os.path.basename(ledFilesSlave[0]).split('-')[-1][0:3] spotlightModes = ['SBS'] stripmapModes = ['UBS', 'UBD', 'HBS', 'HBD', 'HBQ', 'FBS', 'FBD', 'FBQ'] scansarNominalModes = ['WBS', 'WBD', 'WWS', 'WWD'] scansarWideModes = ['VBS', 'VBD'] scansarModes = ['WBS', 'WBD', 'WWS', 'WWD', 'VBS', 'VBD'] #usable combinations if (masterMode in spotlightModes) and (slaveMode in spotlightModes): self._insar.modeCombination = 0 elif (masterMode in stripmapModes) and (slaveMode in stripmapModes): self._insar.modeCombination = 1 elif (masterMode in scansarNominalModes) and (slaveMode in scansarNominalModes): self._insar.modeCombination = 21 elif (masterMode in scansarWideModes) and (slaveMode in scansarWideModes): self._insar.modeCombination = 22 elif (masterMode in scansarNominalModes) and (slaveMode in stripmapModes): self._insar.modeCombination = 31 elif (masterMode in scansarWideModes) and (slaveMode in stripmapModes): self._insar.modeCombination = 32 else: print('\n\nthis mode combination is not possible') print('note that for ScanSAR-stripmap, ScanSAR must be master\n\n') raise Exception('mode combination not supported') if self._insar.modeCombination != 21: print('\n\nburst processing only support {}\n\n'.format(scansarNominalModes)) raise Exception('mode combination not supported') #determine default number of looks: self._insar.numberRangeLooks1 = self.numberRangeLooks1 self._insar.numberAzimuthLooks1 = self.numberAzimuthLooks1 self._insar.numberRangeLooks2 = self.numberRangeLooks2 self._insar.numberAzimuthLooks2 = self.numberAzimuthLooks2 #the following two will be automatically determined by runRdrDemOffset.py self._insar.numberRangeLooksSim = self.numberRangeLooksSim self._insar.numberAzimuthLooksSim = self.numberAzimuthLooksSim self._insar.numberRangeLooksIon = self.numberRangeLooksIon self._insar.numberAzimuthLooksIon = self.numberAzimuthLooksIon self._insar.numberRangeLooksSd = self.numberRangeLooksSd self._insar.numberAzimuthLooksSd = self.numberAzimuthLooksSd #force number of looks 1 to 1 self.numberRangeLooks1 = 1 self.numberAzimuthLooks1 = 1 self._insar.numberRangeLooks1 = 1 self._insar.numberAzimuthLooks1 = 1 if self._insar.numberRangeLooks2 == None: self._insar.numberRangeLooks2 = 7 if self._insar.numberAzimuthLooks2 == None: self._insar.numberAzimuthLooks2 = 2 if self._insar.numberRangeLooksIon == None: self._insar.numberRangeLooksIon = 42 if self._insar.numberAzimuthLooksIon == None: self._insar.numberAzimuthLooksIon = 12 if self._insar.numberRangeLooksSd == None: self._insar.numberRangeLooksSd = 14 if self._insar.numberAzimuthLooksSd == None: self._insar.numberAzimuthLooksSd = 4 #define processing file names self._insar.masterDate = os.path.basename(ledFilesMaster[0]).split('-')[2] self._insar.slaveDate = os.path.basename(ledFilesSlave[0]).split('-')[2] self._insar.setFilename(masterDate=self._insar.masterDate, slaveDate=self._insar.slaveDate, nrlks1=self._insar.numberRangeLooks1, nalks1=self._insar.numberAzimuthLooks1, nrlks2=self._insar.numberRangeLooks2, nalks2=self._insar.numberAzimuthLooks2) self._insar.setFilenameSd(masterDate=self._insar.masterDate, slaveDate=self._insar.slaveDate, nrlks1=self._insar.numberRangeLooks1, nalks1=self._insar.numberAzimuthLooks1, nrlks_sd=self._insar.numberRangeLooksSd, nalks_sd=self._insar.numberAzimuthLooksSd, nsd=3) #find frame numbers if (self._insar.modeCombination == 31) or (self._insar.modeCombination == 32): if (self.masterFrames == None) or (self.slaveFrames == None): raise Exception('for ScanSAR-stripmap inteferometry, you must set master and slave frame numbers') #if not set, find frames automatically if self.masterFrames == None: self.masterFrames = [] for led in ledFilesMaster: frameNumber = os.path.basename(led).split('-')[1][-4:] if frameNumber not in self.masterFrames: self.masterFrames.append(frameNumber) if self.slaveFrames == None: self.slaveFrames = [] for led in ledFilesSlave: frameNumber = os.path.basename(led).split('-')[1][-4:] if frameNumber not in self.slaveFrames: self.slaveFrames.append(frameNumber) #sort frames self.masterFrames = sorted(self.masterFrames) self.slaveFrames = sorted(self.slaveFrames) #check number of frames if len(self.masterFrames) != len(self.slaveFrames): raise Exception('number of frames in master dir is not equal to number of frames \ in slave dir. please set frame number manually') #find swath numbers (if not ScanSAR-ScanSAR, compute valid swaths) if (self._insar.modeCombination == 0) or (self._insar.modeCombination == 1): self.startingSwath = 1 self.endingSwath = 1 if self._insar.modeCombination == 21: if self.startingSwath == None: self.startingSwath = 1 if self.endingSwath == None: self.endingSwath = 5 if self._insar.modeCombination == 22: if self.startingSwath == None: self.startingSwath = 1 if self.endingSwath == None: self.endingSwath = 7 #determine starting and ending swaths for ScanSAR-stripmap, user's settings are overwritten #use first frame to check overlap if (self._insar.modeCombination == 31) or (self._insar.modeCombination == 32): if self._insar.modeCombination == 31: numberOfSwaths = 5 else: numberOfSwaths = 7 overlapSubswaths = [] for i in range(numberOfSwaths): overlapRatio = check_overlap(ledFilesMaster[0], firstFrameImagesMaster[i], ledFilesSlave[0], firstFrameImagesSlave[0]) if overlapRatio > 1.0 / 4.0: overlapSubswaths.append(i+1) if overlapSubswaths == []: raise Exception('There is no overlap area between the ScanSAR-stripmap pair') self.startingSwath = int(overlapSubswaths[0]) self.endingSwath = int(overlapSubswaths[-1]) #save the valid frames and swaths for future processing self._insar.masterFrames = self.masterFrames self._insar.slaveFrames = self.slaveFrames self._insar.startingSwath = self.startingSwath self._insar.endingSwath = self.endingSwath ################################################## #1. create directories and read data ################################################## self.master.configure() self.slave.configure() self.master.track.configure() self.slave.track.configure() for i, (masterFrame, slaveFrame) in enumerate(zip(self._insar.masterFrames, self._insar.slaveFrames)): #frame number starts with 1 frameDir = 'f{}_{}'.format(i+1, masterFrame) if not os.path.exists(frameDir): os.makedirs(frameDir) os.chdir(frameDir) #attach a frame to master and slave frameObjMaster = MultiMode.createFrame() frameObjSlave = MultiMode.createFrame() frameObjMaster.configure() frameObjSlave.configure() self.master.track.frames.append(frameObjMaster) self.slave.track.frames.append(frameObjSlave) #swath number starts with 1 for j in range(self._insar.startingSwath, self._insar.endingSwath+1): print('processing frame {} swath {}'.format(masterFrame, j)) swathDir = 's{}'.format(j) if not os.path.exists(swathDir): os.makedirs(swathDir) os.chdir(swathDir) #attach a swath to master and slave swathObjMaster = MultiMode.createSwath() swathObjSlave = MultiMode.createSwath() swathObjMaster.configure() swathObjSlave.configure() self.master.track.frames[-1].swaths.append(swathObjMaster) self.slave.track.frames[-1].swaths.append(swathObjSlave) #setup master self.master.leaderFile = sorted(glob.glob(os.path.join(self.masterDir, 'LED-ALOS2*{}-*-*'.format(masterFrame))))[0] if masterMode in scansarModes: self.master.imageFile = sorted(glob.glob(os.path.join(self.masterDir, 'IMG-{}-ALOS2*{}-*-*-F{}'.format(self.masterPolarization.upper(), masterFrame, j))))[0] else: self.master.imageFile = sorted(glob.glob(os.path.join(self.masterDir, 'IMG-{}-ALOS2*{}-*-*'.format(self.masterPolarization.upper(), masterFrame))))[0] self.master.outputFile = self._insar.masterSlc self.master.useVirtualFile = self.useVirtualFile #read master (imageFDR, imageData)=self.master.readImage() (leaderFDR, sceneHeaderRecord, platformPositionRecord, facilityRecord)=self.master.readLeader() self.master.setSwath(leaderFDR, sceneHeaderRecord, platformPositionRecord, facilityRecord, imageFDR, imageData) self.master.setFrame(leaderFDR, sceneHeaderRecord, platformPositionRecord, facilityRecord, imageFDR, imageData) self.master.setTrack(leaderFDR, sceneHeaderRecord, platformPositionRecord, facilityRecord, imageFDR, imageData) #setup slave self.slave.leaderFile = sorted(glob.glob(os.path.join(self.slaveDir, 'LED-ALOS2*{}-*-*'.format(slaveFrame))))[0] if slaveMode in scansarModes: self.slave.imageFile = sorted(glob.glob(os.path.join(self.slaveDir, 'IMG-{}-ALOS2*{}-*-*-F{}'.format(self.slavePolarization.upper(), slaveFrame, j))))[0] else: self.slave.imageFile = sorted(glob.glob(os.path.join(self.slaveDir, 'IMG-{}-ALOS2*{}-*-*'.format(self.slavePolarization.upper(), slaveFrame))))[0] self.slave.outputFile = self._insar.slaveSlc self.slave.useVirtualFile = self.useVirtualFile #read slave (imageFDR, imageData)=self.slave.readImage() (leaderFDR, sceneHeaderRecord, platformPositionRecord, facilityRecord)=self.slave.readLeader() self.slave.setSwath(leaderFDR, sceneHeaderRecord, platformPositionRecord, facilityRecord, imageFDR, imageData) self.slave.setFrame(leaderFDR, sceneHeaderRecord, platformPositionRecord, facilityRecord, imageFDR, imageData) self.slave.setTrack(leaderFDR, sceneHeaderRecord, platformPositionRecord, facilityRecord, imageFDR, imageData) os.chdir('../') self._insar.saveProduct(self.master.track.frames[-1], self._insar.masterFrameParameter) self._insar.saveProduct(self.slave.track.frames[-1], self._insar.slaveFrameParameter) os.chdir('../') self._insar.saveProduct(self.master.track, self._insar.masterTrackParameter) self._insar.saveProduct(self.slave.track, self._insar.slaveTrackParameter) ################################################## #2. compute burst synchronization ################################################## #burst synchronization may slowly change along a track as a result of the changing relative speed of the two flights #in one frame, real unsynchronized time is the same for all swaths unsynTime = 0 #real synchronized time/percentage depends on the swath burst length (synTime = burstlength - abs(unsynTime)) #synTime = 0 synPercentage = 0 numberOfFrames = len(self._insar.masterFrames) numberOfSwaths = self._insar.endingSwath - self._insar.startingSwath + 1 for i, frameNumber in enumerate(self._insar.masterFrames): for j, swathNumber in enumerate(range(self._insar.startingSwath, self._insar.endingSwath + 1)): masterSwath = self.master.track.frames[i].swaths[j] slaveSwath = self.slave.track.frames[i].swaths[j] #using Piyush's code for computing range and azimuth offsets midRange = masterSwath.startingRange + masterSwath.rangePixelSize * masterSwath.numberOfSamples * 0.5 midSensingStart = masterSwath.sensingStart + datetime.timedelta(seconds = masterSwath.numberOfLines * 0.5 / masterSwath.prf) llh = self.master.track.orbit.rdr2geo(midSensingStart, midRange) slvaz, slvrng = self.slave.track.orbit.geo2rdr(llh) ###Translate to offsets #note that slave range pixel size and prf might be different from master, here we assume there is a virtual slave with same #range pixel size and prf rgoff = ((slvrng - slaveSwath.startingRange) / masterSwath.rangePixelSize) - masterSwath.numberOfSamples * 0.5 azoff = ((slvaz - slaveSwath.sensingStart).total_seconds() * masterSwath.prf) - masterSwath.numberOfLines * 0.5 #compute burst synchronization #burst parameters for ScanSAR wide mode not estimed yet if self._insar.modeCombination == 21: scburstStartLine = (masterSwath.burstStartTime - masterSwath.sensingStart).total_seconds() * masterSwath.prf + azoff #slave burst start times corresponding to master burst start times (100% synchronization) scburstStartLines = np.arange(scburstStartLine - 100000*masterSwath.burstCycleLength, \ scburstStartLine + 100000*masterSwath.burstCycleLength, \ masterSwath.burstCycleLength) dscburstStartLines = -((slaveSwath.burstStartTime - slaveSwath.sensingStart).total_seconds() * slaveSwath.prf - scburstStartLines) #find the difference with minimum absolute value unsynLines = dscburstStartLines[np.argmin(np.absolute(dscburstStartLines))] if np.absolute(unsynLines) >= slaveSwath.burstLength: synLines = 0 if unsynLines > 0: unsynLines = slaveSwath.burstLength else: unsynLines = -slaveSwath.burstLength else: synLines = slaveSwath.burstLength - np.absolute(unsynLines) unsynTime += unsynLines / masterSwath.prf synPercentage += synLines / masterSwath.burstLength * 100.0 catalog.addItem('burst synchronization of frame {} swath {}'.format(frameNumber, swathNumber), '%.1f%%'%(synLines / masterSwath.burstLength * 100.0), 'runPreprocessor') ############################################################################################ #illustration of the sign of the number of unsynchronized lines (unsynLines) #The convention is the same as ampcor offset, that is, # slaveLineNumber = masterLineNumber + unsynLines # # |-----------------------| ------------ # | | ^ # | | | # | | | unsynLines < 0 # | | | # | | \ / # | | |-----------------------| # | | | | # | | | | # |-----------------------| | | # Master Burst | | # | | # | | # | | # | | # |-----------------------| # Slave Burst # # ############################################################################################ ##burst parameters for ScanSAR wide mode not estimed yet elif self._insar.modeCombination == 31: #scansar is master scburstStartLine = (masterSwath.burstStartTime - masterSwath.sensingStart).total_seconds() * masterSwath.prf + azoff #slave burst start times corresponding to master burst start times (100% synchronization) for k in range(-100000, 100000): saz_burstx = scburstStartLine + masterSwath.burstCycleLength * k st_burstx = slaveSwath.sensingStart + datetime.timedelta(seconds=saz_burstx / masterSwath.prf) if saz_burstx >= 0.0 and saz_burstx <= slaveSwath.numberOfLines -1: slaveSwath.burstStartTime = st_burstx slaveSwath.burstLength = masterSwath.burstLength slaveSwath.burstCycleLength = masterSwath.burstCycleLength slaveSwath.swathNumber = masterSwath.swathNumber break #unsynLines = 0 #synLines = masterSwath.burstLength #unsynTime += unsynLines / masterSwath.prf #synPercentage += synLines / masterSwath.burstLength * 100.0 catalog.addItem('burst synchronization of frame {} swath {}'.format(frameNumber, swathNumber), '%.1f%%'%(100.0), 'runPreprocessor') else: pass #overwrite original frame parameter file if self._insar.modeCombination == 31: frameDir = 'f{}_{}'.format(i+1, frameNumber) self._insar.saveProduct(self.slave.track.frames[i], os.path.join(frameDir, self._insar.slaveFrameParameter)) #getting average if self._insar.modeCombination == 21: unsynTime /= numberOfFrames*numberOfSwaths synPercentage /= numberOfFrames*numberOfSwaths elif self._insar.modeCombination == 31: unsynTime = 0. synPercentage = 100. else: pass #record results if (self._insar.modeCombination == 21) or (self._insar.modeCombination == 31): self._insar.burstUnsynchronizedTime = unsynTime self._insar.burstSynchronization = synPercentage catalog.addItem('burst synchronization averaged', '%.1f%%'%(synPercentage), 'runPreprocessor') ################################################## #3. compute baseline ################################################## #only compute baseline at four corners and center of the master track bboxRdr = getBboxRdr(self.master.track) rangeMin = bboxRdr[0] rangeMax = bboxRdr[1] azimuthTimeMin = bboxRdr[2] azimuthTimeMax = bboxRdr[3] azimuthTimeMid = azimuthTimeMin+datetime.timedelta(seconds=(azimuthTimeMax-azimuthTimeMin).total_seconds()/2.0) rangeMid = (rangeMin + rangeMax) / 2.0 points = [[azimuthTimeMin, rangeMin], [azimuthTimeMin, rangeMax], [azimuthTimeMax, rangeMin], [azimuthTimeMax, rangeMax], [azimuthTimeMid, rangeMid]] Bpar = [] Bperp = [] #modify Piyush's code for computing baslines refElp = Planet(pname='Earth').ellipsoid for x in points: masterSV = self.master.track.orbit.interpolate(x[0], method='hermite') target = self.master.track.orbit.rdr2geo(x[0], x[1]) slvTime, slvrng = self.slave.track.orbit.geo2rdr(target) slaveSV = self.slave.track.orbit.interpolateOrbit(slvTime, method='hermite') targxyz = np.array(refElp.LLH(target[0], target[1], target[2]).ecef().tolist()) mxyz = np.array(masterSV.getPosition()) mvel = np.array(masterSV.getVelocity()) sxyz = np.array(slaveSV.getPosition()) aa = np.linalg.norm(sxyz-mxyz) costheta = (x[1]*x[1] + aa*aa - slvrng*slvrng)/(2.*x[1]*aa) Bpar.append(aa*costheta) perp = aa * np.sqrt(1 - costheta*costheta) direction = np.sign(np.dot( np.cross(targxyz-mxyz, sxyz-mxyz), mvel)) Bperp.append(direction*perp) catalog.addItem('parallel baseline at upperleft of master track', Bpar[0], 'runPreprocessor') catalog.addItem('parallel baseline at upperright of master track', Bpar[1], 'runPreprocessor') catalog.addItem('parallel baseline at lowerleft of master track', Bpar[2], 'runPreprocessor') catalog.addItem('parallel baseline at lowerright of master track', Bpar[3], 'runPreprocessor') catalog.addItem('parallel baseline at center of master track', Bpar[4], 'runPreprocessor') catalog.addItem('perpendicular baseline at upperleft of master track', Bperp[0], 'runPreprocessor') catalog.addItem('perpendicular baseline at upperright of master track', Bperp[1], 'runPreprocessor') catalog.addItem('perpendicular baseline at lowerleft of master track', Bperp[2], 'runPreprocessor') catalog.addItem('perpendicular baseline at lowerright of master track', Bperp[3], 'runPreprocessor') catalog.addItem('perpendicular baseline at center of master track', Bperp[4], 'runPreprocessor') ################################################## #4. compute bounding box ################################################## masterBbox = getBboxGeo(self.master.track) slaveBbox = getBboxGeo(self.slave.track) catalog.addItem('master bounding box', masterBbox, 'runPreprocessor') catalog.addItem('slave bounding box', slaveBbox, 'runPreprocessor') catalog.printToLog(logger, "runPreprocessor") self._insar.procDoc.addAllFromCatalog(catalog)
def runDownloadDem(self): '''download DEM and water body ''' catalog = isceobj.Catalog.createCatalog(self._insar.procDoc.name) self.updateParamemetersFromUser() referenceTrack = self._insar.loadTrack(reference=True) secondaryTrack = self._insar.loadTrack(reference=False) bboxGeo = getBboxGeo(referenceTrack) bbox = np.array(bboxGeo) bboxStr = '{} {} {} {}'.format(np.int(np.floor(bbox[0])), np.int(np.ceil(bbox[1])), np.int(np.floor(bbox[2])), np.int(np.ceil(bbox[3]))) #get 1 arcsecond dem for coregistration if self.dem == None: demDir = 'dem_1_arcsec' os.makedirs(demDir, exist_ok=True) os.chdir(demDir) # downloadUrl = 'http://e4ftl01.cr.usgs.gov/MEASURES/SRTMGL1.003/2000.02.11' # cmd = 'dem.py -a stitch -b {} -k -s 1 -c -f -u {}'.format( # bboxStr, # downloadUrl # ) # runCmd(cmd) # cmd = 'fixImageXml.py -i demLat_*_*_Lon_*_*.dem.wgs84 -f' # runCmd(cmd) # cmd = 'rm *.hgt* *.log demLat_*_*_Lon_*_*.dem demLat_*_*_Lon_*_*.dem.vrt demLat_*_*_Lon_*_*.dem.xml' # runCmd(cmd) #replace the above system calls with function calls downloadDem(list(bbox), demType='version3', resolution=1, fillingValue=-32768, outputFile=None, userName=None, passWord=None) imagePathXml((glob.glob('demLat_*_*_Lon_*_*.dem.wgs84'))[0], fullPath=True) filesRemoved = glob.glob('*.hgt*') + glob.glob('*.log') + glob.glob( 'demLat_*_*_Lon_*_*.dem') + glob.glob( 'demLat_*_*_Lon_*_*.dem.vrt') + glob.glob( 'demLat_*_*_Lon_*_*.dem.xml') for filex in filesRemoved: os.remove(filex) os.chdir('../') self.dem = glob.glob( os.path.join(demDir, 'demLat_*_*_Lon_*_*.dem.wgs84'))[0] #get 3 arcsecond dem for geocoding if self.demGeo == None: demGeoDir = 'dem_3_arcsec' os.makedirs(demGeoDir, exist_ok=True) os.chdir(demGeoDir) # downloadUrl = 'http://e4ftl01.cr.usgs.gov/MEASURES/SRTMGL3.003/2000.02.11' # cmd = 'dem.py -a stitch -b {} -k -s 3 -c -f -u {}'.format( # bboxStr, # downloadUrl # ) # runCmd(cmd) # cmd = 'fixImageXml.py -i demLat_*_*_Lon_*_*.dem.wgs84 -f' # runCmd(cmd) # cmd = 'rm *.hgt* *.log demLat_*_*_Lon_*_*.dem demLat_*_*_Lon_*_*.dem.vrt demLat_*_*_Lon_*_*.dem.xml' # runCmd(cmd) #replace the above system calls with function calls downloadDem(list(bbox), demType='version3', resolution=3, fillingValue=-32768, outputFile=None, userName=None, passWord=None) imagePathXml((glob.glob('demLat_*_*_Lon_*_*.dem.wgs84'))[0], fullPath=True) filesRemoved = glob.glob('*.hgt*') + glob.glob('*.log') + glob.glob( 'demLat_*_*_Lon_*_*.dem') + glob.glob( 'demLat_*_*_Lon_*_*.dem.vrt') + glob.glob( 'demLat_*_*_Lon_*_*.dem.xml') for filex in filesRemoved: os.remove(filex) os.chdir('../') self.demGeo = glob.glob( os.path.join(demGeoDir, 'demLat_*_*_Lon_*_*.dem.wgs84'))[0] #get water body for masking interferogram if self.wbd == None: wbdDir = 'wbd_1_arcsec' os.makedirs(wbdDir, exist_ok=True) os.chdir(wbdDir) #cmd = 'wbd.py {}'.format(bboxStr) #runCmd(cmd) download_wbd(np.int(np.floor(bbox[0])), np.int(np.ceil(bbox[1])), np.int(np.floor(bbox[2])), np.int(np.ceil(bbox[3]))) #cmd = 'fixImageXml.py -i swbdLat_*_*_Lon_*_*.wbd -f' #runCmd(cmd) #cmd = 'rm *.log' #runCmd(cmd) #replace the above system calls with function calls imagePathXml((glob.glob('swbdLat_*_*_Lon_*_*.wbd'))[0], fullPath=True) filesRemoved = glob.glob('*.log') for filex in filesRemoved: os.remove(filex) os.chdir('../') self.wbd = glob.glob(os.path.join(wbdDir, 'swbdLat_*_*_Lon_*_*.wbd'))[0] self._insar.dem = self.dem self._insar.demGeo = self.demGeo self._insar.wbd = self.wbd catalog.printToLog(logger, "runDownloadDem") self._insar.procDoc.addAllFromCatalog(catalog)
####################################################### demFile = os.path.abspath(demGeo) trackReferenceStack = loadProduct(ref_date_stack_track) #compute bounding box for geocoding if bbox is not None: bbox = [float(x) for x in bbox.split('/')] if len(bbox) != 4: raise Exception('user input bbox must have four elements') else: img = isceobj.createImage() img.load(inputFile + '.xml') bbox = getBboxGeo(trackReferenceStack, useTrackOnly=True, numberOfSamples=img.width, numberOfLines=img.length, numberRangeLooks=numberRangeLooks, numberAzimuthLooks=numberAzimuthLooks) print( '=====================================================================================================' ) print('geocode bounding box: {}'.format(bbox)) print( '=====================================================================================================' ) interpMethod = geocodeInterpMethod geocode(trackReferenceStack, demFile, inputFile, bbox, numberRangeLooks, numberAzimuthLooks, interpMethod, 0, 0)
def runBaseline(self): '''compute baseline ''' catalog = isceobj.Catalog.createCatalog(self._insar.procDoc.name) self.updateParamemetersFromUser() referenceTrack = self._insar.loadTrack(reference=True) secondaryTrack = self._insar.loadTrack(reference=False) ################################################## #2. compute burst synchronization ################################################## #burst synchronization may slowly change along a track as a result of the changing relative speed of the two flights #in one frame, real unsynchronized time is the same for all swaths unsynTime = 0 #real synchronized time/percentage depends on the swath burst length (synTime = burstlength - abs(unsynTime)) #synTime = 0 synPercentage = 0 numberOfFrames = len(self._insar.referenceFrames) numberOfSwaths = self._insar.endingSwath - self._insar.startingSwath + 1 for i, frameNumber in enumerate(self._insar.referenceFrames): for j, swathNumber in enumerate(range(self._insar.startingSwath, self._insar.endingSwath + 1)): referenceSwath = referenceTrack.frames[i].swaths[j] secondarySwath = secondaryTrack.frames[i].swaths[j] #using Piyush's code for computing range and azimuth offsets midRange = referenceSwath.startingRange + referenceSwath.rangePixelSize * referenceSwath.numberOfSamples * 0.5 midSensingStart = referenceSwath.sensingStart + datetime.timedelta(seconds = referenceSwath.numberOfLines * 0.5 / referenceSwath.prf) llh = referenceTrack.orbit.rdr2geo(midSensingStart, midRange) slvaz, slvrng = secondaryTrack.orbit.geo2rdr(llh) ###Translate to offsets #note that secondary range pixel size and prf might be different from reference, here we assume there is a virtual secondary with same #range pixel size and prf rgoff = ((slvrng - secondarySwath.startingRange) / referenceSwath.rangePixelSize) - referenceSwath.numberOfSamples * 0.5 azoff = ((slvaz - secondarySwath.sensingStart).total_seconds() * referenceSwath.prf) - referenceSwath.numberOfLines * 0.5 #compute burst synchronization #burst parameters for ScanSAR wide mode not estimed yet if self._insar.modeCombination == 21: scburstStartLine = (referenceSwath.burstStartTime - referenceSwath.sensingStart).total_seconds() * referenceSwath.prf + azoff #secondary burst start times corresponding to reference burst start times (100% synchronization) scburstStartLines = np.arange(scburstStartLine - 100000*referenceSwath.burstCycleLength, \ scburstStartLine + 100000*referenceSwath.burstCycleLength, \ referenceSwath.burstCycleLength) dscburstStartLines = -((secondarySwath.burstStartTime - secondarySwath.sensingStart).total_seconds() * secondarySwath.prf - scburstStartLines) #find the difference with minimum absolute value unsynLines = dscburstStartLines[np.argmin(np.absolute(dscburstStartLines))] if np.absolute(unsynLines) >= secondarySwath.burstLength: synLines = 0 if unsynLines > 0: unsynLines = secondarySwath.burstLength else: unsynLines = -secondarySwath.burstLength else: synLines = secondarySwath.burstLength - np.absolute(unsynLines) unsynTime += unsynLines / referenceSwath.prf synPercentage += synLines / referenceSwath.burstLength * 100.0 catalog.addItem('burst synchronization of frame {} swath {}'.format(frameNumber, swathNumber), '%.1f%%'%(synLines / referenceSwath.burstLength * 100.0), 'runBaseline') ############################################################################################ #illustration of the sign of the number of unsynchronized lines (unsynLines) #The convention is the same as ampcor offset, that is, # secondaryLineNumber = referenceLineNumber + unsynLines # # |-----------------------| ------------ # | | ^ # | | | # | | | unsynLines < 0 # | | | # | | \ / # | | |-----------------------| # | | | | # | | | | # |-----------------------| | | # Reference Burst | | # | | # | | # | | # | | # |-----------------------| # Secondary Burst # # ############################################################################################ ##burst parameters for ScanSAR wide mode not estimed yet elif self._insar.modeCombination == 31: #scansar is reference scburstStartLine = (referenceSwath.burstStartTime - referenceSwath.sensingStart).total_seconds() * referenceSwath.prf + azoff #secondary burst start times corresponding to reference burst start times (100% synchronization) for k in range(-100000, 100000): saz_burstx = scburstStartLine + referenceSwath.burstCycleLength * k st_burstx = secondarySwath.sensingStart + datetime.timedelta(seconds=saz_burstx / referenceSwath.prf) if saz_burstx >= 0.0 and saz_burstx <= secondarySwath.numberOfLines -1: secondarySwath.burstStartTime = st_burstx secondarySwath.burstLength = referenceSwath.burstLength secondarySwath.burstCycleLength = referenceSwath.burstCycleLength secondarySwath.swathNumber = referenceSwath.swathNumber break #unsynLines = 0 #synLines = referenceSwath.burstLength #unsynTime += unsynLines / referenceSwath.prf #synPercentage += synLines / referenceSwath.burstLength * 100.0 catalog.addItem('burst synchronization of frame {} swath {}'.format(frameNumber, swathNumber), '%.1f%%'%(100.0), 'runBaseline') else: pass #overwrite original frame parameter file if self._insar.modeCombination == 31: frameDir = 'f{}_{}'.format(i+1, frameNumber) self._insar.saveProduct(secondaryTrack.frames[i], os.path.join(frameDir, self._insar.secondaryFrameParameter)) #getting average if self._insar.modeCombination == 21: unsynTime /= numberOfFrames*numberOfSwaths synPercentage /= numberOfFrames*numberOfSwaths elif self._insar.modeCombination == 31: unsynTime = 0. synPercentage = 100. else: pass #record results if (self._insar.modeCombination == 21) or (self._insar.modeCombination == 31): self._insar.burstUnsynchronizedTime = unsynTime self._insar.burstSynchronization = synPercentage catalog.addItem('burst synchronization averaged', '%.1f%%'%(synPercentage), 'runBaseline') ################################################## #3. compute baseline ################################################## #only compute baseline at four corners and center of the reference track bboxRdr = getBboxRdr(referenceTrack) rangeMin = bboxRdr[0] rangeMax = bboxRdr[1] azimuthTimeMin = bboxRdr[2] azimuthTimeMax = bboxRdr[3] azimuthTimeMid = azimuthTimeMin+datetime.timedelta(seconds=(azimuthTimeMax-azimuthTimeMin).total_seconds()/2.0) rangeMid = (rangeMin + rangeMax) / 2.0 points = [[azimuthTimeMin, rangeMin], [azimuthTimeMin, rangeMax], [azimuthTimeMax, rangeMin], [azimuthTimeMax, rangeMax], [azimuthTimeMid, rangeMid]] Bpar = [] Bperp = [] #modify Piyush's code for computing baslines refElp = Planet(pname='Earth').ellipsoid for x in points: referenceSV = referenceTrack.orbit.interpolate(x[0], method='hermite') target = referenceTrack.orbit.rdr2geo(x[0], x[1]) slvTime, slvrng = secondaryTrack.orbit.geo2rdr(target) secondarySV = secondaryTrack.orbit.interpolateOrbit(slvTime, method='hermite') targxyz = np.array(refElp.LLH(target[0], target[1], target[2]).ecef().tolist()) mxyz = np.array(referenceSV.getPosition()) mvel = np.array(referenceSV.getVelocity()) sxyz = np.array(secondarySV.getPosition()) #to fix abrupt change near zero in baseline grid. JUN-05-2020 mvelunit = mvel / np.linalg.norm(mvel) sxyz = sxyz - np.dot ( sxyz-mxyz, mvelunit) * mvelunit aa = np.linalg.norm(sxyz-mxyz) costheta = (x[1]*x[1] + aa*aa - slvrng*slvrng)/(2.*x[1]*aa) Bpar.append(aa*costheta) perp = aa * np.sqrt(1 - costheta*costheta) direction = np.sign(np.dot( np.cross(targxyz-mxyz, sxyz-mxyz), mvel)) Bperp.append(direction*perp) catalog.addItem('parallel baseline at upperleft of reference track', Bpar[0], 'runBaseline') catalog.addItem('parallel baseline at upperright of reference track', Bpar[1], 'runBaseline') catalog.addItem('parallel baseline at lowerleft of reference track', Bpar[2], 'runBaseline') catalog.addItem('parallel baseline at lowerright of reference track', Bpar[3], 'runBaseline') catalog.addItem('parallel baseline at center of reference track', Bpar[4], 'runBaseline') catalog.addItem('perpendicular baseline at upperleft of reference track', Bperp[0], 'runBaseline') catalog.addItem('perpendicular baseline at upperright of reference track', Bperp[1], 'runBaseline') catalog.addItem('perpendicular baseline at lowerleft of reference track', Bperp[2], 'runBaseline') catalog.addItem('perpendicular baseline at lowerright of reference track', Bperp[3], 'runBaseline') catalog.addItem('perpendicular baseline at center of reference track', Bperp[4], 'runBaseline') ################################################## #4. compute bounding box ################################################## referenceBbox = getBboxGeo(referenceTrack) secondaryBbox = getBboxGeo(secondaryTrack) catalog.addItem('reference bounding box', referenceBbox, 'runBaseline') catalog.addItem('secondary bounding box', secondaryBbox, 'runBaseline') catalog.printToLog(logger, "runBaseline") self._insar.procDoc.addAllFromCatalog(catalog)
def runDownloadDem(self): '''download DEM and water body ''' catalog = isceobj.Catalog.createCatalog(self._insar.procDoc.name) self.updateParamemetersFromUser() masterTrack = self._insar.loadTrack(master=True) slaveTrack = self._insar.loadTrack(master=False) bboxGeo = getBboxGeo(masterTrack) bbox = np.array(bboxGeo) bboxStr = '{} {} {} {}'.format(np.int(np.floor(bbox[0])), np.int(np.ceil(bbox[1])), np.int(np.floor(bbox[2])), np.int(np.ceil(bbox[3]))) #get 1 arcsecond dem for coregistration if self.dem == None: demDir = 'dem_1_arcsec' if not os.path.exists(demDir): os.makedirs(demDir) os.chdir(demDir) downloadUrl = 'http://e4ftl01.cr.usgs.gov/MEASURES/SRTMGL1.003/2000.02.11' cmd = 'dem.py -a stitch -b {} -k -s 1 -c -f -u {}'.format( bboxStr, downloadUrl) runCmd(cmd) cmd = 'fixImageXml.py -i demLat_*_*_Lon_*_*.dem.wgs84 -f' runCmd(cmd) cmd = 'rm *.hgt* *.log demLat_*_*_Lon_*_*.dem demLat_*_*_Lon_*_*.dem.vrt demLat_*_*_Lon_*_*.dem.xml' runCmd(cmd) os.chdir('../') self.dem = glob.glob( os.path.join(demDir, 'demLat_*_*_Lon_*_*.dem.wgs84'))[0] #get 3 arcsecond dem for geocoding if self.demGeo == None: demGeoDir = 'dem_3_arcsec' if not os.path.exists(demGeoDir): os.makedirs(demGeoDir) os.chdir(demGeoDir) downloadUrl = 'http://e4ftl01.cr.usgs.gov/MEASURES/SRTMGL3.003/2000.02.11' cmd = 'dem.py -a stitch -b {} -k -s 3 -c -f -u {}'.format( bboxStr, downloadUrl) runCmd(cmd) cmd = 'fixImageXml.py -i demLat_*_*_Lon_*_*.dem.wgs84 -f' runCmd(cmd) cmd = 'rm *.hgt* *.log demLat_*_*_Lon_*_*.dem demLat_*_*_Lon_*_*.dem.vrt demLat_*_*_Lon_*_*.dem.xml' runCmd(cmd) os.chdir('../') self.demGeo = glob.glob( os.path.join(demGeoDir, 'demLat_*_*_Lon_*_*.dem.wgs84'))[0] #get water body for masking interferogram if self.wbd == None: wbdDir = 'wbd_1_arcsec' if not os.path.exists(wbdDir): os.makedirs(wbdDir) os.chdir(wbdDir) #cmd = 'wbd.py {}'.format(bboxStr) #runCmd(cmd) download_wbd(np.int(np.floor(bbox[0])), np.int(np.ceil(bbox[1])), np.int(np.floor(bbox[2])), np.int(np.ceil(bbox[3]))) cmd = 'fixImageXml.py -i swbdLat_*_*_Lon_*_*.wbd -f' runCmd(cmd) cmd = 'rm *.log' runCmd(cmd) os.chdir('../') self.wbd = glob.glob(os.path.join(wbdDir, 'swbdLat_*_*_Lon_*_*.wbd'))[0] self._insar.dem = self.dem self._insar.demGeo = self.demGeo self._insar.wbd = self.wbd catalog.printToLog(logger, "runDownloadDem") self._insar.procDoc.addAllFromCatalog(catalog)
def runPreprocessor(self): '''Extract images. ''' catalog = isceobj.Catalog.createCatalog(self._insar.procDoc.name) #find files #actually no need to use absolute path any longer, since we are able to find file from vrt now. 27-JAN-2020, CRL. #denseoffset may still need absolute path when making links self.referenceDir = os.path.abspath(self.referenceDir) self.secondaryDir = os.path.abspath(self.secondaryDir) ledFilesReference = sorted(glob.glob(os.path.join(self.referenceDir, 'LED-ALOS2*-*-*'))) imgFilesReference = sorted(glob.glob(os.path.join(self.referenceDir, 'IMG-{}-ALOS2*-*-*'.format(self.referencePolarization.upper())))) ledFilesSecondary = sorted(glob.glob(os.path.join(self.secondaryDir, 'LED-ALOS2*-*-*'))) imgFilesSecondary = sorted(glob.glob(os.path.join(self.secondaryDir, 'IMG-{}-ALOS2*-*-*'.format(self.secondaryPolarization.upper())))) firstFrameReference = ledFilesReference[0].split('-')[-3][-4:] firstFrameSecondary = ledFilesSecondary[0].split('-')[-3][-4:] firstFrameImagesReference = sorted(glob.glob(os.path.join(self.referenceDir, 'IMG-{}-ALOS2*{}-*-*'.format(self.referencePolarization.upper(), firstFrameReference)))) firstFrameImagesSecondary = sorted(glob.glob(os.path.join(self.secondaryDir, 'IMG-{}-ALOS2*{}-*-*'.format(self.secondaryPolarization.upper(), firstFrameSecondary)))) #determin operation mode referenceMode = os.path.basename(ledFilesReference[0]).split('-')[-1][0:3] secondaryMode = os.path.basename(ledFilesSecondary[0]).split('-')[-1][0:3] spotlightModes = ['SBS'] stripmapModes = ['UBS', 'UBD', 'HBS', 'HBD', 'HBQ', 'FBS', 'FBD', 'FBQ'] scansarNominalModes = ['WBS', 'WBD', 'WWS', 'WWD'] scansarWideModes = ['VBS', 'VBD'] scansarModes = ['WBS', 'WBD', 'WWS', 'WWD', 'VBS', 'VBD'] #usable combinations if (referenceMode in spotlightModes) and (secondaryMode in spotlightModes): self._insar.modeCombination = 0 elif (referenceMode in stripmapModes) and (secondaryMode in stripmapModes): self._insar.modeCombination = 1 elif (referenceMode in scansarNominalModes) and (secondaryMode in scansarNominalModes): self._insar.modeCombination = 21 elif (referenceMode in scansarWideModes) and (secondaryMode in scansarWideModes): self._insar.modeCombination = 22 elif (referenceMode in scansarNominalModes) and (secondaryMode in stripmapModes): self._insar.modeCombination = 31 elif (referenceMode in scansarWideModes) and (secondaryMode in stripmapModes): self._insar.modeCombination = 32 else: print('\n\nthis mode combination is not possible') print('note that for ScanSAR-stripmap, ScanSAR must be reference\n\n') raise Exception('mode combination not supported') # pixel size from real data processing. azimuth pixel size may change a bit as # the antenna points to a different swath and therefore uses a different PRF. # MODE RANGE PIXEL SIZE (LOOKS) AZIMUTH PIXEL SIZE (LOOKS) # ------------------------------------------------------------------- # SPT [SBS] # 1.4304222392897463 (2) 0.9351804642158579 (4) # SM1 [UBS,UBD] # 1.4304222392897463 (2) 1.8291988125114438 (2) # SM2 [HBS,HBD,HBQ] # 2.8608444785794984 (2) 3.0672373839847196 (2) # SM3 [FBS,FBD,FBQ] # 4.291266717869248 (2) 3.2462615913656667 (4) # WD1 [WBS,WBD] [WWS,WWD] # 8.582533435738496 (1) 2.6053935830031887 (14) # 8.582533435738496 (1) 2.092362043327227 (14) # 8.582533435738496 (1) 2.8817632034495717 (14) # 8.582533435738496 (1) 3.054362492601842 (14) # 8.582533435738496 (1) 2.4582084463356977 (14) # WD2 [VBS,VBD] # 8.582533435738496 (1) 2.9215796012950728 (14) # 8.582533435738496 (1) 3.088859074497863 (14) # 8.582533435738496 (1) 2.8792293071133073 (14) # 8.582533435738496 (1) 3.0592146044234854 (14) # 8.582533435738496 (1) 2.8818767752199137 (14) # 8.582533435738496 (1) 3.047038521027477 (14) # 8.582533435738496 (1) 2.898816222039108 (14) #determine default number of looks: self._insar.numberRangeLooks1 = self.numberRangeLooks1 self._insar.numberAzimuthLooks1 = self.numberAzimuthLooks1 self._insar.numberRangeLooks2 = self.numberRangeLooks2 self._insar.numberAzimuthLooks2 = self.numberAzimuthLooks2 #the following two will be automatically determined by runRdrDemOffset.py self._insar.numberRangeLooksSim = self.numberRangeLooksSim self._insar.numberAzimuthLooksSim = self.numberAzimuthLooksSim self._insar.numberRangeLooksIon = self.numberRangeLooksIon self._insar.numberAzimuthLooksIon = self.numberAzimuthLooksIon if self._insar.numberRangeLooks1 == None: if referenceMode in ['SBS']: self._insar.numberRangeLooks1 = 2 elif referenceMode in ['UBS', 'UBD']: self._insar.numberRangeLooks1 = 2 elif referenceMode in ['HBS', 'HBD', 'HBQ']: self._insar.numberRangeLooks1 = 2 elif referenceMode in ['FBS', 'FBD', 'FBQ']: self._insar.numberRangeLooks1 = 2 elif referenceMode in ['WBS', 'WBD']: self._insar.numberRangeLooks1 = 1 elif referenceMode in ['WWS', 'WWD']: self._insar.numberRangeLooks1 = 2 elif referenceMode in ['VBS', 'VBD']: self._insar.numberRangeLooks1 = 1 else: raise Exception('unknow acquisition mode') if self._insar.numberAzimuthLooks1 == None: if referenceMode in ['SBS']: self._insar.numberAzimuthLooks1 = 4 elif referenceMode in ['UBS', 'UBD']: self._insar.numberAzimuthLooks1 = 2 elif referenceMode in ['HBS', 'HBD', 'HBQ']: self._insar.numberAzimuthLooks1 = 2 elif referenceMode in ['FBS', 'FBD', 'FBQ']: self._insar.numberAzimuthLooks1 = 4 elif referenceMode in ['WBS', 'WBD']: self._insar.numberAzimuthLooks1 = 14 elif referenceMode in ['WWS', 'WWD']: self._insar.numberAzimuthLooks1 = 14 elif referenceMode in ['VBS', 'VBD']: self._insar.numberAzimuthLooks1 = 14 else: raise Exception('unknow acquisition mode') if self._insar.numberRangeLooks2 == None: if referenceMode in spotlightModes: self._insar.numberRangeLooks2 = 4 elif referenceMode in stripmapModes: self._insar.numberRangeLooks2 = 4 elif referenceMode in scansarModes: self._insar.numberRangeLooks2 = 5 else: raise Exception('unknow acquisition mode') if self._insar.numberAzimuthLooks2 == None: if referenceMode in spotlightModes: self._insar.numberAzimuthLooks2 = 4 elif referenceMode in stripmapModes: self._insar.numberAzimuthLooks2 = 4 elif referenceMode in scansarModes: self._insar.numberAzimuthLooks2 = 2 else: raise Exception('unknow acquisition mode') if self._insar.numberRangeLooksIon == None: if referenceMode in spotlightModes: self._insar.numberRangeLooksIon = 16 elif referenceMode in stripmapModes: self._insar.numberRangeLooksIon = 16 elif referenceMode in scansarModes: self._insar.numberRangeLooksIon = 40 else: raise Exception('unknow acquisition mode') if self._insar.numberAzimuthLooksIon == None: if referenceMode in spotlightModes: self._insar.numberAzimuthLooksIon = 16 elif referenceMode in stripmapModes: self._insar.numberAzimuthLooksIon = 16 elif referenceMode in scansarModes: self._insar.numberAzimuthLooksIon = 16 else: raise Exception('unknow acquisition mode') #define processing file names self._insar.referenceDate = os.path.basename(ledFilesReference[0]).split('-')[2] self._insar.secondaryDate = os.path.basename(ledFilesSecondary[0]).split('-')[2] self._insar.setFilename(referenceDate=self._insar.referenceDate, secondaryDate=self._insar.secondaryDate, nrlks1=self._insar.numberRangeLooks1, nalks1=self._insar.numberAzimuthLooks1, nrlks2=self._insar.numberRangeLooks2, nalks2=self._insar.numberAzimuthLooks2) #find frame numbers if (self._insar.modeCombination == 31) or (self._insar.modeCombination == 32): if (self.referenceFrames == None) or (self.secondaryFrames == None): raise Exception('for ScanSAR-stripmap inteferometry, you must set reference and secondary frame numbers') #if not set, find frames automatically if self.referenceFrames == None: self.referenceFrames = [] for led in ledFilesReference: frameNumber = os.path.basename(led).split('-')[1][-4:] if frameNumber not in self.referenceFrames: self.referenceFrames.append(frameNumber) if self.secondaryFrames == None: self.secondaryFrames = [] for led in ledFilesSecondary: frameNumber = os.path.basename(led).split('-')[1][-4:] if frameNumber not in self.secondaryFrames: self.secondaryFrames.append(frameNumber) #sort frames self.referenceFrames = sorted(self.referenceFrames) self.secondaryFrames = sorted(self.secondaryFrames) #check number of frames if len(self.referenceFrames) != len(self.secondaryFrames): raise Exception('number of frames in reference dir is not equal to number of frames \ in secondary dir. please set frame number manually') #find swath numbers (if not ScanSAR-ScanSAR, compute valid swaths) if (self._insar.modeCombination == 0) or (self._insar.modeCombination == 1): self.startingSwath = 1 self.endingSwath = 1 if self._insar.modeCombination == 21: if self.startingSwath == None: self.startingSwath = 1 if self.endingSwath == None: self.endingSwath = 5 if self._insar.modeCombination == 22: if self.startingSwath == None: self.startingSwath = 1 if self.endingSwath == None: self.endingSwath = 7 #determine starting and ending swaths for ScanSAR-stripmap, user's settings are overwritten #use first frame to check overlap if (self._insar.modeCombination == 31) or (self._insar.modeCombination == 32): if self._insar.modeCombination == 31: numberOfSwaths = 5 else: numberOfSwaths = 7 overlapSubswaths = [] for i in range(numberOfSwaths): overlapRatio = check_overlap(ledFilesReference[0], firstFrameImagesReference[i], ledFilesSecondary[0], firstFrameImagesSecondary[0]) if overlapRatio > 1.0 / 4.0: overlapSubswaths.append(i+1) if overlapSubswaths == []: raise Exception('There is no overlap area between the ScanSAR-stripmap pair') self.startingSwath = int(overlapSubswaths[0]) self.endingSwath = int(overlapSubswaths[-1]) #save the valid frames and swaths for future processing self._insar.referenceFrames = self.referenceFrames self._insar.secondaryFrames = self.secondaryFrames self._insar.startingSwath = self.startingSwath self._insar.endingSwath = self.endingSwath ################################################## #1. create directories and read data ################################################## self.reference.configure() self.secondary.configure() self.reference.track.configure() self.secondary.track.configure() for i, (referenceFrame, secondaryFrame) in enumerate(zip(self._insar.referenceFrames, self._insar.secondaryFrames)): #frame number starts with 1 frameDir = 'f{}_{}'.format(i+1, referenceFrame) os.makedirs(frameDir, exist_ok=True) os.chdir(frameDir) #attach a frame to reference and secondary frameObjReference = MultiMode.createFrame() frameObjSecondary = MultiMode.createFrame() frameObjReference.configure() frameObjSecondary.configure() self.reference.track.frames.append(frameObjReference) self.secondary.track.frames.append(frameObjSecondary) #swath number starts with 1 for j in range(self._insar.startingSwath, self._insar.endingSwath+1): print('processing frame {} swath {}'.format(referenceFrame, j)) swathDir = 's{}'.format(j) os.makedirs(swathDir, exist_ok=True) os.chdir(swathDir) #attach a swath to reference and secondary swathObjReference = MultiMode.createSwath() swathObjSecondary = MultiMode.createSwath() swathObjReference.configure() swathObjSecondary.configure() self.reference.track.frames[-1].swaths.append(swathObjReference) self.secondary.track.frames[-1].swaths.append(swathObjSecondary) #setup reference self.reference.leaderFile = sorted(glob.glob(os.path.join(self.referenceDir, 'LED-ALOS2*{}-*-*'.format(referenceFrame))))[0] if referenceMode in scansarModes: self.reference.imageFile = sorted(glob.glob(os.path.join(self.referenceDir, 'IMG-{}-ALOS2*{}-*-*-F{}'.format(self.referencePolarization.upper(), referenceFrame, j))))[0] else: self.reference.imageFile = sorted(glob.glob(os.path.join(self.referenceDir, 'IMG-{}-ALOS2*{}-*-*'.format(self.referencePolarization.upper(), referenceFrame))))[0] self.reference.outputFile = self._insar.referenceSlc self.reference.useVirtualFile = self.useVirtualFile #read reference (imageFDR, imageData)=self.reference.readImage() (leaderFDR, sceneHeaderRecord, platformPositionRecord, facilityRecord)=self.reference.readLeader() self.reference.setSwath(leaderFDR, sceneHeaderRecord, platformPositionRecord, facilityRecord, imageFDR, imageData) self.reference.setFrame(leaderFDR, sceneHeaderRecord, platformPositionRecord, facilityRecord, imageFDR, imageData) self.reference.setTrack(leaderFDR, sceneHeaderRecord, platformPositionRecord, facilityRecord, imageFDR, imageData) #setup secondary self.secondary.leaderFile = sorted(glob.glob(os.path.join(self.secondaryDir, 'LED-ALOS2*{}-*-*'.format(secondaryFrame))))[0] if secondaryMode in scansarModes: self.secondary.imageFile = sorted(glob.glob(os.path.join(self.secondaryDir, 'IMG-{}-ALOS2*{}-*-*-F{}'.format(self.secondaryPolarization.upper(), secondaryFrame, j))))[0] else: self.secondary.imageFile = sorted(glob.glob(os.path.join(self.secondaryDir, 'IMG-{}-ALOS2*{}-*-*'.format(self.secondaryPolarization.upper(), secondaryFrame))))[0] self.secondary.outputFile = self._insar.secondarySlc self.secondary.useVirtualFile = self.useVirtualFile #read secondary (imageFDR, imageData)=self.secondary.readImage() (leaderFDR, sceneHeaderRecord, platformPositionRecord, facilityRecord)=self.secondary.readLeader() self.secondary.setSwath(leaderFDR, sceneHeaderRecord, platformPositionRecord, facilityRecord, imageFDR, imageData) self.secondary.setFrame(leaderFDR, sceneHeaderRecord, platformPositionRecord, facilityRecord, imageFDR, imageData) self.secondary.setTrack(leaderFDR, sceneHeaderRecord, platformPositionRecord, facilityRecord, imageFDR, imageData) os.chdir('../') self._insar.saveProduct(self.reference.track.frames[-1], self._insar.referenceFrameParameter) self._insar.saveProduct(self.secondary.track.frames[-1], self._insar.secondaryFrameParameter) os.chdir('../') self._insar.saveProduct(self.reference.track, self._insar.referenceTrackParameter) self._insar.saveProduct(self.secondary.track, self._insar.secondaryTrackParameter) ################################################## #2. compute burst synchronization ################################################## #burst synchronization may slowly change along a track as a result of the changing relative speed of the two flights #in one frame, real unsynchronized time is the same for all swaths unsynTime = 0 #real synchronized time/percentage depends on the swath burst length (synTime = burstlength - abs(unsynTime)) #synTime = 0 synPercentage = 0 numberOfFrames = len(self._insar.referenceFrames) numberOfSwaths = self._insar.endingSwath - self._insar.startingSwath + 1 for i, frameNumber in enumerate(self._insar.referenceFrames): for j, swathNumber in enumerate(range(self._insar.startingSwath, self._insar.endingSwath + 1)): referenceSwath = self.reference.track.frames[i].swaths[j] secondarySwath = self.secondary.track.frames[i].swaths[j] #using Piyush's code for computing range and azimuth offsets midRange = referenceSwath.startingRange + referenceSwath.rangePixelSize * referenceSwath.numberOfSamples * 0.5 midSensingStart = referenceSwath.sensingStart + datetime.timedelta(seconds = referenceSwath.numberOfLines * 0.5 / referenceSwath.prf) llh = self.reference.track.orbit.rdr2geo(midSensingStart, midRange) slvaz, slvrng = self.secondary.track.orbit.geo2rdr(llh) ###Translate to offsets #note that secondary range pixel size and prf might be different from reference, here we assume there is a virtual secondary with same #range pixel size and prf rgoff = ((slvrng - secondarySwath.startingRange) / referenceSwath.rangePixelSize) - referenceSwath.numberOfSamples * 0.5 azoff = ((slvaz - secondarySwath.sensingStart).total_seconds() * referenceSwath.prf) - referenceSwath.numberOfLines * 0.5 #compute burst synchronization #burst parameters for ScanSAR wide mode not estimed yet if self._insar.modeCombination == 21: scburstStartLine = (referenceSwath.burstStartTime - referenceSwath.sensingStart).total_seconds() * referenceSwath.prf + azoff #secondary burst start times corresponding to reference burst start times (100% synchronization) scburstStartLines = np.arange(scburstStartLine - 100000*referenceSwath.burstCycleLength, \ scburstStartLine + 100000*referenceSwath.burstCycleLength, \ referenceSwath.burstCycleLength) dscburstStartLines = -((secondarySwath.burstStartTime - secondarySwath.sensingStart).total_seconds() * secondarySwath.prf - scburstStartLines) #find the difference with minimum absolute value unsynLines = dscburstStartLines[np.argmin(np.absolute(dscburstStartLines))] if np.absolute(unsynLines) >= secondarySwath.burstLength: synLines = 0 if unsynLines > 0: unsynLines = secondarySwath.burstLength else: unsynLines = -secondarySwath.burstLength else: synLines = secondarySwath.burstLength - np.absolute(unsynLines) unsynTime += unsynLines / referenceSwath.prf synPercentage += synLines / referenceSwath.burstLength * 100.0 catalog.addItem('burst synchronization of frame {} swath {}'.format(frameNumber, swathNumber), '%.1f%%'%(synLines / referenceSwath.burstLength * 100.0), 'runPreprocessor') ############################################################################################ #illustration of the sign of the number of unsynchronized lines (unsynLines) #The convention is the same as ampcor offset, that is, # secondaryLineNumber = referenceLineNumber + unsynLines # # |-----------------------| ------------ # | | ^ # | | | # | | | unsynLines < 0 # | | | # | | \ / # | | |-----------------------| # | | | | # | | | | # |-----------------------| | | # Reference Burst | | # | | # | | # | | # | | # |-----------------------| # Secondary Burst # # ############################################################################################ ##burst parameters for ScanSAR wide mode not estimed yet elif self._insar.modeCombination == 31: #scansar is reference scburstStartLine = (referenceSwath.burstStartTime - referenceSwath.sensingStart).total_seconds() * referenceSwath.prf + azoff #secondary burst start times corresponding to reference burst start times (100% synchronization) for k in range(-100000, 100000): saz_burstx = scburstStartLine + referenceSwath.burstCycleLength * k st_burstx = secondarySwath.sensingStart + datetime.timedelta(seconds=saz_burstx / referenceSwath.prf) if saz_burstx >= 0.0 and saz_burstx <= secondarySwath.numberOfLines -1: secondarySwath.burstStartTime = st_burstx secondarySwath.burstLength = referenceSwath.burstLength secondarySwath.burstCycleLength = referenceSwath.burstCycleLength secondarySwath.swathNumber = referenceSwath.swathNumber break #unsynLines = 0 #synLines = referenceSwath.burstLength #unsynTime += unsynLines / referenceSwath.prf #synPercentage += synLines / referenceSwath.burstLength * 100.0 catalog.addItem('burst synchronization of frame {} swath {}'.format(frameNumber, swathNumber), '%.1f%%'%(100.0), 'runPreprocessor') else: pass #overwrite original frame parameter file if self._insar.modeCombination == 31: frameDir = 'f{}_{}'.format(i+1, frameNumber) self._insar.saveProduct(self.secondary.track.frames[i], os.path.join(frameDir, self._insar.secondaryFrameParameter)) #getting average if self._insar.modeCombination == 21: unsynTime /= numberOfFrames*numberOfSwaths synPercentage /= numberOfFrames*numberOfSwaths elif self._insar.modeCombination == 31: unsynTime = 0. synPercentage = 100. else: pass #record results if (self._insar.modeCombination == 21) or (self._insar.modeCombination == 31): self._insar.burstUnsynchronizedTime = unsynTime self._insar.burstSynchronization = synPercentage catalog.addItem('burst synchronization averaged', '%.1f%%'%(synPercentage), 'runPreprocessor') ################################################## #3. compute baseline ################################################## #only compute baseline at four corners and center of the reference track bboxRdr = getBboxRdr(self.reference.track) rangeMin = bboxRdr[0] rangeMax = bboxRdr[1] azimuthTimeMin = bboxRdr[2] azimuthTimeMax = bboxRdr[3] azimuthTimeMid = azimuthTimeMin+datetime.timedelta(seconds=(azimuthTimeMax-azimuthTimeMin).total_seconds()/2.0) rangeMid = (rangeMin + rangeMax) / 2.0 points = [[azimuthTimeMin, rangeMin], [azimuthTimeMin, rangeMax], [azimuthTimeMax, rangeMin], [azimuthTimeMax, rangeMax], [azimuthTimeMid, rangeMid]] Bpar = [] Bperp = [] #modify Piyush's code for computing baslines refElp = Planet(pname='Earth').ellipsoid for x in points: referenceSV = self.reference.track.orbit.interpolate(x[0], method='hermite') target = self.reference.track.orbit.rdr2geo(x[0], x[1]) slvTime, slvrng = self.secondary.track.orbit.geo2rdr(target) secondarySV = self.secondary.track.orbit.interpolateOrbit(slvTime, method='hermite') targxyz = np.array(refElp.LLH(target[0], target[1], target[2]).ecef().tolist()) mxyz = np.array(referenceSV.getPosition()) mvel = np.array(referenceSV.getVelocity()) sxyz = np.array(secondarySV.getPosition()) #to fix abrupt change near zero in baseline grid. JUN-05-2020 mvelunit = mvel / np.linalg.norm(mvel) sxyz = sxyz - np.dot ( sxyz-mxyz, mvelunit) * mvelunit aa = np.linalg.norm(sxyz-mxyz) costheta = (x[1]*x[1] + aa*aa - slvrng*slvrng)/(2.*x[1]*aa) Bpar.append(aa*costheta) perp = aa * np.sqrt(1 - costheta*costheta) direction = np.sign(np.dot( np.cross(targxyz-mxyz, sxyz-mxyz), mvel)) Bperp.append(direction*perp) catalog.addItem('parallel baseline at upperleft of reference track', Bpar[0], 'runPreprocessor') catalog.addItem('parallel baseline at upperright of reference track', Bpar[1], 'runPreprocessor') catalog.addItem('parallel baseline at lowerleft of reference track', Bpar[2], 'runPreprocessor') catalog.addItem('parallel baseline at lowerright of reference track', Bpar[3], 'runPreprocessor') catalog.addItem('parallel baseline at center of reference track', Bpar[4], 'runPreprocessor') catalog.addItem('perpendicular baseline at upperleft of reference track', Bperp[0], 'runPreprocessor') catalog.addItem('perpendicular baseline at upperright of reference track', Bperp[1], 'runPreprocessor') catalog.addItem('perpendicular baseline at lowerleft of reference track', Bperp[2], 'runPreprocessor') catalog.addItem('perpendicular baseline at lowerright of reference track', Bperp[3], 'runPreprocessor') catalog.addItem('perpendicular baseline at center of reference track', Bperp[4], 'runPreprocessor') ################################################## #4. compute bounding box ################################################## referenceBbox = getBboxGeo(self.reference.track) secondaryBbox = getBboxGeo(self.secondary.track) catalog.addItem('reference bounding box', referenceBbox, 'runPreprocessor') catalog.addItem('secondary bounding box', secondaryBbox, 'runPreprocessor') catalog.printToLog(logger, "runPreprocessor") self._insar.procDoc.addAllFromCatalog(catalog)