def run(frame1, frame2, orbit1, orbit2, formSlc1, formSlc2, imSlc1, imSlc2, infos, catalog=None, sceneid='NO_ID'): logger.info("Calculate offset between slcs using ampcor: %s" % sceneid) prf1 = frame1.getInstrument().getPulseRepetitionFrequency() prf2 = frame2.getInstrument().getPulseRepetitionFrequency() nearRange1 = formSlc1.startingRange nearRange2 = formSlc2.startingRange fs1 = frame1.getInstrument().getRangeSamplingRate() ###There seems to be no other way of determining image length - Piyush patchSize = infos['patchSize'] numPatches = infos['numberPatches'] valid_az_samples = infos['numberValidPulses'] firstAc = infos['firstSampleAcrossPrf'] firstDown = infos['firstSampleDownPrf'] numLocationAcross = infos['numberLocationAcrossPrf'] numLocationDown = infos['numberLocationDownPrf'] widthSlc = imSlc1.getWidth() coarseRange = (nearRange1 - nearRange2) / (CN.SPEED_OF_LIGHT / (2 * fs1)) coarseAcross = int(coarseRange + 0.5) if (coarseRange <= 0): coarseAcross = int(coarseRange - 0.5) grossRg = infos['grossRg'] print("gross Rg: ", grossRg) if grossRg is not None: coarseAcross = grossRg time1, schPosition1, schVelocity1, offset1 = orbit1._unpackOrbit() time2, schPosition2, schVelocity2, offset2 = orbit2._unpackOrbit() s1 = schPosition1[0][0] s1_2 = schPosition1[1][0] s2 = schPosition2[0][0] s2_2 = schPosition2[1][0] coarseAz = int((s1 - s2) / (s2_2 - s2) + prf1 * (1 / prf1 - 1 / prf2) * (patchSize - valid_az_samples) / 2) coarseDown = int(coarseAz + 0.5) if (coarseAz <= 0): coarseDown = int(coarseAz - 0.5) grossAz = infos['grossAz'] print("gross Az: ", grossAz) if grossAz is not None: coarseDown = grossAz coarseAcross = 0 + coarseAcross coarseDown = 0 + coarseDown logger.debug("Gross Across: %s" % (coarseAcross)) logger.debug("Gross Down: %s" % (coarseDown)) offAc = max(firstAc, coarseAcross) offDn = max(firstDown, coarseDown) lastAc = widthSlc - offAc lastDown = (numPatches * valid_az_samples) - offDn mSlc = isceobj.createSlcImage() IU.copyAttributes(imSlc1, mSlc) accessMode = 'read' mSlc.setAccessMode(accessMode) mSlc.createImage() sSlc = isceobj.createSlcImage() IU.copyAttributes(imSlc2, sSlc) accessMode = 'read' sSlc.setAccessMode(accessMode) sSlc.createImage() objAmpcor = Ampcor() objAmpcor.setImageDataType1('complex') objAmpcor.setImageDataType2('complex') objAmpcor.setFirstSampleAcross(offAc) objAmpcor.setLastSampleAcross(lastAc) objAmpcor.setNumberLocationAcross(numLocationAcross) objAmpcor.setFirstSampleDown(offDn) objAmpcor.setLastSampleDown(lastDown) objAmpcor.setNumberLocationDown(numLocationDown) objAmpcor.setAcrossGrossOffset(coarseAcross) objAmpcor.setDownGrossOffset(coarseDown) objAmpcor.setFirstPRF(prf1) objAmpcor.setSecondPRF(prf2) if catalog is not None: # Record the inputs isceobj.Catalog.recordInputs(catalog, objAmpcor, "runOffsetprf.%s" % sceneid, logger, "runOffsetprf.%s" % sceneid) objAmpcor.ampcor(mSlc, sSlc) if catalog is not None: # Record the outputs isceobj.Catalog.recordOutputs(catalog, objAmpcor, "runOffsetprf.%s" % sceneid, logger, "runOffsetprf.%s" % sceneid) mSlc.finalizeImage() sSlc.finalizeImage() return objAmpcor.getOffsetField()
def estimateOffsetField(reference, secondary, azoffset=0, rgoffset=0): ''' Estimate offset field between burst and simamp. ''' sim = isceobj.createSlcImage() sim.load(secondary + '.xml') sim.setAccessMode('READ') sim.createImage() sar = isceobj.createSlcImage() sar.load(reference + '.xml') sar.setAccessMode('READ') sar.createImage() width = sar.getWidth() length = sar.getLength() objOffset = Ampcor(name='reference_offset1') objOffset.configure() objOffset.setAcrossGrossOffset(rgoffset) objOffset.setDownGrossOffset(azoffset) objOffset.setWindowSizeWidth(128) objOffset.setWindowSizeHeight(128) objOffset.setSearchWindowSizeWidth(40) objOffset.setSearchWindowSizeHeight(40) margin = 2 * objOffset.searchWindowSizeWidth + objOffset.windowSizeWidth nAcross = 60 nDown = 60 offAc = max(101, -rgoffset) + margin offDn = max(101, -azoffset) + margin lastAc = int(min(width, sim.getWidth() - offAc) - margin) lastDn = int(min(length, sim.getLength() - offDn) - margin) if not objOffset.firstSampleAcross: objOffset.setFirstSampleAcross(offAc) if not objOffset.lastSampleAcross: objOffset.setLastSampleAcross(lastAc) if not objOffset.firstSampleDown: objOffset.setFirstSampleDown(offDn) if not objOffset.lastSampleDown: objOffset.setLastSampleDown(lastDn) if not objOffset.numberLocationAcross: objOffset.setNumberLocationAcross(nAcross) if not objOffset.numberLocationDown: objOffset.setNumberLocationDown(nDown) objOffset.setFirstPRF(1.0) objOffset.setSecondPRF(1.0) objOffset.setImageDataType1('complex') objOffset.setImageDataType2('complex') objOffset.ampcor(sar, sim) sar.finalizeImage() sim.finalizeImage() result = objOffset.getOffsetField() return result
#2. The following not set #in roi_pac the value is set to 0 1 #in isce the value is set to 0.001 1000.0 #SNR and Covariance Thresholds (-) = {s1} {s2} #should add the following in Ampcor? #THIS SHOULD BE THE ONLY THING THAT IS DIFFERENT FROM THAT OF ROI_PAC #ampcor.setThresholdSNR(0) #ampcor.setThresholdCov(1) ampcor.setDebugFlag(False) ampcor.setDisplayFlag(False) #in summary, only two things not set which are indicated by 'The following not set' above. #run ampcor ampcor.ampcor() offsets = ampcor.getOffsetField() ampcorOffsetFile = os.path.join(secondaryDir, 'ampcor.off') writeOffset(offsets, ampcorOffsetFile) #finalize image, and re-create it #otherwise the file pointer is still at the end of the image mSLC.finalizeImage() sSLC.finalizeImage() ########################################## #3. cull offsets ########################################## refinedOffsets = cullOffsets(offsets) if refinedOffsets == None: print( '******************************************************************'
def runSlcOffset(self): '''estimate SLC offsets ''' if hasattr(self, 'doInSAR'): if not self.doInSAR: print('\nInSAR processing not requested, skip this and the remaining InSAR steps...') 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.dem) wbdFile = os.path.abspath(self._insar.wbd) for i, frameNumber in enumerate(self._insar.referenceFrames): frameDir = 'f{}_{}'.format(i+1, frameNumber) os.chdir(frameDir) for j, swathNumber in enumerate(range(self._insar.startingSwath, self._insar.endingSwath + 1)): swathDir = 's{}'.format(swathNumber) os.chdir(swathDir) print('estimating offset frame {}, swath {}'.format(frameNumber, swathNumber)) referenceSwath = referenceTrack.frames[i].swaths[j] secondarySwath = secondaryTrack.frames[i].swaths[j] ########################################## #1. set number of matching points ########################################## #set initinial numbers if (self._insar.modeCombination == 21) or (self._insar.modeCombination == 22): numberOfOffsetsRange = 10 numberOfOffsetsAzimuth = 40 else: numberOfOffsetsRange = 20 numberOfOffsetsAzimuth = 20 #change the initial numbers using water body if self.useWbdForNumberOffsets and (self._insar.wbd != None): numberRangeLooks=100 numberAzimuthLooks=100 #compute land ratio using topo module topo(referenceSwath, referenceTrack, demFile, 'lat.rdr', 'lon.rdr', 'hgt.rdr', losFile='los.rdr', incFile=None, mskFile=None, numberRangeLooks=numberRangeLooks, numberAzimuthLooks=numberAzimuthLooks, multilookTimeOffset=False) waterBodyRadar('lat.rdr', 'lon.rdr', wbdFile, 'wbd.rdr') wbdImg = isceobj.createImage() wbdImg.load('wbd.rdr.xml') width = wbdImg.width length = wbdImg.length wbd = np.fromfile('wbd.rdr', dtype=np.byte).reshape(length, width) landRatio = np.sum(wbd==0) / (length*width) if (landRatio <= 0.00125): print('\n\nWARNING: land too small for estimating slc offsets at frame {}, swath {}'.format(frameNumber, swathNumber)) print('proceed to use geometric offsets for forming interferogram') print('but please consider not using this swath\n\n') catalog.addItem('warning message', 'land too small for estimating slc offsets at frame {}, swath {}, use geometric offsets'.format(frameNumber, swathNumber), 'runSlcOffset') #compute geomtricla offsets geo2rdr(secondarySwath, secondaryTrack, 'lat.rdr', 'lon.rdr', 'hgt.rdr', 'rg.rdr', 'az.rdr', numberRangeLooks=numberRangeLooks, numberAzimuthLooks=numberAzimuthLooks, multilookTimeOffset=False) reformatGeometricalOffset('rg.rdr', 'az.rdr', 'cull.off', rangeStep=numberRangeLooks, azimuthStep=numberAzimuthLooks, maximumNumberOfOffsets=2000) os.remove('lat.rdr') os.remove('lat.rdr.vrt') os.remove('lat.rdr.xml') os.remove('lon.rdr') os.remove('lon.rdr.vrt') os.remove('lon.rdr.xml') os.remove('hgt.rdr') os.remove('hgt.rdr.vrt') os.remove('hgt.rdr.xml') os.remove('los.rdr') os.remove('los.rdr.vrt') os.remove('los.rdr.xml') os.remove('wbd.rdr') os.remove('wbd.rdr.vrt') os.remove('wbd.rdr.xml') os.remove('rg.rdr') os.remove('rg.rdr.vrt') os.remove('rg.rdr.xml') os.remove('az.rdr') os.remove('az.rdr.vrt') os.remove('az.rdr.xml') os.chdir('../') continue os.remove('lat.rdr') os.remove('lat.rdr.vrt') os.remove('lat.rdr.xml') os.remove('lon.rdr') os.remove('lon.rdr.vrt') os.remove('lon.rdr.xml') os.remove('hgt.rdr') os.remove('hgt.rdr.vrt') os.remove('hgt.rdr.xml') os.remove('los.rdr') os.remove('los.rdr.vrt') os.remove('los.rdr.xml') os.remove('wbd.rdr') os.remove('wbd.rdr.vrt') os.remove('wbd.rdr.xml') #put the results on a grid with a specified interval interval = 0.2 axisRatio = int(np.sqrt(landRatio)/interval)*interval + interval if axisRatio > 1: axisRatio = 1 numberOfOffsetsRange = int(numberOfOffsetsRange/axisRatio) numberOfOffsetsAzimuth = int(numberOfOffsetsAzimuth/axisRatio) else: catalog.addItem('warning message', 'no water mask used to determine number of matching points. frame {} swath {}'.format(frameNumber, swathNumber), 'runSlcOffset') #user's settings if self.numberRangeOffsets != None: numberOfOffsetsRange = self.numberRangeOffsets[i][j] if self.numberAzimuthOffsets != None: numberOfOffsetsAzimuth = self.numberAzimuthOffsets[i][j] catalog.addItem('number of offsets range frame {} swath {}'.format(frameNumber, swathNumber), numberOfOffsetsRange, 'runSlcOffset') catalog.addItem('number of offsets azimuth frame {} swath {}'.format(frameNumber, swathNumber), numberOfOffsetsAzimuth, 'runSlcOffset') ########################################## #2. match using ampcor ########################################## ampcor = Ampcor(name='insarapp_slcs_ampcor') ampcor.configure() mSLC = isceobj.createSlcImage() mSLC.load(self._insar.referenceSlc+'.xml') mSLC.setAccessMode('read') mSLC.createImage() sSLC = isceobj.createSlcImage() sSLC.load(self._insar.secondarySlc+'.xml') sSLC.setAccessMode('read') sSLC.createImage() ampcor.setImageDataType1('complex') ampcor.setImageDataType2('complex') ampcor.setReferenceSlcImage(mSLC) ampcor.setSecondarySlcImage(sSLC) #MATCH REGION #compute an offset at image center to use rgoff, azoff = computeOffsetFromOrbit(referenceSwath, referenceTrack, secondarySwath, secondaryTrack, referenceSwath.numberOfSamples * 0.5, referenceSwath.numberOfLines * 0.5) #it seems that we cannot use 0, haven't look into the problem if rgoff == 0: rgoff = 1 if azoff == 0: azoff = 1 firstSample = 1 if rgoff < 0: firstSample = int(35 - rgoff) firstLine = 1 if azoff < 0: firstLine = int(35 - azoff) ampcor.setAcrossGrossOffset(rgoff) ampcor.setDownGrossOffset(azoff) ampcor.setFirstSampleAcross(firstSample) ampcor.setLastSampleAcross(mSLC.width) ampcor.setNumberLocationAcross(numberOfOffsetsRange) ampcor.setFirstSampleDown(firstLine) ampcor.setLastSampleDown(mSLC.length) ampcor.setNumberLocationDown(numberOfOffsetsAzimuth) #MATCH PARAMETERS #full-aperture mode if (self._insar.modeCombination == 21) or \ (self._insar.modeCombination == 22) or \ (self._insar.modeCombination == 31) or \ (self._insar.modeCombination == 32): ampcor.setWindowSizeWidth(64) ampcor.setWindowSizeHeight(512) #note this is the half width/length of search area, number of resulting correlation samples: 32*2+1 ampcor.setSearchWindowSizeWidth(32) ampcor.setSearchWindowSizeHeight(32) #triggering full-aperture mode matching ampcor.setWinsizeFilt(8) ampcor.setOversamplingFactorFilt(64) #regular mode else: ampcor.setWindowSizeWidth(64) ampcor.setWindowSizeHeight(64) ampcor.setSearchWindowSizeWidth(32) ampcor.setSearchWindowSizeHeight(32) #REST OF THE STUFF ampcor.setAcrossLooks(1) ampcor.setDownLooks(1) ampcor.setOversamplingFactor(64) ampcor.setZoomWindowSize(16) #1. The following not set #Matching Scale for Sample/Line Directions (-) = 1. 1. #should add the following in Ampcor.py? #if not set, in this case, Ampcor.py'value is also 1. 1. #ampcor.setScaleFactorX(1.) #ampcor.setScaleFactorY(1.) #MATCH THRESHOLDS AND DEBUG DATA #2. The following not set #in roi_pac the value is set to 0 1 #in isce the value is set to 0.001 1000.0 #SNR and Covariance Thresholds (-) = {s1} {s2} #should add the following in Ampcor? #THIS SHOULD BE THE ONLY THING THAT IS DIFFERENT FROM THAT OF ROI_PAC #ampcor.setThresholdSNR(0) #ampcor.setThresholdCov(1) ampcor.setDebugFlag(False) ampcor.setDisplayFlag(False) #in summary, only two things not set which are indicated by 'The following not set' above. #run ampcor ampcor.ampcor() offsets = ampcor.getOffsetField() ampcorOffsetFile = 'ampcor.off' writeOffset(offsets, ampcorOffsetFile) #finalize image, and re-create it #otherwise the file pointer is still at the end of the image mSLC.finalizeImage() sSLC.finalizeImage() ########################################## #3. cull offsets ########################################## refinedOffsets = cullOffsets(offsets) if refinedOffsets == None: print('******************************************************************') print('WARNING: There are not enough offsets left, so we are forced to') print(' use offset without culling. frame {}, swath {}'.format(frameNumber, swathNumber)) print('******************************************************************') catalog.addItem('warning message', 'not enough offsets left, use offset without culling. frame {} swath {}'.format(frameNumber, swathNumber), 'runSlcOffset') refinedOffsets = offsets cullOffsetFile = 'cull.off' writeOffset(refinedOffsets, cullOffsetFile) os.chdir('../') os.chdir('../') catalog.printToLog(logger, "runSlcOffset") self._insar.procDoc.addAllFromCatalog(catalog)
def runAmpcor(master, slave): ''' Run one ampcor process. ''' import isceobj from mroipac.ampcor.Ampcor import Ampcor mImg = isceobj.createSlcImage() mImg.load(master + '.xml') mImg.setAccessMode('READ') mImg.createImage() sImg = isceobj.createSlcImage() sImg.load(slave + '.xml') sImg.setAccessMode('READ') sImg.createImage() objAmpcor = Ampcor('ampcor_burst') objAmpcor.configure() objAmpcor.setImageDataType1('mag') objAmpcor.setImageDataType2('mag') if objAmpcor.acrossGrossOffset is None: coarseAcross = 0 if objAmpcor.downGrossOffset is None: coarseDown = 0 objAmpcor.windowSizeWidth = 64 objAmpcor.windowSizeHeight = 32 objAmpcor.searchWindowSizeWidth = 16 objAmpcor.searchWindowSizeHeight = 16 objAmpcor.oversamplingFactor = 32 xMargin = 2 * objAmpcor.searchWindowSizeWidth + objAmpcor.windowSizeWidth yMargin = 2 * objAmpcor.searchWindowSizeHeight + objAmpcor.windowSizeHeight firstAc = 1000 #####Compute image positions offDn = objAmpcor.windowSizeHeight // 2 + 1 offAc = firstAc + xMargin offDnmax = mImg.getLength() - objAmpcor.windowSizeHeight // 2 - 1 lastAc = int(mImg.width - 1000 - xMargin) if not objAmpcor.firstSampleAcross: objAmpcor.setFirstSampleAcross(offAc) if not objAmpcor.lastSampleAcross: objAmpcor.setLastSampleAcross(lastAc) if not objAmpcor.numberLocationAcross: objAmpcor.setNumberLocationAcross(80) if not objAmpcor.firstSampleDown: objAmpcor.setFirstSampleDown(offDn) if not objAmpcor.lastSampleDown: objAmpcor.setLastSampleDown(offDnmax) ###Since we are only dealing with overlaps objAmpcor.setNumberLocationDown(20) #####Override gross offsets if not provided if not objAmpcor.acrossGrossOffset: objAmpcor.setAcrossGrossOffset(coarseAcross) if not objAmpcor.downGrossOffset: objAmpcor.setDownGrossOffset(coarseDown) objAmpcor.setImageDataType1('mag') objAmpcor.setImageDataType2('mag') objAmpcor.setFirstPRF(1.0) objAmpcor.setSecondPRF(1.0) objAmpcor.setFirstRangeSpacing(1.0) objAmpcor.setSecondRangeSpacing(1.0) objAmpcor(mImg, sImg) mImg.finalizeImage() sImg.finalizeImage() return objAmpcor.getOffsetField()
#in isce the value is set to 0.001 1000.0 #SNR and Covariance Thresholds (-) = {s1} {s2} #should add the following in Ampcor? #THIS SHOULD BE THE ONLY THING THAT IS DIFFERENT FROM THAT OF ROI_PAC #objAmpcor.setThresholdSNR(0) #objAmpcor.setThresholdCov(1) objAmpcor.setDebugFlag(False) objAmpcor.setDisplayFlag(False) #in summary, only two things not set which are indicated by 'The following not set' above. #run ampcor objAmpcor.ampcor() #get offsets offsets = objAmpcor.getOffsetField() offsetsPlain = '' for offsetx in offsets: offsetsPlainx = "{}".format(offsetx) offsetsPlainx = offsetsPlainx.split() offsetsPlain = offsetsPlain + "{:8d} {:10.3f} {:8d} {:12.3f} {:11.5f} {:11.6f} {:11.6f} {:11.6f}\n".format( int(offsetsPlainx[0]), float(offsetsPlainx[1]), int(offsetsPlainx[2]), float(offsetsPlainx[3]), float(offsetsPlainx[4]), float(offsetsPlainx[5]), float(offsetsPlainx[6]), float(offsetsPlainx[7])) with open(offsetFile, 'w') as f: f.write(offsetsPlain) #############################################################################################################
def runCoregCc(self): '''coregister bursts by cross correlation ''' catalog = isceobj.Catalog.createCatalog(self._insar.procDoc.name) self.updateParamemetersFromUser() masterTrack = self._insar.loadTrack(master=True) slaveTrack = self._insar.loadTrack(master=False) #demFile = os.path.abspath(self._insar.dem) #wbdFile = os.path.abspath(self._insar.wbd) ############################################################################### self._insar.rangeResidualOffsetCc = [ [] for i in range(len(masterTrack.frames)) ] self._insar.azimuthResidualOffsetCc = [ [] for i in range(len(masterTrack.frames)) ] for i, frameNumber in enumerate(self._insar.masterFrames): frameDir = 'f{}_{}'.format(i + 1, frameNumber) os.chdir(frameDir) for j, swathNumber in enumerate( range(self._insar.startingSwath, self._insar.endingSwath + 1)): swathDir = 's{}'.format(swathNumber) os.chdir(swathDir) print('processing frame {}, swath {}'.format( frameNumber, swathNumber)) masterSwath = masterTrack.frames[i].swaths[j] slaveSwath = slaveTrack.frames[i].swaths[j] ################################################## # estimate cross-correlation offsets ################################################## #compute number of offsets to use wbdImg = isceobj.createImage() wbdImg.load(self._insar.wbdOut + '.xml') width = wbdImg.width length = wbdImg.length #initial number of offsets to use numberOfOffsets = 800 #compute land ratio to further determine the number of offsets to use if self.useWbdForNumberOffsets: wbd = np.memmap(self._insar.wbdOut, dtype='byte', mode='r', shape=(length, width)) landRatio = np.sum(wbd == 0) / length / width del wbd if (landRatio <= 0.00125): print( '\n\nWARNING: land area too small for estimating offsets between master and slave magnitudes at frame {}, swath {}' .format(frameNumber, swathNumber)) print('set offsets to zero\n\n') self._insar.rangeResidualOffsetCc[i].append(0.0) self._insar.azimuthResidualOffsetCc[i].append(0.0) catalog.addItem( 'warning message', 'land area too small for estimating offsets between master and slave magnitudes at frame {}, swath {}' .format(frameNumber, swathNumber), 'runCoregCc') continue #total number of offsets to use numberOfOffsets /= landRatio #allocate number of offsets in range/azimuth according to image width/length #number of offsets to use in range/azimuth numberOfOffsetsRange = int( np.sqrt(numberOfOffsets * width / length)) numberOfOffsetsAzimuth = int( length / width * np.sqrt(numberOfOffsets * width / length)) #this should be better? numberOfOffsetsRange = int(np.sqrt(numberOfOffsets)) numberOfOffsetsAzimuth = int(np.sqrt(numberOfOffsets)) if numberOfOffsetsRange > int(width / 2): numberOfOffsetsRange = int(width / 2) if numberOfOffsetsAzimuth > int(length / 2): numberOfOffsetsAzimuth = int(length / 2) if numberOfOffsetsRange < 10: numberOfOffsetsRange = 10 if numberOfOffsetsAzimuth < 10: numberOfOffsetsAzimuth = 10 #user's settings if self.numberRangeOffsets != None: numberOfOffsetsRange = self.numberRangeOffsets[i][j] if self.numberAzimuthOffsets != None: numberOfOffsetsAzimuth = self.numberAzimuthOffsets[i][j] catalog.addItem( 'number of range offsets at frame {}, swath {}'.format( frameNumber, swathNumber), '{}'.format(numberOfOffsetsRange), 'runCoregCc') catalog.addItem( 'number of azimuth offsets at frame {}, swath {}'.format( frameNumber, swathNumber), '{}'.format(numberOfOffsetsAzimuth), 'runCoregCc') #need to cp to current directory to make it (gdal) work if not os.path.isfile(self._insar.masterMagnitude): os.symlink( os.path.join(self._insar.masterBurstPrefix, self._insar.masterMagnitude), self._insar.masterMagnitude) #shutil.copy2() can overwrite shutil.copy2( os.path.join(self._insar.masterBurstPrefix, self._insar.masterMagnitude + '.vrt'), self._insar.masterMagnitude + '.vrt') shutil.copy2( os.path.join(self._insar.masterBurstPrefix, self._insar.masterMagnitude + '.xml'), self._insar.masterMagnitude + '.xml') if not os.path.isfile(self._insar.slaveMagnitude): os.symlink( os.path.join( self._insar.slaveBurstPrefix + '_1_coreg_geom', self._insar.slaveMagnitude), self._insar.slaveMagnitude) #shutil.copy2() can overwrite shutil.copy2( os.path.join(self._insar.slaveBurstPrefix + '_1_coreg_geom', self._insar.slaveMagnitude + '.vrt'), self._insar.slaveMagnitude + '.vrt') shutil.copy2( os.path.join(self._insar.slaveBurstPrefix + '_1_coreg_geom', self._insar.slaveMagnitude + '.xml'), self._insar.slaveMagnitude + '.xml') #matching ampcor = Ampcor(name='insarapp_slcs_ampcor') ampcor.configure() mMag = isceobj.createImage() mMag.load(self._insar.masterMagnitude + '.xml') mMag.setAccessMode('read') mMag.createImage() sMag = isceobj.createImage() sMag.load(self._insar.slaveMagnitude + '.xml') sMag.setAccessMode('read') sMag.createImage() ampcor.setImageDataType1('real') ampcor.setImageDataType2('real') ampcor.setMasterSlcImage(mMag) ampcor.setSlaveSlcImage(sMag) #MATCH REGION rgoff = 0 azoff = 0 #it seems that we cannot use 0, haven't look into the problem if rgoff == 0: rgoff = 1 if azoff == 0: azoff = 1 firstSample = 1 if rgoff < 0: firstSample = int(35 - rgoff) firstLine = 1 if azoff < 0: firstLine = int(35 - azoff) ampcor.setAcrossGrossOffset(rgoff) ampcor.setDownGrossOffset(azoff) ampcor.setFirstSampleAcross(firstSample) ampcor.setLastSampleAcross(mMag.width) ampcor.setNumberLocationAcross(numberOfOffsetsRange) ampcor.setFirstSampleDown(firstLine) ampcor.setLastSampleDown(mMag.length) ampcor.setNumberLocationDown(numberOfOffsetsAzimuth) #MATCH PARAMETERS ampcor.setWindowSizeWidth(64) ampcor.setWindowSizeHeight(64) #note this is the half width/length of search area, so number of resulting correlation samples: 8*2+1 ampcor.setSearchWindowSizeWidth(8) ampcor.setSearchWindowSizeHeight(8) #REST OF THE STUFF ampcor.setAcrossLooks(1) ampcor.setDownLooks(1) ampcor.setOversamplingFactor(64) ampcor.setZoomWindowSize(16) #1. The following not set #Matching Scale for Sample/Line Directions (-) = 1. 1. #should add the following in Ampcor.py? #if not set, in this case, Ampcor.py'value is also 1. 1. #ampcor.setScaleFactorX(1.) #ampcor.setScaleFactorY(1.) #MATCH THRESHOLDS AND DEBUG DATA #2. The following not set #in roi_pac the value is set to 0 1 #in isce the value is set to 0.001 1000.0 #SNR and Covariance Thresholds (-) = {s1} {s2} #should add the following in Ampcor? #THIS SHOULD BE THE ONLY THING THAT IS DIFFERENT FROM THAT OF ROI_PAC #ampcor.setThresholdSNR(0) #ampcor.setThresholdCov(1) ampcor.setDebugFlag(False) ampcor.setDisplayFlag(False) #in summary, only two things not set which are indicated by 'The following not set' above. #run ampcor ampcor.ampcor() offsets = ampcor.getOffsetField() refinedOffsets = cullOffsetsRoipac(offsets, numThreshold=50) #finalize image, and re-create it #otherwise the file pointer is still at the end of the image mMag.finalizeImage() sMag.finalizeImage() #clear up os.remove(self._insar.masterMagnitude) os.remove(self._insar.masterMagnitude + '.vrt') os.remove(self._insar.masterMagnitude + '.xml') os.remove(self._insar.slaveMagnitude) os.remove(self._insar.slaveMagnitude + '.vrt') os.remove(self._insar.slaveMagnitude + '.xml') #compute average offsets to use in resampling if refinedOffsets == None: rangeOffset = 0 azimuthOffset = 0 self._insar.rangeResidualOffsetCc[i].append(rangeOffset) self._insar.azimuthResidualOffsetCc[i].append(azimuthOffset) print( '\n\nWARNING: too few offsets left in matching master and slave magnitudes at frame {}, swath {}' .format(frameNumber, swathNumber)) print('set offsets to zero\n\n') catalog.addItem( 'warning message', 'too few offsets left in matching master and slave magnitudes at frame {}, swath {}' .format(frameNumber, swathNumber), 'runCoregCc') else: rangeOffset, azimuthOffset = meanOffset(refinedOffsets) #for range offset, need to compute from a polynomial #see components/isceobj/Location/Offset.py and components/isceobj/Util/Library/python/Poly2D.py for definations (azimuthPoly, rangePoly) = refinedOffsets.getFitPolynomials(rangeOrder=2, azimuthOrder=2) #make a deep copy, otherwise it also changes original coefficient list of rangePoly, which affects following rangePoly(*, *) computation polyCoeff = copy.deepcopy(rangePoly.getCoeffs()) rgIndex = (np.arange(width) - rangePoly.getMeanRange() ) / rangePoly.getNormRange() azIndex = (np.arange(length) - rangePoly.getMeanAzimuth() ) / rangePoly.getNormAzimuth() rangeOffset = polyCoeff[0][0] + polyCoeff[0][1]*rgIndex[None,:] + polyCoeff[0][2]*rgIndex[None,:]**2 + \ (polyCoeff[1][0] + polyCoeff[1][1]*rgIndex[None,:]) * azIndex[:, None] + \ polyCoeff[2][0] * azIndex[:, None]**2 polyCoeff.append([ rangePoly.getMeanRange(), rangePoly.getNormRange(), rangePoly.getMeanAzimuth(), rangePoly.getNormAzimuth() ]) self._insar.rangeResidualOffsetCc[i].append(polyCoeff) self._insar.azimuthResidualOffsetCc[i].append(azimuthOffset) catalog.addItem( 'range residual offset at {} {} at frame {}, swath {}'. format(0, 0, frameNumber, swathNumber), '{}'.format(rangePoly(0, 0)), 'runCoregCc') catalog.addItem( 'range residual offset at {} {} at frame {}, swath {}'. format(0, width - 1, frameNumber, swathNumber), '{}'.format(rangePoly(0, width - 1)), 'runCoregCc') catalog.addItem( 'range residual offset at {} {} at frame {}, swath {}'. format(length - 1, 0, frameNumber, swathNumber), '{}'.format(rangePoly(length - 1, 0)), 'runCoregCc') catalog.addItem( 'range residual offset at {} {} at frame {}, swath {}'. format(length - 1, width - 1, frameNumber, swathNumber), '{}'.format(rangePoly(length - 1, width - 1)), 'runCoregCc') catalog.addItem( 'azimuth residual offset at frame {}, swath {}'.format( frameNumber, swathNumber), '{}'.format(azimuthOffset), 'runCoregCc') DEBUG = False if DEBUG: print('+++++++++++++++++++++++++++++') print(rangeOffset[0, 0], rangePoly(0, 0)) print(rangeOffset[0, width - 1], rangePoly(0, width - 1)) print(rangeOffset[length - 1, 0], rangePoly(length - 1, 0)) print(rangeOffset[length - 1, width - 1], rangePoly(length - 1, width - 1)) print( rangeOffset[int((length - 1) / 2), int((width - 1) / 2)], rangePoly(int((length - 1) / 2), int((width - 1) / 2))) print('+++++++++++++++++++++++++++++') ################################################## # resample bursts ################################################## slaveBurstResampledDir = self._insar.slaveBurstPrefix + '_2_coreg_cc' #interferogramDir = self._insar.masterBurstPrefix + '-' + self._insar.slaveBurstPrefix + '_coreg_geom' interferogramDir = 'burst_interf_2_coreg_cc' interferogramPrefix = self._insar.masterBurstPrefix + '-' + self._insar.slaveBurstPrefix resampleBursts(masterSwath, slaveSwath, self._insar.masterBurstPrefix, self._insar.slaveBurstPrefix, slaveBurstResampledDir, interferogramDir, self._insar.masterBurstPrefix, self._insar.slaveBurstPrefix, self._insar.slaveBurstPrefix, interferogramPrefix, self._insar.rangeOffset, self._insar.azimuthOffset, rangeOffsetResidual=rangeOffset, azimuthOffsetResidual=azimuthOffset) ################################################## # mosaic burst amplitudes and interferograms ################################################## os.chdir(slaveBurstResampledDir) mosaicBurstAmplitude(masterSwath, self._insar.slaveBurstPrefix, self._insar.slaveMagnitude, numberOfLooksThreshold=4) os.chdir('../') os.chdir(interferogramDir) mosaicBurstInterferogram(masterSwath, interferogramPrefix, self._insar.interferogram, numberOfLooksThreshold=4) os.chdir('../') ################################################## # final amplitude and interferogram ################################################## amp = np.zeros( (masterSwath.numberOfLines, 2 * masterSwath.numberOfSamples), dtype=np.float32) amp[0:, 1:masterSwath.numberOfSamples*2:2] = np.fromfile(os.path.join(slaveBurstResampledDir, self._insar.slaveMagnitude), \ dtype=np.float32).reshape(masterSwath.numberOfLines, masterSwath.numberOfSamples) amp[0:, 0:masterSwath.numberOfSamples*2:2] = np.fromfile(os.path.join(self._insar.masterBurstPrefix, self._insar.masterMagnitude), \ dtype=np.float32).reshape(masterSwath.numberOfLines, masterSwath.numberOfSamples) amp.astype(np.float32).tofile(self._insar.amplitude) create_xml(self._insar.amplitude, masterSwath.numberOfSamples, masterSwath.numberOfLines, 'amp') os.rename( os.path.join(interferogramDir, self._insar.interferogram), self._insar.interferogram) os.rename( os.path.join(interferogramDir, self._insar.interferogram + '.vrt'), self._insar.interferogram + '.vrt') os.rename( os.path.join(interferogramDir, self._insar.interferogram + '.xml'), self._insar.interferogram + '.xml') os.chdir('../') os.chdir('../') ############################################################################### catalog.printToLog(logger, "runCoregCc") self._insar.procDoc.addAllFromCatalog(catalog)
def estimateSwathOffset(swath1, swath2, image1, image2, rangeScale1=1, azimuthScale1=1, rangeScale2=1, azimuthScale2=1, numberOfAzimuthLooks=10): ''' estimate offset of two adjacent swaths using matching ''' from osgeo import gdal import isceobj from contrib.alos2proc_f.alos2proc_f import rect_with_looks from isceobj.Alos2Proc.Alos2ProcPublic import create_xml from isceobj.Alos2Proc.Alos2ProcPublic import cullOffsets from isceobj.Alos2Proc.Alos2ProcPublic import meanOffset from mroipac.ampcor.Ampcor import Ampcor #processing image 1 rangeOff1 = int( (swath2.startingRange - swath1.startingRange) / swath1.rangePixelSize) if rangeOff1 < 0: rangeOff1 = 0 numberOfSamples1 = swath1.numberOfSamples - rangeOff1 numberOfSamplesRect1 = int(numberOfSamples1 / rangeScale1) numberOfLinesRect1 = int(swath1.numberOfLines / azimuthScale1) numberOfSamplesLook1 = int(numberOfSamplesRect1 / 1) numberOfLinesLook1 = int(numberOfLinesRect1 / numberOfAzimuthLooks) #get magnitude image whether complex or not #ReadAsArray: https://pcjericks.github.io/py-gdalogr-cookbook/raster_layers.html ds = gdal.Open(image1 + '.vrt', gdal.GA_ReadOnly) data = ds.ReadAsArray(rangeOff1, 0, numberOfSamples1, swath1.numberOfLines) ds = None (np.absolute(data)).astype(np.float32).tofile('image1.float') #rectify if rangeScale1 == 1 and azimuthScale1 == 1: os.rename('image1.float', 'image1_rect.float') else: rect_with_looks('image1.float', 'image1_rect.float', numberOfSamples1, swath1.numberOfLines, numberOfSamplesRect1, numberOfLinesRect1, rangeScale1, 0.0, 0.0, azimuthScale1, 0.0, 0.0, 1, 1, 1, 1, 'REAL', 'Bilinear') os.remove('image1.float') #take looks if numberOfAzimuthLooks == 1: os.rename('image1_rect.float', 'image1_look.float') else: data1 = np.fromfile('image1_rect.float', dtype=np.float32).reshape(numberOfLinesRect1, numberOfSamplesRect1) data1 = np.sqrt(multilook(data1**2, numberOfAzimuthLooks, 1)) data1.astype(np.float32).tofile('image1_look.float') os.remove('image1_rect.float') create_xml('image1_look.float', numberOfSamplesLook1, numberOfLinesLook1, 'float') #processing image 2 rangeOff2 = 0 numberOfSamples2 = int( (swath1.startingRange + swath1.rangePixelSize * (swath1.numberOfSamples - 1) - swath2.startingRange) / swath2.rangePixelSize) + 1 if numberOfSamples2 > swath2.numberOfSamples: numberOfSamples2 = swath2.numberOfSamples numberOfSamplesRect2 = int(numberOfSamples2 / rangeScale2) numberOfLinesRect2 = int(swath2.numberOfLines / azimuthScale2) numberOfSamplesLook2 = int(numberOfSamplesRect2 / 1) numberOfLinesLook2 = int(numberOfLinesRect2 / numberOfAzimuthLooks) #get magnitude image whether complex or not ds = gdal.Open(image2 + '.vrt', gdal.GA_ReadOnly) data = ds.ReadAsArray(rangeOff2, 0, numberOfSamples2, swath2.numberOfLines) ds = None (np.absolute(data)).astype(np.float32).tofile('image2.float') #rectify if rangeScale2 == 1 and azimuthScale2 == 1: os.rename('image2.float', 'image2_rect.float') else: rect_with_looks('image2.float', 'image2_rect.float', numberOfSamples2, swath2.numberOfLines, numberOfSamplesRect2, numberOfLinesRect2, rangeScale2, 0.0, 0.0, azimuthScale2, 0.0, 0.0, 1, 1, 1, 1, 'REAL', 'Bilinear') os.remove('image2.float') #take looks if numberOfAzimuthLooks == 1: os.rename('image2_rect.float', 'image2_look.float') else: data2 = np.fromfile('image2_rect.float', dtype=np.float32).reshape(numberOfLinesRect2, numberOfSamplesRect2) data2 = np.sqrt(multilook(data2**2, numberOfAzimuthLooks, 1)) data2.astype(np.float32).tofile('image2_look.float') os.remove('image2_rect.float') create_xml('image2_look.float', numberOfSamplesLook2, numberOfLinesLook2, 'float') #matching ampcor = Ampcor(name='insarapp_slcs_ampcor') ampcor.configure() mMag = isceobj.createImage() mMag.load('image1_look.float.xml') mMag.setAccessMode('read') mMag.createImage() sMag = isceobj.createImage() sMag.load('image2_look.float.xml') sMag.setAccessMode('read') sMag.createImage() ampcor.setImageDataType1('real') ampcor.setImageDataType2('real') ampcor.setReferenceSlcImage(mMag) ampcor.setSecondarySlcImage(sMag) #MATCH REGION rgoff = 0 azoff = int( (swath1.sensingStart - swath2.sensingStart).total_seconds() / swath1.azimuthLineInterval / azimuthScale1 / numberOfAzimuthLooks) #it seems that we cannot use 0, haven't look into the problem if rgoff == 0: rgoff = 1 if azoff == 0: azoff = 1 firstSample = 1 if rgoff < 0: firstSample = int(35 - rgoff) firstLine = 1 if azoff < 0: firstLine = int(35 - azoff) ampcor.setAcrossGrossOffset(rgoff) ampcor.setDownGrossOffset(azoff) ampcor.setFirstSampleAcross(firstSample) ampcor.setLastSampleAcross(numberOfSamplesLook1) ampcor.setNumberLocationAcross(20) ampcor.setFirstSampleDown(firstLine) ampcor.setLastSampleDown(numberOfLinesLook1) ampcor.setNumberLocationDown(100) #MATCH PARAMETERS ampcor.setWindowSizeWidth(32) ampcor.setWindowSizeHeight(32) #note this is the half width/length of search area, so number of resulting correlation samples: 8*2+1 ampcor.setSearchWindowSizeWidth(8) ampcor.setSearchWindowSizeHeight(8) #REST OF THE STUFF ampcor.setAcrossLooks(1) ampcor.setDownLooks(1) ampcor.setOversamplingFactor(64) ampcor.setZoomWindowSize(16) #1. The following not set #Matching Scale for Sample/Line Directions (-) = 1. 1. #should add the following in Ampcor.py? #if not set, in this case, Ampcor.py'value is also 1. 1. #ampcor.setScaleFactorX(1.) #ampcor.setScaleFactorY(1.) #MATCH THRESHOLDS AND DEBUG DATA #2. The following not set #in roi_pac the value is set to 0 1 #in isce the value is set to 0.001 1000.0 #SNR and Covariance Thresholds (-) = {s1} {s2} #should add the following in Ampcor? #THIS SHOULD BE THE ONLY THING THAT IS DIFFERENT FROM THAT OF ROI_PAC #ampcor.setThresholdSNR(0) #ampcor.setThresholdCov(1) ampcor.setDebugFlag(False) ampcor.setDisplayFlag(False) #in summary, only two things not set which are indicated by 'The following not set' above. #run ampcor ampcor.ampcor() offsets = ampcor.getOffsetField() refinedOffsets = cullOffsets(offsets) #finalize image, and re-create it #otherwise the file pointer is still at the end of the image mMag.finalizeImage() sMag.finalizeImage() os.remove('image1_look.float') os.remove('image1_look.float.vrt') os.remove('image1_look.float.xml') os.remove('image2_look.float') os.remove('image2_look.float.vrt') os.remove('image2_look.float.xml') if refinedOffsets != None: rangeOffset, azimuthOffset = meanOffset(refinedOffsets) rangeOffset -= rangeOff1 / rangeScale1 azimuthOffset *= numberOfAzimuthLooks return (rangeOffset, azimuthOffset) else: return None
def runRdrDemOffset(self): '''estimate between radar image and dem ''' catalog = isceobj.Catalog.createCatalog(self._insar.procDoc.name) self.updateParamemetersFromUser() referenceTrack = self._insar.loadTrack(reference=True) demFile = os.path.abspath(self._insar.dem) insarDir = 'insar' os.makedirs(insarDir, exist_ok=True) os.chdir(insarDir) rdrDemDir = 'rdr_dem_offset' os.makedirs(rdrDemDir, exist_ok=True) os.chdir(rdrDemDir) ################################################################################################## #compute dem pixel size demImage = isceobj.createDemImage() demImage.load(demFile + '.xml') #DEM pixel size in meters (appoximate value) demDeltaLon = abs(demImage.getDeltaLongitude()) / 0.0002777777777777778 * 30.0 demDeltaLat = abs(demImage.getDeltaLatitude()) / 0.0002777777777777778 * 30.0 #number of looks to take in range if self._insar.numberRangeLooksSim == None: if self._insar.numberRangeLooks1 * referenceTrack.rangePixelSize > demDeltaLon: self._insar.numberRangeLooksSim = 1 else: self._insar.numberRangeLooksSim = int(demDeltaLon / (self._insar.numberRangeLooks1 * referenceTrack.rangePixelSize) + 0.5) #number of looks to take in azimuth if self._insar.numberAzimuthLooksSim == None: if self._insar.numberAzimuthLooks1 * referenceTrack.azimuthPixelSize > demDeltaLat: self._insar.numberAzimuthLooksSim = 1 else: self._insar.numberAzimuthLooksSim = int(demDeltaLat / (self._insar.numberAzimuthLooks1 * referenceTrack.azimuthPixelSize) + 0.5) #simulate a radar image using dem simulateRadar(os.path.join('../', self._insar.height), self._insar.sim, scale=3.0, offset=100.0) sim = isceobj.createImage() sim.load(self._insar.sim+'.xml') #take looks if (self._insar.numberRangeLooksSim == 1) and (self._insar.numberAzimuthLooksSim == 1): simLookFile = self._insar.sim ampLookFile = 'amp_{}rlks_{}alks.float'.format(self._insar.numberRangeLooksSim*self._insar.numberRangeLooks1, self._insar.numberAzimuthLooksSim*self._insar.numberAzimuthLooks1) cmd = "imageMath.py -e='sqrt(a_0*a_0+a_1*a_1)' --a={} -o {} -t float".format(os.path.join('../', self._insar.amplitude), ampLookFile) runCmd(cmd) else: simLookFile = 'sim_{}rlks_{}alks.float'.format(self._insar.numberRangeLooksSim*self._insar.numberRangeLooks1, self._insar.numberAzimuthLooksSim*self._insar.numberAzimuthLooks1) ampLookFile = 'amp_{}rlks_{}alks.float'.format(self._insar.numberRangeLooksSim*self._insar.numberRangeLooks1, self._insar.numberAzimuthLooksSim*self._insar.numberAzimuthLooks1) ampTmpFile = 'amp_tmp.float' look(self._insar.sim, simLookFile, sim.width, self._insar.numberRangeLooksSim, self._insar.numberAzimuthLooksSim, 2, 0, 1) look(os.path.join('../', self._insar.amplitude), ampTmpFile, sim.width, self._insar.numberRangeLooksSim, self._insar.numberAzimuthLooksSim, 4, 1, 1) width = int(sim.width/self._insar.numberRangeLooksSim) length = int(sim.length/self._insar.numberAzimuthLooksSim) create_xml(simLookFile, width, length, 'float') create_xml(ampTmpFile, width, length, 'amp') cmd = "imageMath.py -e='sqrt(a_0*a_0+a_1*a_1)' --a={} -o {} -t float".format(ampTmpFile, ampLookFile) runCmd(cmd) os.remove(ampTmpFile) os.remove(ampTmpFile+'.vrt') os.remove(ampTmpFile+'.xml') #initial number of offsets to use numberOfOffsets = 800 #compute land ratio to further determine the number of offsets to use wbd=np.memmap(os.path.join('../', self._insar.wbdOut), dtype='byte', mode='r', shape=(sim.length, sim.width)) landRatio = np.sum(wbd[0:sim.length:10, 0:sim.width:10]!=-1) / int(sim.length/10) / int(sim.width/10) del wbd if (landRatio <= 0.00125): print('\n\nWARNING: land area too small for estimating offsets between radar and dem') print('do not estimate offsets between radar and dem\n\n') self._insar.radarDemAffineTransform = [1.0, 0.0, 0.0, 1.0, 0.0, 0.0] catalog.addItem('warning message', 'land area too small for estimating offsets between radar and dem', 'runRdrDemOffset') os.chdir('../../') catalog.printToLog(logger, "runRdrDemOffset") self._insar.procDoc.addAllFromCatalog(catalog) return #total number of offsets to use numberOfOffsets /= landRatio #allocate number of offsets in range/azimuth according to image width/length width = int(sim.width/self._insar.numberRangeLooksSim) length = int(sim.length/self._insar.numberAzimuthLooksSim) #number of offsets to use in range/azimuth numberOfOffsetsRange = int(np.sqrt(numberOfOffsets * width / length)) numberOfOffsetsAzimuth = int(length / width * np.sqrt(numberOfOffsets * width / length)) #this should be better? numberOfOffsetsRange = int(np.sqrt(numberOfOffsets)) numberOfOffsetsAzimuth = int(np.sqrt(numberOfOffsets)) if numberOfOffsetsRange > int(width/2): numberOfOffsetsRange = int(width/2) if numberOfOffsetsAzimuth > int(length/2): numberOfOffsetsAzimuth = int(length/2) if numberOfOffsetsRange < 10: numberOfOffsetsRange = 10 if numberOfOffsetsAzimuth < 10: numberOfOffsetsAzimuth = 10 catalog.addItem('number of range offsets', '{}'.format(numberOfOffsetsRange), 'runRdrDemOffset') catalog.addItem('number of azimuth offsets', '{}'.format(numberOfOffsetsAzimuth), 'runRdrDemOffset') #matching ampcor = Ampcor(name='insarapp_slcs_ampcor') ampcor.configure() mMag = isceobj.createImage() mMag.load(ampLookFile+'.xml') mMag.setAccessMode('read') mMag.createImage() sMag = isceobj.createImage() sMag.load(simLookFile+'.xml') sMag.setAccessMode('read') sMag.createImage() ampcor.setImageDataType1('real') ampcor.setImageDataType2('real') ampcor.setReferenceSlcImage(mMag) ampcor.setSecondarySlcImage(sMag) #MATCH REGION rgoff = 0 azoff = 0 #it seems that we cannot use 0, haven't look into the problem if rgoff == 0: rgoff = 1 if azoff == 0: azoff = 1 firstSample = 1 if rgoff < 0: firstSample = int(35 - rgoff) firstLine = 1 if azoff < 0: firstLine = int(35 - azoff) ampcor.setAcrossGrossOffset(rgoff) ampcor.setDownGrossOffset(azoff) ampcor.setFirstSampleAcross(firstSample) ampcor.setLastSampleAcross(width) ampcor.setNumberLocationAcross(numberOfOffsetsRange) ampcor.setFirstSampleDown(firstLine) ampcor.setLastSampleDown(length) ampcor.setNumberLocationDown(numberOfOffsetsAzimuth) #MATCH PARAMETERS ampcor.setWindowSizeWidth(64) ampcor.setWindowSizeHeight(64) #note this is the half width/length of search area, so number of resulting correlation samples: 8*2+1 ampcor.setSearchWindowSizeWidth(16) ampcor.setSearchWindowSizeHeight(16) #REST OF THE STUFF ampcor.setAcrossLooks(1) ampcor.setDownLooks(1) ampcor.setOversamplingFactor(64) ampcor.setZoomWindowSize(16) #1. The following not set #Matching Scale for Sample/Line Directions (-) = 1. 1. #should add the following in Ampcor.py? #if not set, in this case, Ampcor.py'value is also 1. 1. #ampcor.setScaleFactorX(1.) #ampcor.setScaleFactorY(1.) #MATCH THRESHOLDS AND DEBUG DATA #2. The following not set #in roi_pac the value is set to 0 1 #in isce the value is set to 0.001 1000.0 #SNR and Covariance Thresholds (-) = {s1} {s2} #should add the following in Ampcor? #THIS SHOULD BE THE ONLY THING THAT IS DIFFERENT FROM THAT OF ROI_PAC #ampcor.setThresholdSNR(0) #ampcor.setThresholdCov(1) ampcor.setDebugFlag(False) ampcor.setDisplayFlag(False) #in summary, only two things not set which are indicated by 'The following not set' above. #run ampcor ampcor.ampcor() offsets = ampcor.getOffsetField() ampcorOffsetFile = 'ampcor.off' cullOffsetFile = 'cull.off' affineTransformFile = 'affine_transform.txt' writeOffset(offsets, ampcorOffsetFile) #finalize image, and re-create it #otherwise the file pointer is still at the end of the image mMag.finalizeImage() sMag.finalizeImage() # #cull offsets # import io # from contextlib import redirect_stdout # f = io.StringIO() # with redirect_stdout(f): # fitoff(ampcorOffsetFile, cullOffsetFile, 1.5, .5, 50) # s = f.getvalue() # #print(s) # with open(affineTransformFile, 'w') as f: # f.write(s) #cull offsets import subprocess proc = subprocess.Popen(["python3", "-c", "import isce; from contrib.alos2proc_f.alos2proc_f import fitoff; fitoff('ampcor.off', 'cull.off', 1.5, .5, 50)"], stdout=subprocess.PIPE) out = proc.communicate()[0] with open(affineTransformFile, 'w') as f: f.write(out.decode('utf-8')) #check number of offsets left with open(cullOffsetFile, 'r') as f: numCullOffsets = sum(1 for linex in f) if numCullOffsets < 50: print('\n\nWARNING: too few points left after culling, {} left'.format(numCullOffsets)) print('do not estimate offsets between radar and dem\n\n') self._insar.radarDemAffineTransform = [1.0, 0.0, 0.0, 1.0, 0.0, 0.0] catalog.addItem('warning message', 'too few points left after culling, {} left'.format(numCullOffsets), 'runRdrDemOffset') os.chdir('../../') catalog.printToLog(logger, "runRdrDemOffset") self._insar.procDoc.addAllFromCatalog(catalog) return #read affine transform parameters with open(affineTransformFile) as f: lines = f.readlines() i = 0 for linex in lines: if 'Affine Matrix ' in linex: m11 = float(lines[i + 2].split()[0]) m12 = float(lines[i + 2].split()[1]) m21 = float(lines[i + 3].split()[0]) m22 = float(lines[i + 3].split()[1]) t1 = float(lines[i + 7].split()[0]) t2 = float(lines[i + 7].split()[1]) break i += 1 self._insar.radarDemAffineTransform = [m11, m12, m21, m22, t1, t2] ################################################################################################## os.chdir('../../') catalog.printToLog(logger, "runRdrDemOffset") self._insar.procDoc.addAllFromCatalog(catalog)
def run(imageAmp, imageSim, numBand, infos, nstages, scale, stdWriter, catalog=None, sceneid='NO_ID'): logger.info("Running Rgoffset: %s" % sceneid) coarseAcross = 0 coarseDown = 0 firstAc = infos['firstSampleAcross'] firstDown = infos['firstSampleDown'] numLocationAcross = infos['numberLocationAcross'] numLocationDown = infos['numberLocationDown'] slaveWidth = imageAmp.getWidth() slaveLength = imageAmp.getLength() objAmp = isceobj.createSlcImage() objAmp.dataType = 'CFLOAT' objAmp.bands = 1 objAmp.setFilename(imageAmp.getFilename()) objAmp.setAccessMode('read') objAmp.setWidth(slaveWidth) objAmp.createImage() masterWidth = imageSim.getWidth() objSim = isceobj.createImage() objSim.setFilename(imageSim.getFilename()) objSim.dataType = 'FLOAT' objSim.setWidth(masterWidth) objSim.setAccessMode('read') objSim.createImage() masterLength = imageSim.getLength() finalIteration = False for iterNum in xrange(nstages-1,-1,-1): ####Rewind the images try: objAmp.rewind() objSim.rewind() except: print('Issues when rewinding images.') #KK sys.exit? ###### logger.debug('Starting Iteration Stage : %d'%(iterNum)) logger.debug("Gross Across: %s" % (coarseAcross)) logger.debug("Gross Down: %s" % (coarseDown)) ####Clear objs objAmpcor = None objOff = None offField = None objAmpcor = Ampcor() objAmpcor.setImageDataType1('real') objAmpcor.setImageDataType2('complex') ####Dummy values as there is no scale difference at this step objAmpcor.setFirstPRF(1.0) objAmpcor.setSecondPRF(1.0) objAmpcor.setFirstRangeSpacing(1.0) objAmpcor.setSecondRangeSpacing(1.0) #####Scale all the reference and search windows scaleFactor = scale**iterNum objAmpcor.windowSizeWidth *= scaleFactor objAmpcor.windowSizeHeight *= scaleFactor objAmpcor.searchWindowSizeWidth *= scaleFactor objAmpcor.searchWindowSizeHeight *= scaleFactor xMargin = 2*objAmpcor.searchWindowSizeWidth + objAmpcor.windowSizeWidth yMargin = 2*objAmpcor.searchWindowSizeHeight + objAmpcor.windowSizeHeight #####Set image limits for search offAc = max(firstAc,-coarseAcross)+xMargin offDn = max(firstDn,-coarseDown)+yMargin offAcmax = int(coarseAcross) logger.debug("Gross Max Across: %s" % (offAcmax)) lastAc = int(min(masterWidth, slaveWidth-offAcmax) - xMargin) offDnmax = int(coarseDown) logger.debug("Gross Max Down: %s" % (offDnmax)) lastDn = int(min(masterLength, slaveLength-offDnmax) - yMargin) logger.debug("Last Down: %s" %(lastDn)) objAmpcor.setFirstSampleAcross(offAc) objAmpcor.setLastSampleAcross(lastAc) objAmpcor.setFirstSampleDown(offDn) objAmpcor.setLastSampleDown(lastDn) objAmpcor.setAcrossGrossOffset(coarseAcross) objAmpcor.setDownGrossOffset(coarseDown) if (offAc > lastAc) or (offDn > lastDn): print('Search window scale is too large.') print('Skipping Scale: %d'%(iterNum+1)) continue if ((lastAc - offAc) <= (2*xMargin)) or ((lastDn - offDn) <= (2*yMargin)): print('Image not large enough accounting for margins.') print('Skipping Scale: %d'%(iterNum+1)) continue logger.debug('Looks = %d'%scaleFactor) logger.debug('Correlation window sizes: %d %d'%(objAmpcor.windowSizeWidth, objAmpcor.windowSizeHeight)) logger.debug('Search window sizes: %d %d'%(objAmpcor.searchWindowSizeWidth, objAmpcor.searchWindowSizeHeight)) logger.debug(' Across pos: %d %d out of (%d,%d)'%(objAmpcor.firstSampleAcross, objAmpcor.lastSampleAcross, masterWidth, slaveWidth)) logger.debug(' Down pos: %d %d out of (%d,%d)'%(objAmpcor.firstSampleDown, objAmpcor.lastSampleDown, masterLength, slaveLength)) if (iterNum == 0) or finalIteration: if catalog is not None: # Record the inputs isceobj.Catalog.recordInputs(catalog, objAmpcor, "runRgoffset.%s" % sceneid, logger, "runRgoffset.%s" % sceneid) objAmpcor.setNumberLocationAcross(numLocationAcross) objAmpcor.setNumberLocationDown(numLocationDown) else: objAmpcor.setNumberLocationAcross(20) objAmpcor.setNumberLocationDown(20) objAmpcor.setAcrossLooks(scaleFactor) objAmpcor.setDownLooks(scaleFactor) objAmpcor.setZoomWindowSize(scale*objAmpcor.zoomWindowSize) objAmpcor.setOversamplingFactor(2) objAmpcor.ampcor(objSim,objAmp) offField = objAmpcor.getOffsetField() if (iterNum == 0) or finalIteration: if catalog is not None: # Record the outputs isceobj.Catalog.recordOutputs(catalog, objAmpcor, "runRgoffset.%s" % sceneid, logger, "runRgoffset.%s" % sceneid) else: objOff = isceobj.createOffoutliers() objOff.wireInputPort(name='offsets', object=offField) objOff.setSNRThreshold(2.0) objOff.setDistance(10) objOff.setStdWriter = stdWriter.set_file_tags("nstage_offoutliers"+str(iterNum), "log", "err", "out") objOff.offoutliers() coarseAcross = int(objOff.averageOffsetAcross) coarseDown = int(objOff.averageOffsetDown) objSim.finalizeImage() objAmp.finalizeImage() objOff = None objAmpcor = None return offField
def run(imageAmp, imageSim, numBand, prf, fs1, infos, stdWriter, catalog=None, sceneid='NO_ID'): #fs1: range sampling rate firstAc = infos['firstSampleAcrossPrf'] firstDown = infos['firstSampleDownPrf'] numLocationAcross = infos['numberLocationAcrossPrf'] numLocationDown = infos['numberLocationDownPrf'] coarseAcross = 0 coarseDown = 0 #Fake amplitude image as a complex image objAmp = isceobj.createImage() objAmp.setAccessMode('read') objAmp.dataType = 'CFLOAT' objAmp.bands = 1 objAmp.setFilename(imageAmp.filename) objAmp.setWidth(imageAmp.width) objAmp.createImage() widthAmp = objAmp.getWidth() intLength = objAmp.getLength() objSim = isceobj.createImage() objSim.setFilename(imageSim.filename) objSim.setWidth(imageSim.width) objSim.dataType='FLOAT' objSim.setAccessMode('read') objSim.createImage() # check if it's correct delRg1 = CN.SPEED_OF_LIGHT / (2*fs1) objAmpcor = Ampcor() objAmpcor.setImageDataType1('real') objAmpcor.setImageDataType2('complex') ####Adjust first and last values using window sizes xMargin = 2*objAmpcor.searchWindowSizeWidth + objAmpcor.windowSizeWidth yMargin = 2*objAmpcor.searchWindowSizeHeight + objAmpcor.windowSizeHeight offAc = max(firstAc, -coarseAcross) + xMargin offDn = max(firstDown, -coarseDown) + yMargin lastAc = int(min(widthAmp, widthAmp-offAc) - xMargin) lastDn = int(min(intLength, intLength-offDn) - yMargin) print(xMargin, yMargin) print(offAc, lastAc) print(offDn, lastDn) objAmpcor.setFirstSampleAcross(offAc) objAmpcor.setLastSampleAcross(lastAc) objAmpcor.setNumberLocationAcross(numLocationAcross) objAmpcor.setFirstSampleDown(offDn) objAmpcor.setLastSampleDown(lastDn) objAmpcor.setNumberLocationDown(numLocationDown) #set the tag used in the outfile. each message is preceded by this tag #if the writer is not of "file" type the call has no effect objAmpcor.stdWriter = stdWriter.set_file_tags("rgoffset", "log", "err", "out") objAmpcor.setFirstPRF(prf) objAmpcor.setSecondPRF(prf) objAmpcor.setAcrossGrossOffset(coarseAcross) objAmpcor.setDownGrossOffset(coarseDown) objAmpcor.setFirstRangeSpacing(delRg1) objAmpcor.setSecondRangeSpacing(delRg1) objAmpcor.ampcor(objSim,objAmp) if catalog is not None: # Record the inputs and outputs isceobj.Catalog.recordInputsAndOutputs(catalog, objAmpcor, "runRgoffset_ampcor.%s" % sceneid, logger, "runRgoffset_ampcor.%s" % sceneid) objAmp.finalizeImage() objSim.finalizeImage() return objAmpcor.getOffsetField()
def runRgoffset(self): numLocationAcross = self._insar.getNumberLocationAcrossPrf() numLocationDown = self._insar.getNumberLocationDownPrf() firstAc = self._insar.getFirstSampleAcrossPrf() firstDown = self._insar.getFirstSampleDownPrf() #Fake amplitude image as a complex image imageAmp = self._insar.getResampAmpImage() objAmp = isceobj.createImage() objAmp.setAccessMode('read') objAmp.dataType = 'CFLOAT' objAmp.bands = 1 objAmp.setFilename(imageAmp.filename) objAmp.setWidth(imageAmp.width) objAmp.createImage() widthAmp = objAmp.getWidth() intLength = objAmp.getLength() imageSim = self._insar.getSimAmpImage() objSim = isceobj.createImage() objSim.setFilename(imageSim.filename) objSim.setWidth(imageSim.width) objSim.dataType = 'FLOAT' objSim.setAccessMode('read') objSim.createImage() simWidth = imageSim.getWidth() simLength = imageSim.getLength() fs1 = self._insar.getReferenceFrame().getInstrument().getRangeSamplingRate( ) ##check delRg1 = CN.SPEED_OF_LIGHT / (2 * fs1) ## if it's correct objAmpcor = Ampcor(name='insarapp_intsim_ampcor') objAmpcor.configure() objAmpcor.setImageDataType1('real') objAmpcor.setImageDataType2('mag') ####Adjust first and last values using window sizes xMargin = 2 * objAmpcor.searchWindowSizeWidth + objAmpcor.windowSizeWidth yMargin = 2 * objAmpcor.searchWindowSizeHeight + objAmpcor.windowSizeHeight if not objAmpcor.acrossGrossOffset: coarseAcross = 0 else: coarseAcross = objAmpcor.acrossGrossOffset if not objAmpcor.downGrossOffset: coarseDown = 0 else: coarseDown = objAmpcor.downGrossOffset offAc = max(firstAc, -coarseAcross) + xMargin + 1 offDn = max(firstDown, -coarseDown) + yMargin + 1 lastAc = int(min(widthAmp, simWidth - offAc) - xMargin - 1) lastDn = int(min(intLength, simLength - offDn) - yMargin - 1) if not objAmpcor.firstSampleAcross: objAmpcor.setFirstSampleAcross(offAc) if not objAmpcor.lastSampleAcross: objAmpcor.setLastSampleAcross(lastAc) if not objAmpcor.numberLocationAcross: objAmpcor.setNumberLocationAcross(numLocationAcross) if not objAmpcor.firstSampleDown: objAmpcor.setFirstSampleDown(offDn) if not objAmpcor.lastSampleDown: objAmpcor.setLastSampleDown(lastDn) if not objAmpcor.numberLocationDown: objAmpcor.setNumberLocationDown(numLocationDown) #set the tag used in the outfile. each message is precided by this tag #is the writer is not of "file" type the call has no effect self._stdWriter.setFileTag("rgoffset", "log") self._stdWriter.setFileTag("rgoffset", "err") self._stdWriter.setFileTag("rgoffset", "out") objAmpcor.setStdWriter(self._stdWriter) prf = self._insar.getReferenceFrame().getInstrument( ).getPulseRepetitionFrequency() objAmpcor.setFirstPRF(prf) objAmpcor.setSecondPRF(prf) if not objAmpcor.acrossGrossOffset: objAmpcor.setAcrossGrossOffset(coarseAcross) if not objAmpcor.downGrossOffset: objAmpcor.setDownGrossOffset(coarseDown) objAmpcor.setFirstRangeSpacing(delRg1) objAmpcor.setSecondRangeSpacing(delRg1) objAmpcor.ampcor(objSim, objAmp) # Record the inputs and outputs from isceobj.Catalog import recordInputsAndOutputs recordInputsAndOutputs(self._insar.procDoc, objAmpcor, "runRgoffset_ampcor", \ logger, "runRgoffset_ampcor") self._insar.setOffsetField(objAmpcor.getOffsetField()) self._insar.setRefinedOffsetField(objAmpcor.getOffsetField()) objAmp.finalizeImage() objSim.finalizeImage()
def runSlcMatch(self): '''match a pair of SLCs ''' 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() demFile = os.path.abspath(self._insar.dem) wbdFile = os.path.abspath(self._insar.wbd) denseOffsetDir = 'dense_offset' os.makedirs(denseOffsetDir, exist_ok=True) os.chdir(denseOffsetDir) masterTrack = self._insar.loadProduct(self._insar.masterTrackParameter) slaveTrack = self._insar.loadProduct(self._insar.slaveTrackParameter) ######################################################################################### ################################################## # compute geometric offsets ################################################## if self.useGPU and self._insar.hasGPU(): topoGPU(masterTrack, 1, 1, demFile, 'lat.rdr', 'lon.rdr', 'hgt.rdr', 'los.rdr') geo2RdrGPU(slaveTrack, 1, 1, 'lat.rdr', 'lon.rdr', 'hgt.rdr', 'rg.off', 'az.off') else: topoCPU(masterTrack, 1, 1, demFile, 'lat.rdr', 'lon.rdr', 'hgt.rdr', 'los.rdr') geo2RdrCPU(slaveTrack, 1, 1, 'lat.rdr', 'lon.rdr', 'hgt.rdr', 'rg.off', 'az.off') ################################################## # resample SLC ################################################## #SlaveSlcResampled = os.path.splitext(self._insar.slaveSlc)[0]+'_resamp'+os.path.splitext(self._insar.slaveSlc)[1] SlaveSlcResampled = self._insar.slaveSlcCoregistered rangeOffsets2Frac = 0.0 azimuthOffsets2Frac = 0.0 resamp(self._insar.slaveSlc, SlaveSlcResampled, 'rg.off', 'az.off', masterTrack.numberOfSamples, masterTrack.numberOfLines, slaveTrack.prf, slaveTrack.dopplerVsPixel, [rangeOffsets2Frac, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], [azimuthOffsets2Frac, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]) create_xml(SlaveSlcResampled, masterTrack.numberOfSamples, masterTrack.numberOfLines, 'slc') if self.estimateResidualOffset: numberOfOffsets = 800 rangeStep = 50 length = masterTrack.numberOfLines width = masterTrack.numberOfSamples waterBodyRadar('lat.rdr', 'lon.rdr', wbdFile, 'wbd.rdr') wbd=np.memmap('wbd.rdr', dtype=np.int8, mode='r', shape=(length, width)) azimuthStep = int(length/width*rangeStep+0.5) landRatio = np.sum(wbd[0:length:azimuthStep,0:width:rangeStep]!=-1)/(int(length/azimuthStep)*int(width/rangeStep)) del wbd if (landRatio <= 0.00125): print('\n\nWARNING: land area too small for estimating residual slc offsets') print('do not estimate residual offsets\n\n') catalog.addItem('warning message', 'land area too small for estimating residual slc offsets', 'runSlcMatch') else: numberOfOffsets /= landRatio #we use equal number of offsets in range and azimuth here numberOfOffsetsRange = int(np.sqrt(numberOfOffsets)+0.5) numberOfOffsetsAzimuth = int(np.sqrt(numberOfOffsets)+0.5) if numberOfOffsetsRange > int(width/2): numberOfOffsetsRange = int(width/2) if numberOfOffsetsAzimuth > int(length/2): numberOfOffsetsAzimuth = int(length/2) if numberOfOffsetsRange < 10: numberOfOffsetsRange = 10 if numberOfOffsetsAzimuth < 10: numberOfOffsetsAzimuth = 10 ########################################## #2. match using ampcor ########################################## ampcor = Ampcor(name='insarapp_slcs_ampcor') ampcor.configure() mSLC = isceobj.createSlcImage() mSLC.load(self._insar.masterSlc+'.xml') mSLC.setAccessMode('read') mSLC.createImage() sSLC = isceobj.createSlcImage() sSLC.load(SlaveSlcResampled+'.xml') sSLC.setAccessMode('read') sSLC.createImage() ampcor.setImageDataType1('complex') ampcor.setImageDataType2('complex') ampcor.setMasterSlcImage(mSLC) ampcor.setSlaveSlcImage(sSLC) #MATCH REGION #compute an offset at image center to use rgoff = 0.0 azoff = 0.0 #it seems that we cannot use 0, haven't look into the problem if rgoff == 0: rgoff = 1 if azoff == 0: azoff = 1 firstSample = 1 if rgoff < 0: firstSample = int(35 - rgoff) firstLine = 1 if azoff < 0: firstLine = int(35 - azoff) ampcor.setAcrossGrossOffset(rgoff) ampcor.setDownGrossOffset(azoff) ampcor.setFirstSampleAcross(firstSample) ampcor.setLastSampleAcross(mSLC.width) ampcor.setNumberLocationAcross(numberOfOffsetsRange) ampcor.setFirstSampleDown(firstLine) ampcor.setLastSampleDown(mSLC.length) ampcor.setNumberLocationDown(numberOfOffsetsAzimuth) #MATCH PARAMETERS #full-aperture mode if (self._insar.modeCombination == 21) or \ (self._insar.modeCombination == 22) or \ (self._insar.modeCombination == 31) or \ (self._insar.modeCombination == 32): ampcor.setWindowSizeWidth(64) ampcor.setWindowSizeHeight(512) #note this is the half width/length of search area, number of resulting correlation samples: 32*2+1 ampcor.setSearchWindowSizeWidth(32) ampcor.setSearchWindowSizeHeight(32) #triggering full-aperture mode matching ampcor.setWinsizeFilt(8) ampcor.setOversamplingFactorFilt(64) #regular mode else: ampcor.setWindowSizeWidth(64) ampcor.setWindowSizeHeight(64) ampcor.setSearchWindowSizeWidth(16) ampcor.setSearchWindowSizeHeight(16) #REST OF THE STUFF ampcor.setAcrossLooks(1) ampcor.setDownLooks(1) ampcor.setOversamplingFactor(64) ampcor.setZoomWindowSize(16) #1. The following not set #Matching Scale for Sample/Line Directions (-) = 1. 1. #should add the following in Ampcor.py? #if not set, in this case, Ampcor.py'value is also 1. 1. #ampcor.setScaleFactorX(1.) #ampcor.setScaleFactorY(1.) #MATCH THRESHOLDS AND DEBUG DATA #2. The following not set #in roi_pac the value is set to 0 1 #in isce the value is set to 0.001 1000.0 #SNR and Covariance Thresholds (-) = {s1} {s2} #should add the following in Ampcor? #THIS SHOULD BE THE ONLY THING THAT IS DIFFERENT FROM THAT OF ROI_PAC #ampcor.setThresholdSNR(0) #ampcor.setThresholdCov(1) ampcor.setDebugFlag(False) ampcor.setDisplayFlag(False) #in summary, only two things not set which are indicated by 'The following not set' above. #run ampcor ampcor.ampcor() offsets = ampcor.getOffsetField() mSLC.finalizeImage() sSLC.finalizeImage() #3. cull offsets refinedOffsets = cullOffsetsRoipac(offsets, numThreshold=50) if refinedOffsets == None: print('\n\nWARNING: too few offsets left for slc residual offset estimation') print('do not estimate residual offsets\n\n') catalog.addItem('warning message', 'too few offsets left for slc residual offset estimation', 'runSlcMatch') else: rangeOffset, azimuthOffset = meanOffset(refinedOffsets) os.remove(SlaveSlcResampled) os.remove(SlaveSlcResampled+'.vrt') os.remove(SlaveSlcResampled+'.xml') rangeOffsets2Frac = rangeOffset azimuthOffsets2Frac = azimuthOffset resamp(self._insar.slaveSlc, SlaveSlcResampled, 'rg.off', 'az.off', masterTrack.numberOfSamples, masterTrack.numberOfLines, slaveTrack.prf, slaveTrack.dopplerVsPixel, [rangeOffsets2Frac, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], [azimuthOffsets2Frac, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]) create_xml(SlaveSlcResampled, masterTrack.numberOfSamples, masterTrack.numberOfLines, 'slc') catalog.addItem('number of offsets range', numberOfOffsetsRange, 'runSlcMatch') catalog.addItem('number of offsets azimuth', numberOfOffsetsAzimuth, 'runSlcMatch') catalog.addItem('range residual offset after geometric coregistration', rangeOffset, 'runSlcMatch') catalog.addItem('azimuth residual offset after geometric coregistration', azimuthOffset, 'runSlcMatch') if self.deleteGeometryFiles: os.remove('lat.rdr') os.remove('lat.rdr.vrt') os.remove('lat.rdr.xml') os.remove('lon.rdr') os.remove('lon.rdr.vrt') os.remove('lon.rdr.xml') os.remove('hgt.rdr') os.remove('hgt.rdr.vrt') os.remove('hgt.rdr.xml') os.remove('los.rdr') os.remove('los.rdr.vrt') os.remove('los.rdr.xml') # if os.path.isfile('wbd.rdr'): # os.remove('wbd.rdr') # os.remove('wbd.rdr.vrt') # os.remove('wbd.rdr.xml') ######################################################################################### os.chdir('../') catalog.printToLog(logger, "runSlcMatch") self._insar.procDoc.addAllFromCatalog(catalog)
def run(frame1, frame2, formSlc1, formSlc2, imSlc1, imSlc2, nstages, scale, infos, stdWriter, catalog=None, sceneid='NO_ID'): logger.info( "Calculate offset between slcs using %d stages of ampcor: %s " % (nstages, sceneid)) prf1 = frame1.getInstrument().getPulseRepetitionFrequency() prf2 = frame2.getInstrument().getPulseRepetitionFrequency() nearRange1 = formSlc1.startingRange nearRange2 = formSlc2.startingRange fs1 = frame1.getInstrument().getRangeSamplingRate() fs2 = frame2.getInstrument().getRangeSamplingRate() ###There seems to be no other way of determining image length - Piyush patchSize = infos['patchSize'] numPatches = infos['numberPatches'] valid_az_samples = infos['numberValidPulses'] firstAc = infos['firstSampleAcrossPrf'] firstDown = infos['firstSampleDownPrf'] numLocationAcross = infos['numberLocationAcrossPrf'] numLocationDown = infos['numberLocationDownPrf'] delRg1 = CN.SPEED_OF_LIGHT / (2 * fs1) delRg2 = CN.SPEED_OF_LIGHT / (2 * fs2) grossRg = infos['grossRg'] if grossRg is not None: coarseAcross = grossRg else: coarseRange = (nearRange1 - nearRange2) / delRg2 coarseAcross = int(coarseRange + 0.5) if (coarseRange <= 0): coarseAcross = int(coarseRange - 0.5) grossAz = infos['grossAz'] if grossAz is not None: coarseDown = grossAz else: s1 = formSlc1.mocompPosition[1][0] s1_2 = formSlc1.mocompPosition[1][1] s2 = formSlc2.mocompPosition[1][0] s2_2 = formSlc2.mocompPosition[1][1] coarseAz = int((s1 - s2) / (s2_2 - s2) + prf2 * (1 / prf1 - 1 / prf2) * (patchSize - valid_az_samples) / 2) coarseDown = int(coarseAz + 0.5) if (coarseAz <= 0): coarseDown = int(coarseAz - 0.5) coarseAcross = 0 + coarseAcross coarseDown = 0 + coarseDown mSlc = isceobj.createSlcImage() IU.copyAttributes(imSlc1, mSlc) accessMode = 'read' mSlc.setAccessMode(accessMode) mSlc.createImage() masterWidth = mSlc.getWidth() masterLength = mSlc.getLength() sSlc = isceobj.createSlcImage() IU.copyAttributes(imSlc2, sSlc) accessMode = 'read' sSlc.setAccessMode(accessMode) sSlc.createImage() slaveWidth = sSlc.getWidth() slaveLength = sSlc.getLength() finalIteration = False for iterNum in xrange(nstages - 1, -1, -1): ####Rewind the images try: mSlc.rewind() sSlc.rewind() except: print('Issues when rewinding images.' ) #KK shouldn't it be an error? sys.exit ###### logger.debug('Starting Iteration Stage : %d' % (iterNum)) logger.debug("Gross Across: %s" % (coarseAcross)) logger.debug("Gross Down: %s" % (coarseDown)) ####Clear objs objAmpcor = None objOff = None offField = None objAmpcor = Ampcor() objAmpcor.setImageDataType1('complex') objAmpcor.setImageDataType2('complex') objAmpcor.setFirstPRF(prf1) objAmpcor.setSecondPRF(prf2) objAmpcor.setFirstRangeSpacing(delRg1) objAmpcor.setSecondRangeSpacing(delRg2) #####Scale all the reference and search windows scaleFactor = scale**iterNum objAmpcor.windowSizeWidth *= scaleFactor objAmpcor.windowSizeHeight *= scaleFactor objAmpcor.searchWindowSizeWidth *= scaleFactor objAmpcor.searchWindowSizeHeight *= scaleFactor xMargin = 2 * objAmpcor.searchWindowSizeWidth + objAmpcor.windowSizeWidth yMargin = 2 * objAmpcor.searchWindowSizeHeight + objAmpcor.windowSizeHeight #####Set image limits for search offAc = max(firstAc, -coarseAcross) + xMargin offDn = max(firstDown, -coarseDown) + yMargin offAcmax = int(coarseAcross + ((fs2 / fs1) - 1) * masterWidth) logger.debug("Gross Max Across: %s" % (offAcmax)) lastAc = int(min(masterWidth, slaveWidth - offAcmax) - xMargin) offDnmax = int(coarseDown + ((prf2 / prf1) - 1) * masterLength) logger.debug("Gross Max Down: %s" % (offDnmax)) lastDn = int(min(masterLength, slaveLength - offDnmax) - yMargin) objAmpcor.setFirstSampleAcross(offAc) objAmpcor.setLastSampleAcross(lastAc) objAmpcor.setFirstSampleDown(offDn) objAmpcor.setLastSampleDown(lastDn) objAmpcor.setAcrossGrossOffset(coarseAcross) objAmpcor.setDownGrossOffset(coarseDown) if (offAc > lastAc) or (offDn > lastDn): print('Search window scale is too large.') print('Skipping Scale: %d' % (iterNum + 1)) continue logger.debug('Looks = %d' % scaleFactor) logger.debug('Correlation window sizes: %d %d' % (objAmpcor.windowSizeWidth, objAmpcor.windowSizeHeight)) logger.debug('Search window sizes: %d %d' % (objAmpcor.searchWindowSizeWidth, objAmpcor.searchWindowSizeHeight)) logger.debug(' Across pos: %d %d out of (%d,%d)' % (objAmpcor.firstSampleAcross, objAmpcor.lastSampleAcross, masterWidth, slaveWidth)) logger.debug(' Down pos: %d %d out of (%d,%d)' % (objAmpcor.firstSampleDown, objAmpcor.lastSampleDown, masterLength, slaveLength)) if (iterNum == 0) or finalIteration: if catalog is not None: # Record the inputs isceobj.Catalog.recordInputs(catalog, objAmpcor, "runOffsetprf.%s" % sceneid, logger, "runOffsetprf.%s" % sceneid) objAmpcor.setNumberLocationAcross(numLocationAcross) objAmpcor.setNumberLocationDown(numLocationDown) else: objAmpcor.setNumberLocationAcross(10) objAmpcor.setNumberLocationDown(10) objAmpcor.setAcrossLooks(scaleFactor) objAmpcor.setDownLooks(scaleFactor) objAmpcor.setZoomWindowSize(scale * objAmpcor.zoomWindowSize) objAmpcor.setOversamplingFactor(2) objAmpcor.ampcor(mSlc, sSlc) offField = objAmpcor.getOffsetField() if (iterNum == 0) or finalIteration: if catalog is not None: # Record the outputs isceobj.Catalog.recordOutputs(catalog, objAmpcor, "runOffsetprf.%s" % sceneid, logger, "runOffsetprf.%s" % sceneid) else: objOff = isceobj.createOffoutliers() objOff.wireInputPort(name='offsets', object=offField) objOff.setSNRThreshold(2.0) objOff.setDistance(10) objOff.setStdWriter = stdWriter.set_file_tags( "nstage_offoutliers" + str(iterNum), "log", "err", "out") objOff.offoutliers() coarseAcross = int(objOff.averageOffsetAcross) coarseDown = int(objOff.averageOffsetDown) mSlc.finalizeImage() sSlc.finalizeImage() objOff = None objAmpcor = None return offField
def runOffsetprf(self): from isceobj.Catalog import recordInputs logger.info("Calculate offset between slcs using ampcor") masterFrame = self._insar.getMasterFrame() slaveFrame = self._insar.getSlaveFrame() masterOrbit = self._insar.getMasterOrbit() slaveOrbit = self._insar.getSlaveOrbit() prf1 = masterFrame.getInstrument().getPulseRepetitionFrequency() prf2 = slaveFrame.getInstrument().getPulseRepetitionFrequency() nearRange1 = self.insar.formSLC1.startingRange nearRange2 = self.insar.formSLC2.startingRange fs1 = masterFrame.getInstrument().getRangeSamplingRate() fs2 = slaveFrame.getInstrument().getRangeSamplingRate() ###There seems to be no other way of determining image length - Piyush patchSize = self._insar.getPatchSize() numPatches = self._insar.getNumberPatches() valid_az_samples = self._insar.getNumberValidPulses() firstAc = self._insar.getFirstSampleAcrossPrf() firstDown = self._insar.getFirstSampleDownPrf() numLocationAcross = self._insar.getNumberLocationAcrossPrf() numLocationDown = self._insar.getNumberLocationDownPrf() delRg1 = CN.SPEED_OF_LIGHT / (2 * fs1) delRg2 = CN.SPEED_OF_LIGHT / (2 * fs2) coarseRange = (nearRange1 - nearRange2) / delRg2 coarseAcross = int(coarseRange + 0.5) if (coarseRange <= 0): coarseAcross = int(coarseRange - 0.5) pass if self.grossRg is not None: coarseAcross = self.grossRg pass s1 = self.insar.formSLC1.mocompPosition[1][0] s1_2 = self.insar.formSLC1.mocompPosition[1][1] s2 = self.insar.formSLC2.mocompPosition[1][0] s2_2 = self.insar.formSLC2.mocompPosition[1][1] coarseAz = int((s1 - s2) / (s2_2 - s2) + prf2 * (1 / prf1 - 1 / prf2) * (patchSize - valid_az_samples) / 2) coarseDown = int(coarseAz + 0.5) if (coarseAz <= 0): coarseDown = int(coarseAz - 0.5) pass if self.grossAz is not None: coarseDown = self.grossAz pass coarseAcross = 0 + coarseAcross coarseDown = 0 + coarseDown mSlcImage = self._insar.getMasterSlcImage() mSlc = isceobj.createSlcImage() IU.copyAttributes(mSlcImage, mSlc) accessMode = 'read' mSlc.setAccessMode(accessMode) mSlc.createImage() masterWidth = mSlc.getWidth() masterLength = mSlc.getLength() sSlcImage = self._insar.getSlaveSlcImage() sSlc = isceobj.createSlcImage() IU.copyAttributes(sSlcImage, sSlc) accessMode = 'read' sSlc.setAccessMode(accessMode) sSlc.createImage() slaveWidth = sSlc.getWidth() slaveLength = sSlc.getLength() objAmpcor = Ampcor(name='insarapp_slcs_ampcor') objAmpcor.configure() objAmpcor.setImageDataType1('complex') objAmpcor.setImageDataType2('complex') if objAmpcor.acrossGrossOffset: coarseAcross = objAmpcor.acrossGrossOffset if objAmpcor.downGrossOffset: coarseDown = objAmpcor.downGrossOffset logger.debug("Gross Across: %s" % (coarseAcross)) logger.debug("Gross Down: %s" % (coarseDown)) xMargin = 2 * objAmpcor.searchWindowSizeWidth + objAmpcor.windowSizeWidth yMargin = 2 * objAmpcor.searchWindowSizeHeight + objAmpcor.windowSizeHeight #####Compute image positions offAc = max(firstAc, -coarseAcross) + xMargin offDn = max(firstDown, -coarseDown) + yMargin offAcmax = int(coarseAcross + ((fs2 / fs1) - 1) * masterWidth) logger.debug("Gross Max Across: %s" % (offAcmax)) lastAc = int(min(masterWidth, slaveWidth - offAcmax) - xMargin) offDnmax = int(coarseDown + ((prf2 / prf1) - 1) * masterLength) logger.debug("Gross Max Down: %s" % (offDnmax)) lastDown = int(min(masterLength, slaveLength - offDnmax) - yMargin) if not objAmpcor.firstSampleAcross: objAmpcor.setFirstSampleAcross(offAc) if not objAmpcor.lastSampleAcross: objAmpcor.setLastSampleAcross(lastAc) if not objAmpcor.numberLocationAcross: objAmpcor.setNumberLocationAcross(numLocationAcross) if not objAmpcor.firstSampleDown: objAmpcor.setFirstSampleDown(offDn) if not objAmpcor.lastSampleDown: objAmpcor.setLastSampleDown(lastDown) if not objAmpcor.numberLocationDown: objAmpcor.setNumberLocationDown(numLocationDown) #####Override gross offsets if not provided if not objAmpcor.acrossGrossOffset: objAmpcor.setAcrossGrossOffset(coarseAcross) if not objAmpcor.downGrossOffset: objAmpcor.setDownGrossOffset(coarseDown) #####User inputs are overriden here objAmpcor.setFirstPRF(prf1) objAmpcor.setSecondPRF(prf2) objAmpcor.setFirstRangeSpacing(delRg1) objAmpcor.setSecondRangeSpacing(delRg2) # Record the inputs recordInputs(self._insar.procDoc, objAmpcor, "runOffsetprf", logger, "runOffsetprf") objAmpcor.ampcor(mSlc, sSlc) # Record the outputs from isceobj.Catalog import recordOutputs recordOutputs(self._insar.procDoc, objAmpcor, "runOffsetprf", logger, "runOffsetprf") mSlc.finalizeImage() sSlc.finalizeImage() # save the input offset field for the record self._insar.setOffsetField(objAmpcor.getOffsetField()) self._insar.setRefinedOffsetField(objAmpcor.getOffsetField())
objAmpcor.setImageDataType2('real') #####Stage 2: No ports for ampcor ### Any parameters can be controlled through my_ampcor.xml ### Stage 3: Set values as needed ####Only set these values if user does not define it in my_ampcor.xml if objAmpcor.acrossGrossOffset is None: objAmpcor.acrossGrossOffset = coarseAcross if objAmpcor.downGrossOffset is None: objAmpcor.downGrossOffset = coarseDown logging.info('Across Gross Offset = %d' % (objAmpcor.acrossGrossOffset)) logging.info('Down Gross Offset = %d' % (objAmpcor.downGrossOffset)) ####Stage 4: Call the main method objAmpcor.ampcor(masterImg, slaveImg) ###Close ununsed images masterImg.finalizeImage() slaveImg.finalizeImage() ######Stage 5: Get required data out of the processing run offField = objAmpcor.getOffsetField() logging.info('Number of returned offsets : %d' % (len(offField._offsets))) ####Write output to an ascii file field = np.array(offField.unpackOffsets()) np.savetxt(inps.outfile, field, delimiter=" ", format='%5.6f')
def estimateFrameOffset(swath1, swath2, image1, image2, matchingMode=0): ''' estimate offset of two adjacent frames using matching matchingMode: 0: ScanSAR full-aperture image 1: regular image ''' import isceobj from isceobj.Alos2Proc.Alos2ProcPublic import cullOffsets from isceobj.Alos2Proc.Alos2ProcPublic import cullOffsetsRoipac from isceobj.Alos2Proc.Alos2ProcPublic import meanOffset from mroipac.ampcor.Ampcor import Ampcor ########################################## #2. match using ampcor ########################################## ampcor = Ampcor(name='insarapp_slcs_ampcor') ampcor.configure() #mSLC = isceobj.createSlcImage() mSLC = isceobj.createImage() mSLC.load(image1 + '.xml') mSLC.setFilename(image1) #mSLC.extraFilename = image1 + '.vrt' mSLC.setAccessMode('read') mSLC.createImage() #sSLC = isceobj.createSlcImage() sSLC = isceobj.createImage() sSLC.load(image2 + '.xml') sSLC.setFilename(image2) #sSLC.extraFilename = image2 + '.vrt' sSLC.setAccessMode('read') sSLC.createImage() if mSLC.dataType.upper() == 'CFLOAT': ampcor.setImageDataType1('complex') ampcor.setImageDataType2('complex') elif mSLC.dataType.upper() == 'FLOAT': ampcor.setImageDataType1('real') ampcor.setImageDataType2('real') else: raise Exception('file type not supported yet.') ampcor.setMasterSlcImage(mSLC) ampcor.setSlaveSlcImage(sSLC) #MATCH REGION #compute an offset at image center to use rgoff = -(swath2.startingRange - swath1.startingRange) / swath1.rangePixelSize azoff = -( (swath2.sensingStart - swath1.sensingStart).total_seconds()) / swath1.azimuthLineInterval rgoff = int(rgoff) azoff = int(azoff) #it seems that we cannot use 0, haven't look into the problem if rgoff == 0: rgoff = 1 if azoff == 0: azoff = 1 firstSample = 1 if rgoff < 0: firstSample = int(35 - rgoff) firstLine = 1 if azoff < 0: firstLine = int(35 - azoff) ampcor.setAcrossGrossOffset(rgoff) ampcor.setDownGrossOffset(azoff) ampcor.setFirstSampleAcross(firstSample) ampcor.setLastSampleAcross(mSLC.width) ampcor.setNumberLocationAcross(30) ampcor.setFirstSampleDown(firstLine) ampcor.setLastSampleDown(mSLC.length) ampcor.setNumberLocationDown(10) #MATCH PARAMETERS #full-aperture mode if matchingMode == 0: ampcor.setWindowSizeWidth(64) ampcor.setWindowSizeHeight(512) #note this is the half width/length of search area, number of resulting correlation samples: 32*2+1 ampcor.setSearchWindowSizeWidth(32) ampcor.setSearchWindowSizeHeight(32) #triggering full-aperture mode matching ampcor.setWinsizeFilt(8) ampcor.setOversamplingFactorFilt(64) #regular mode else: ampcor.setWindowSizeWidth(64) ampcor.setWindowSizeHeight(64) ampcor.setSearchWindowSizeWidth(32) ampcor.setSearchWindowSizeHeight(32) #REST OF THE STUFF ampcor.setAcrossLooks(1) ampcor.setDownLooks(1) ampcor.setOversamplingFactor(64) ampcor.setZoomWindowSize(16) #1. The following not set #Matching Scale for Sample/Line Directions (-) = 1. 1. #should add the following in Ampcor.py? #if not set, in this case, Ampcor.py'value is also 1. 1. #ampcor.setScaleFactorX(1.) #ampcor.setScaleFactorY(1.) #MATCH THRESHOLDS AND DEBUG DATA #2. The following not set #in roi_pac the value is set to 0 1 #in isce the value is set to 0.001 1000.0 #SNR and Covariance Thresholds (-) = {s1} {s2} #should add the following in Ampcor? #THIS SHOULD BE THE ONLY THING THAT IS DIFFERENT FROM THAT OF ROI_PAC #ampcor.setThresholdSNR(0) #ampcor.setThresholdCov(1) ampcor.setDebugFlag(False) ampcor.setDisplayFlag(False) #in summary, only two things not set which are indicated by 'The following not set' above. #run ampcor ampcor.ampcor() offsets = ampcor.getOffsetField() #ampcorOffsetFile = 'ampcor.off' #writeOffset(offsets, ampcorOffsetFile) #finalize image, and re-create it #otherwise the file pointer is still at the end of the image mSLC.finalizeImage() sSLC.finalizeImage() ############################################# #3. cull offsets ############################################# #refinedOffsets = cullOffsets(offsets) refinedOffsets = cullOffsetsRoipac(offsets, numThreshold=50) if refinedOffsets != None: rangeOffset, azimuthOffset = meanOffset(refinedOffsets) return (rangeOffset, azimuthOffset) else: return None
def estimateOffsetField(burst, simfile,offset=0.0): ''' Estimate offset field between burst and simamp. ''' sim = isceobj.createImage() sim.load(simfile+'.xml') sim.setAccessMode('READ') sim.createImage() sar = isceobj.createSlcImage() sar.load(burst.getImage().filename + '.xml') sar.setAccessMode('READ') sar.createImage() width = sar.getWidth() length = sar.getLength() objOffset = Ampcor(name='reference_offset') objOffset.configure() objOffset.setWindowSizeWidth(128) objOffset.setWindowSizeHeight(128) objOffset.setSearchWindowSizeWidth(16) objOffset.setSearchWindowSizeHeight(16) margin = 2*objOffset.searchWindowSizeWidth + objOffset.windowSizeWidth nAcross = 40 nDown = 40 if not objOffset.firstSampleAcross: objOffset.setFirstSampleAcross(margin+101) if not objOffset.lastSampleAcross: objOffset.setLastSampleAcross(width-margin-101) if not objOffset.firstSampleDown: objOffset.setFirstSampleDown(margin+offset+101) if not objOffset.lastSampleDown: objOffset.setLastSampleDown(length - margin-101) if not objOffset.acrossGrossOffset: objOffset.setAcrossGrossOffset(0.0) if not objOffset.downGrossOffset: objOffset.setDownGrossOffset(offset) if not objOffset.numberLocationAcross: objOffset.setNumberLocationAcross(nAcross) if not objOffset.numberLocationDown: objOffset.setNumberLocationDown(nDown) objOffset.setFirstPRF(1.0) objOffset.setSecondPRF(1.0) objOffset.setImageDataType1('complex') objOffset.setImageDataType2('real') objOffset.ampcor(sar, sim) sar.finalizeImage() sim.finalizeImage() result = objOffset.getOffsetField() return result