def snaphuUnwrapOriginal(wrapName, corName, ampName, unwrapName, costMode='s', initMethod='mcf'): ''' unwrap interferogram using original snaphu program ''' import numpy as np import isceobj corImg = isceobj.createImage() corImg.load(corName + '.xml') width = corImg.width length = corImg.length #specify coherence file format in configure file snaphuConfFile = 'snaphu.conf' if corImg.bands == 1: snaphuConf = '''CORRFILEFORMAT FLOAT_DATA CONNCOMPFILE {} MAXNCOMPS 20'''.format(unwrapName + '.conncomp') else: snaphuConf = '''CORRFILEFORMAT FLOAT_DATA CONNCOMPFILE {} MAXNCOMPS 20'''.format(unwrapName + '.conncomp') with open(snaphuConfFile, 'w') as f: f.write(snaphuConf) cmd = 'snaphu {} {} -f {} -{} -o {} -a {} -c {} -v --{}'.format( wrapName, width, snaphuConfFile, costMode, unwrapName, ampName, corName, initMethod) runCmd(cmd) create_xml(unwrapName, width, length, 'unw') connImage = isceobj.Image.createImage() connImage.setFilename(unwrapName + '.conncomp') connImage.setWidth(width) connImage.setAccessMode('read') connImage.setDataType('BYTE') connImage.renderVRT() connImage.createImage() connImage.finalizeImage() connImage.renderHdr() del connImage #remove wired things in no-data area amp = np.memmap(unwrapName, dtype='float32', mode='r+', shape=(length * 2, width)) wrap = np.fromfile(wrapName, dtype=np.complex64).reshape(length, width) (amp[0:length * 2:2, :])[np.nonzero(wrap == 0)] = 0 (amp[1:length * 2:2, :])[np.nonzero(wrap == 0)] = 0 del amp del wrap return
def runLook(self): '''take looks ''' catalog = isceobj.Catalog.createCatalog(self._insar.procDoc.name) self.updateParamemetersFromUser() #masterTrack = self._insar.loadTrack(master=True) #slaveTrack = self._insar.loadTrack(master=False) wbdFile = os.path.abspath(self._insar.wbd) insarDir = 'insar' if not os.path.exists(insarDir): os.makedirs(insarDir) os.chdir(insarDir) amp = isceobj.createImage() amp.load(self._insar.amplitude+'.xml') width = amp.width length = amp.length width2 = int(width / self._insar.numberRangeLooks2) length2 = int(length / self._insar.numberAzimuthLooks2) if not ((self._insar.numberRangeLooks2 == 1) and (self._insar.numberAzimuthLooks2 == 1)): #take looks look(self._insar.differentialInterferogram, self._insar.multilookDifferentialInterferogram, width, self._insar.numberRangeLooks2, self._insar.numberAzimuthLooks2, 4, 0, 1) look(self._insar.amplitude, self._insar.multilookAmplitude, width, self._insar.numberRangeLooks2, self._insar.numberAzimuthLooks2, 4, 1, 1) look(self._insar.latitude, self._insar.multilookLatitude, width, self._insar.numberRangeLooks2, self._insar.numberAzimuthLooks2, 3, 0, 1) look(self._insar.longitude, self._insar.multilookLongitude, width, self._insar.numberRangeLooks2, self._insar.numberAzimuthLooks2, 3, 0, 1) look(self._insar.height, self._insar.multilookHeight, width, self._insar.numberRangeLooks2, self._insar.numberAzimuthLooks2, 3, 0, 1) #creat xml create_xml(self._insar.multilookDifferentialInterferogram, width2, length2, 'int') create_xml(self._insar.multilookAmplitude, width2, length2, 'amp') create_xml(self._insar.multilookLatitude, width2, length2, 'double') create_xml(self._insar.multilookLongitude, width2, length2, 'double') create_xml(self._insar.multilookHeight, width2, length2, 'double') #los has two bands, use look program in isce instead cmd = "looks.py -i {} -o {} -r {} -a {}".format(self._insar.los, self._insar.multilookLos, self._insar.numberRangeLooks2, self._insar.numberAzimuthLooks2) runCmd(cmd) #water body #this looking operation has no problems where there is only water and land, but there is also possible no-data area #look(self._insar.wbdOut, self._insar.multilookWbdOut, width, self._insar.numberRangeLooks2, self._insar.numberAzimuthLooks2, 0, 0, 1) #create_xml(self._insar.multilookWbdOut, width2, length2, 'byte') #use waterBodyRadar instead to avoid the problems of no-data pixels in water body waterBodyRadar(self._insar.multilookLatitude, self._insar.multilookLongitude, wbdFile, self._insar.multilookWbdOut) os.chdir('../') catalog.printToLog(logger, "runLook") self._insar.procDoc.addAllFromCatalog(catalog)
def simulateRadar(hgtfile, simfile, scale=3.0, offset=100.0): ''' simulate a radar image by computing gradient of a dem image. ''' import numpy as np import isceobj from isceobj.Alos2Proc.Alos2ProcPublic import create_xml #set chunk length here for efficient processing ############################################### chunk_length = 1000 ############################################### hgt = isceobj.createImage() hgt.load(hgtfile + '.xml') chunk_width = hgt.width num_chunk = int(hgt.length / chunk_length) chunk_length_last = hgt.length - num_chunk * chunk_length simData = np.zeros((chunk_length, chunk_width), dtype=np.float32) hgtfp = open(hgtfile, 'rb') simfp = open(simfile, 'wb') print("simulating a radar image using topography") for i in range(num_chunk): print("processing chunk %6d of %6d" % (i + 1, num_chunk), end='\r', flush=True) hgtData = np.fromfile(hgtfp, dtype=np.float64, count=chunk_length * chunk_width).reshape( chunk_length, chunk_width) simData[:, 0:chunk_width - 1] = scale * np.diff(hgtData, axis=1) + offset simData.astype(np.float32).tofile(simfp) print("processing chunk %6d of %6d" % (num_chunk, num_chunk)) if chunk_length_last != 0: hgtData = np.fromfile(hgtfp, dtype=np.float64, count=chunk_length_last * chunk_width).reshape( chunk_length_last, chunk_width) simData[0:chunk_length_last, 0:chunk_width - 1] = scale * np.diff(hgtData, axis=1) + offset (simData[0:chunk_length_last, :]).astype(np.float32).tofile(simfp) hgtfp.close() simfp.close() create_xml(simfile, hgt.width, hgt.length, 'float')
def formInterferogram(slcReference, slcSecondary, interferogram, amplitude, numberRangeLooks, numberAzimuthLooks): import numpy as np import isce, isceobj from isceobj.Alos2Proc.Alos2ProcPublic import multilook from isceobj.Alos2Proc.Alos2ProcPublic import create_xml img = isceobj.createImage() img.load(slcReference + '.xml') width = img.width length = img.length width2 = int(width / numberRangeLooks) length2 = int(length / numberAzimuthLooks) fpRef = open(slcReference, 'rb') fpSec = open(slcSecondary, 'rb') fpInf = open(interferogram, 'wb') fpAmp = open(amplitude, 'wb') for k in range(length2): if (((k + 1) % 200) == 0): print("processing line %6d of %6d" % (k + 1, length2), end='\r', flush=True) ref = np.fromfile(fpRef, dtype=np.complex64, count=numberAzimuthLooks * width).reshape( numberAzimuthLooks, width) sec = np.fromfile(fpSec, dtype=np.complex64, count=numberAzimuthLooks * width).reshape( numberAzimuthLooks, width) inf = multilook(ref * np.conjugate(sec), numberAzimuthLooks, numberRangeLooks, mean=False) amp = np.sqrt(multilook(ref.real*ref.real+ref.imag*ref.imag, numberAzimuthLooks, numberRangeLooks, mean=False)) + 1j * \ np.sqrt(multilook(sec.real*sec.real+sec.imag*sec.imag, numberAzimuthLooks, numberRangeLooks, mean=False)) index = np.nonzero((np.real(amp) == 0) + (np.imag(amp) == 0)) amp[index] = 0 inf.tofile(fpInf) amp.tofile(fpAmp) print("processing line %6d of %6d" % (length2, length2)) fpRef.close() fpSec.close() fpInf.close() fpAmp.close() create_xml(interferogram, width2, length2, 'int') create_xml(amplitude, width2, length2, 'amp')
def mosaicBurstInterferogram(swath, burstPrefix, outputFile, numberOfLooksThreshold=1): ''' take a burst sequence and output mosaicked file ''' import numpy as np interferogram = np.zeros((swath.numberOfLines, swath.numberOfSamples), dtype=np.complex64) cnt = np.zeros((swath.numberOfLines, swath.numberOfSamples), dtype=np.int8) for i in range(swath.numberOfBursts): burstFile = burstPrefix + '_%02d.int' % (i + 1) burstInterferogram = np.fromfile(burstFile, dtype=np.complex64).reshape( swath.burstSlcNumberOfLines, swath.burstSlcNumberOfSamples) interferogram[ 0 + swath.burstSlcFirstLineOffsets[i]:swath.burstSlcNumberOfLines + swath.burstSlcFirstLineOffsets[i], :] += burstInterferogram cnt[0 + swath.burstSlcFirstLineOffsets[i]:swath.burstSlcNumberOfLines + swath.burstSlcFirstLineOffsets[i], :] += (burstInterferogram != 0) #trim upper and lower edges with less number of looks ############################################################################# firstLine = 0 for i in range(swath.numberOfLines): if np.sum(cnt[i, :] >= numberOfLooksThreshold ) > swath.numberOfSamples / 2: firstLine = i break lastLine = swath.numberOfLines - 1 for i in range(swath.numberOfLines): if np.sum(cnt[swath.numberOfLines - 1 - i, :] >= numberOfLooksThreshold ) > swath.numberOfSamples / 2: lastLine = swath.numberOfLines - 1 - i break interferogram[:firstLine, :] = 0 interferogram[lastLine + 1:, :] = 0 # if numberOfLooksThreshold!= None: # interferogram[np.nonzero(cnt<numberOfLooksThreshold)] = 0 ############################################################################# interferogram.astype(np.complex64).tofile(outputFile) create_xml(outputFile, swath.numberOfSamples, swath.numberOfLines, 'int')
def mosaicBurstAmplitude(swath, burstPrefix, outputFile, numberOfLooksThreshold=1): ''' take a burst sequence and output the magnitude ''' import numpy as np amp = np.zeros((swath.numberOfLines, swath.numberOfSamples), dtype=np.float32) cnt = np.zeros((swath.numberOfLines, swath.numberOfSamples), dtype=np.int8) for i in range(swath.numberOfBursts): burstFile = burstPrefix + '_%02d.slc' % (i + 1) #azLineOffset = round((swath.burstSlcStartTimes[i] - swath.burstSlcStartTimes[0]).total_seconds() / swath.azimuthLineInterval) burstMag = np.absolute( np.fromfile(burstFile, dtype=np.complex64).reshape( swath.burstSlcNumberOfLines, swath.burstSlcNumberOfSamples)) burstPwr = burstMag * burstMag amp[0 + swath.burstSlcFirstLineOffsets[i]:swath.burstSlcNumberOfLines + swath.burstSlcFirstLineOffsets[i], :] += burstPwr cnt[0 + swath.burstSlcFirstLineOffsets[i]:swath.burstSlcNumberOfLines + swath.burstSlcFirstLineOffsets[i], :] += (burstPwr != 0) #trim upper and lower edges with less number of looks ############################################################################# firstLine = 0 for i in range(swath.numberOfLines): if np.sum(cnt[i, :] >= numberOfLooksThreshold ) > swath.numberOfSamples / 2: firstLine = i break lastLine = swath.numberOfLines - 1 for i in range(swath.numberOfLines): if np.sum(cnt[swath.numberOfLines - 1 - i, :] >= numberOfLooksThreshold ) > swath.numberOfSamples / 2: lastLine = swath.numberOfLines - 1 - i break amp[:firstLine, :] = 0 amp[lastLine + 1:, :] = 0 # if numberOfLooksThreshold!= None: # amp[np.nonzero(cnt<numberOfLooksThreshold)] = 0 ############################################################################# np.sqrt(amp).astype(np.float32).tofile(outputFile) create_xml(outputFile, swath.numberOfSamples, swath.numberOfLines, 'float')
def runRectRangeOffset(self): '''rectify range offset ''' 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) insarDir = 'insar' os.makedirs(insarDir, exist_ok=True) os.chdir(insarDir) #rectify rgoff = isceobj.createImage() rgoff.load(self._insar.rangeOffset+'.xml') if self._insar.radarDemAffineTransform == [1.0, 0.0, 0.0, 1.0, 0.0, 0.0]: if not os.path.isfile(self._insar.rectRangeOffset): os.symlink(self._insar.rangeOffset, self._insar.rectRangeOffset) create_xml(self._insar.rectRangeOffset, rgoff.width, rgoff.length, 'float') else: rect_with_looks(self._insar.rangeOffset, self._insar.rectRangeOffset, rgoff.width, rgoff.length, rgoff.width, rgoff.length, self._insar.radarDemAffineTransform[0], self._insar.radarDemAffineTransform[1], self._insar.radarDemAffineTransform[2], self._insar.radarDemAffineTransform[3], self._insar.radarDemAffineTransform[4], self._insar.radarDemAffineTransform[5], self._insar.numberRangeLooksSim*self._insar.numberRangeLooks1, self._insar.numberAzimuthLooksSim*self._insar.numberAzimuthLooks1, self._insar.numberRangeLooks1, self._insar.numberAzimuthLooks1, 'REAL', 'Bilinear') create_xml(self._insar.rectRangeOffset, rgoff.width, rgoff.length, 'float') os.chdir('../') catalog.printToLog(logger, "runRectRangeOffset") self._insar.procDoc.addAllFromCatalog(catalog)
def runLookSd(self): '''take looks ''' catalog = isceobj.Catalog.createCatalog(self._insar.procDoc.name) self.updateParamemetersFromUser() #masterTrack = self._insar.loadTrack(master=True) #slaveTrack = self._insar.loadTrack(master=False) wbdFile = os.path.abspath(self._insar.wbd) sdDir = 'sd' if not os.path.exists(sdDir): os.makedirs(sdDir) os.chdir(sdDir) sd = isceobj.createImage() sd.load(self._insar.interferogramSd[0] + '.xml') width = sd.width length = sd.length width2 = int(width / self._insar.numberRangeLooksSd) length2 = int(length / self._insar.numberAzimuthLooksSd) if not ((self._insar.numberRangeLooksSd == 1) and (self._insar.numberAzimuthLooksSd == 1)): #take looks for sd, sdMultilook in zip(self._insar.interferogramSd, self._insar.multilookInterferogramSd): look(sd, sdMultilook, width, self._insar.numberRangeLooksSd, self._insar.numberAzimuthLooksSd, 4, 0, 1) create_xml(sdMultilook, width2, length2, 'int') look(os.path.join('../insar', self._insar.latitude), self._insar.multilookLatitudeSd, width, self._insar.numberRangeLooksSd, self._insar.numberAzimuthLooksSd, 3, 0, 1) look(os.path.join('../insar', self._insar.longitude), self._insar.multilookLongitudeSd, width, self._insar.numberRangeLooksSd, self._insar.numberAzimuthLooksSd, 3, 0, 1) create_xml(self._insar.multilookLatitudeSd, width2, length2, 'double') create_xml(self._insar.multilookLongitudeSd, width2, length2, 'double') #water body waterBodyRadar(self._insar.multilookLatitudeSd, self._insar.multilookLongitudeSd, wbdFile, self._insar.multilookWbdOutSd) os.chdir('../') catalog.printToLog(logger, "runLookSd") self._insar.procDoc.addAllFromCatalog(catalog)
def runExtractBurst(self): '''extract bursts. ''' 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) ############################################################################### 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('extracting bursts frame {}, swath {}'.format( frameNumber, swathNumber)) az_ratio1 = 20.0 for k in range(2): if k == 0: #master swath = masterTrack.frames[i].swaths[j] unsynLines = self._insar.burstUnsynchronizedTime * swath.prf extractDir = self._insar.masterBurstPrefix burstPrefix = self._insar.masterBurstPrefix fullApertureSlc = self._insar.masterSlc magnitude = self._insar.masterMagnitude else: #slave swath = slaveTrack.frames[i].swaths[j] unsynLines = -self._insar.burstUnsynchronizedTime * swath.prf extractDir = self._insar.slaveBurstPrefix burstPrefix = self._insar.slaveBurstPrefix fullApertureSlc = self._insar.slaveSlc magnitude = self._insar.slaveMagnitude #UPDATE SWATH PARAMETERS 1 ######################################################################################### if self._insar.burstSynchronization <= self.burstSynchronizationThreshold: swath.burstLength -= abs(unsynLines) if unsynLines < 0: swath.burstStartTime += datetime.timedelta( seconds=abs(unsynLines) / swath.prf) ######################################################################################### #extract burst os.makedirs(extractDir, exist_ok=True) os.chdir(extractDir) if os.path.isfile(os.path.join('../', fullApertureSlc)): os.rename(os.path.join('../', fullApertureSlc), fullApertureSlc) os.rename(os.path.join('../', fullApertureSlc + '.vrt'), fullApertureSlc + '.vrt') os.rename(os.path.join('../', fullApertureSlc + '.xml'), fullApertureSlc + '.xml') extract_burst(fullApertureSlc, burstPrefix, swath.prf, swath.prfFraction, swath.burstLength, swath.burstCycleLength-swath.burstLength, \ (swath.burstStartTime - swath.sensingStart).total_seconds() * swath.prf, swath.azimuthFmrateVsPixel, swath.dopplerVsPixel, az_ratio1, 0.0) #read output parameters with open('extract_burst.txt', 'r') as f: lines = f.readlines() offsetFromFirstBurst = [] for linex in lines: if 'total number of bursts extracted' in linex: numberOfBursts = int(linex.split(':')[1]) if 'output burst length' in linex: burstSlcNumberOfLines = int(linex.split(':')[1]) if 'line number of first line of first output burst in original SLC (1.0/prf)' in linex: fb_ln = float(linex.split(':')[1]) if 'bsl of first output burst' in linex: bsl_firstburst = float(linex.split(':')[1]) if 'offset from first burst' in linex: offsetFromFirstBurst.append( int(linex.split(',')[0].split(':')[1])) #time of first line of first burst raw firstBurstRawStartTime = swath.sensingStart + datetime.timedelta( seconds=bsl_firstburst / swath.prf) #time of first line of first burst slc #original time is at the upper edge of first line, we change it to center of first line. sensingStart = swath.sensingStart + datetime.timedelta( seconds=fb_ln / swath.prf + (az_ratio1 - 1.0) / 2.0 / swath.prf) numberOfLines = offsetFromFirstBurst[numberOfBursts - 1] + burstSlcNumberOfLines for ii in range(numberOfBursts): burstFile = burstPrefix + '_%02d.slc' % (ii + 1) create_xml(burstFile, swath.numberOfSamples, burstSlcNumberOfLines, 'slc') #UPDATE SWATH PARAMETERS 2 ######################################################################################### swath.numberOfLines = numberOfLines #this is also the time of the first line of the first burst slc swath.sensingStart = sensingStart swath.azimuthPixelSize = az_ratio1 * swath.azimuthPixelSize swath.azimuthLineInterval = az_ratio1 * swath.azimuthLineInterval swath.numberOfBursts = numberOfBursts swath.firstBurstRawStartTime = firstBurstRawStartTime swath.firstBurstSlcStartTime = sensingStart swath.burstSlcFirstLineOffsets = offsetFromFirstBurst swath.burstSlcNumberOfSamples = swath.numberOfSamples swath.burstSlcNumberOfLines = burstSlcNumberOfLines ######################################################################################### #create a magnitude image mosaicBurstAmplitude(swath, burstPrefix, magnitude, numberOfLooksThreshold=4) os.chdir('../') os.chdir('../') self._insar.saveProduct(masterTrack.frames[i], self._insar.masterFrameParameter) self._insar.saveProduct(slaveTrack.frames[i], self._insar.slaveFrameParameter) os.chdir('../') ############################################################################### catalog.printToLog(logger, "runExtractBurst") self._insar.procDoc.addAllFromCatalog(catalog)
def runFilt(self): '''filter interferogram ''' catalog = isceobj.Catalog.createCatalog(self._insar.procDoc.name) self.updateParamemetersFromUser() #masterTrack = self._insar.loadTrack(master=True) #slaveTrack = self._insar.loadTrack(master=False) insarDir = 'insar' os.makedirs(insarDir, exist_ok=True) os.chdir(insarDir) ############################################################ # STEP 1. filter interferogram ############################################################ print('\nfilter interferogram: {}'.format( self._insar.multilookDifferentialInterferogram)) toBeFiltered = self._insar.multilookDifferentialInterferogram if self.removeMagnitudeBeforeFiltering: toBeFiltered = 'tmp.int' cmd = "imageMath.py -e='a/(abs(a)+(a==0))' --a={} -o {} -t cfloat -s BSQ".format( self._insar.multilookDifferentialInterferogram, toBeFiltered) runCmd(cmd) #if shutil.which('psfilt1') != None: if True: intImage = isceobj.createIntImage() intImage.load(toBeFiltered + '.xml') width = intImage.width length = intImage.length # cmd = "psfilt1 {int} {filtint} {width} {filterstrength} 64 16".format( # int = toBeFiltered, # filtint = self._insar.filteredInterferogram, # width = width, # filterstrength = self.filterStrength # ) # runCmd(cmd) windowSize = self.filterWinsize stepSize = self.filterStepsize psfilt1(toBeFiltered, self._insar.filteredInterferogram, width, self.filterStrength, windowSize, stepSize) create_xml(self._insar.filteredInterferogram, width, length, 'int') else: #original intImage = isceobj.createIntImage() intImage.load(toBeFiltered + '.xml') intImage.setAccessMode('read') intImage.createImage() width = intImage.width length = intImage.length #filtered filtImage = isceobj.createIntImage() filtImage.setFilename(self._insar.filteredInterferogram) filtImage.setWidth(width) filtImage.setAccessMode('write') filtImage.createImage() #looks like the ps filtering program keep the original interferogram magnitude, which is bad for phase unwrapping? filters = Filter() filters.wireInputPort(name='interferogram', object=intImage) filters.wireOutputPort(name='filtered interferogram', object=filtImage) filters.goldsteinWerner(alpha=self.filterStrength) intImage.finalizeImage() filtImage.finalizeImage() del intImage, filtImage, filters if self.removeMagnitudeBeforeFiltering: os.remove(toBeFiltered) os.remove(toBeFiltered + '.vrt') os.remove(toBeFiltered + '.xml') #restore original magnitude tmpFile = 'tmp.int' renameFile(self._insar.filteredInterferogram, tmpFile) cmd = "imageMath.py -e='a*abs(b)' --a={} --b={} -o {} -t cfloat -s BSQ".format( tmpFile, self._insar.multilookDifferentialInterferogram, self._insar.filteredInterferogram) runCmd(cmd) os.remove(tmpFile) os.remove(tmpFile + '.vrt') os.remove(tmpFile + '.xml') ############################################################ # STEP 2. create phase sigma using filtered interferogram ############################################################ print('\ncreate phase sigma using: {}'.format( self._insar.filteredInterferogram)) #recreate filtered image filtImage = isceobj.createIntImage() filtImage.load(self._insar.filteredInterferogram + '.xml') filtImage.setAccessMode('read') filtImage.createImage() #amplitude image ampImage = isceobj.createAmpImage() ampImage.load(self._insar.multilookAmplitude + '.xml') ampImage.setAccessMode('read') ampImage.createImage() #phase sigma correlation image phsigImage = isceobj.createImage() phsigImage.setFilename(self._insar.multilookPhsig) phsigImage.setWidth(width) phsigImage.dataType = 'FLOAT' phsigImage.bands = 1 phsigImage.setImageType('cor') phsigImage.setAccessMode('write') phsigImage.createImage() icu = Icu(name='insarapp_filter_icu') icu.configure() icu.unwrappingFlag = False icu.icu(intImage=filtImage, ampImage=ampImage, phsigImage=phsigImage) phsigImage.renderHdr() filtImage.finalizeImage() ampImage.finalizeImage() phsigImage.finalizeImage() del filtImage del ampImage del phsigImage del icu ############################################################ # STEP 3. mask filtered interferogram using water body ############################################################ print('\nmask filtered interferogram using: {}'.format( self._insar.multilookWbdOut)) if self.waterBodyMaskStartingStep == 'filt': if not os.path.exists(self._insar.multilookWbdOut): catalog.addItem( 'warning message', 'requested masking interferogram with water body, but water body does not exist', 'runFilt') else: wbd = np.fromfile(self._insar.multilookWbdOut, dtype=np.int8).reshape(length, width) phsig = np.memmap(self._insar.multilookPhsig, dtype='float32', mode='r+', shape=(length, width)) phsig[np.nonzero(wbd == -1)] = 0 del phsig filt = np.memmap(self._insar.filteredInterferogram, dtype='complex64', mode='r+', shape=(length, width)) filt[np.nonzero(wbd == -1)] = 0 del filt del wbd os.chdir('../') catalog.printToLog(logger, "runFilt") self._insar.procDoc.addAllFromCatalog(catalog)
dates[dateIndexReference], dates[i], Bpar, Bperp) if dateSecondary != []: if dates[i] not in dateSecondary: continue #compute baseline grid if baselineGrid: baselineFile = '{}-{}.rmg'.format(dates[dateIndexReference], dates[i]) if os.path.isfile(baselineFile): print('baseline grid file {} already exists, do not create'. format(baselineFile)) else: for j in range(lengthBaseline): for k in range(widthBaseline): (baseline[j * 2, k], baseline[j * 2 + 1, k]) = computeBaseline( trackReference, trackSecondary, azimuthTimeMin + datetime.timedelta(seconds=azimuthDelta * j), rangeMin + rangeDelta * k) baseline.astype(np.float32).tofile(baselineFile) create_xml(baselineFile, widthBaseline, lengthBaseline, 'rmg') #dump baseline at image center if baselineCenterFile is not None: print('\nbaselines at image centers') print(baselineCenter) with open(baselineCenterFile, 'w') as f: f.write(baselineCenter)
img.load(latitude + '.xml') width = img.width length = img.length width2 = int(width / numberRangeLooks2) length2 = int(length / numberAzimuthLooks2) if not ((numberRangeLooks2 == 1) and (numberAzimuthLooks2 == 1)): #take looks look(latitude, multilookLatitude, width, numberRangeLooks2, numberAzimuthLooks2, 3, 0, 1) look(longitude, multilookLongitude, width, numberRangeLooks2, numberAzimuthLooks2, 3, 0, 1) look(height, multilookHeight, width, numberRangeLooks2, numberAzimuthLooks2, 3, 0, 1) #creat xml create_xml(multilookLatitude, width2, length2, 'double') create_xml(multilookLongitude, width2, length2, 'double') create_xml(multilookHeight, width2, length2, 'double') #los has two bands, use look program in isce instead #cmd = "looks.py -i {} -o {} -r {} -a {}".format(self._insar.los, self._insar.multilookLos, self._insar.numberRangeLooks2, self._insar.numberAzimuthLooks2) #runCmd(cmd) #replace the above system call with function call from mroipac.looks.Looks import Looks from isceobj.Image import createImage inImage = createImage() inImage.load(los + '.xml') lkObj = Looks() lkObj.setDownLooks(numberAzimuthLooks2) lkObj.setAcrossLooks(numberRangeLooks2)
index2 = np.linspace(0, width2-1, num=width2, endpoint=True) index3 = np.linspace(0, width3-1, num=width3, endpoint=True) * nrlo/nrli + (nrlo-nrli)/(2.0*nrli) ionrect = np.zeros((length3, width3), dtype=np.float32) for i in range(length2): f = interp1d(index2, ionfilt[i,:], kind='cubic', fill_value="extrapolate") ionrect[i, :] = f(index3) index2 = np.linspace(0, length2-1, num=length2, endpoint=True) index3 = np.linspace(0, length3-1, num=length3, endpoint=True) * nalo/nali + (nalo-nali)/(2.0*nali) for j in range(width3): f = interp1d(index2, ionrect[0:length2, j], kind='cubic', fill_value="extrapolate") ionrect[:, j] = f(index3) ionrectfile = 'filt_ion_'+dates2[idate]+ml3+'.ion' ionrect.astype(np.float32).tofile(ionrectfile) create_xml(ionrectfile, width3, length3, 'float') else: ionrectfile = 'filt_ion_'+dates2[idate]+ml2+'.ion' ts[idate, :, :].astype(np.float32).tofile(ionrectfile) create_xml(ionrectfile, width, length, 'float') if interp and ((numberRangeLooks2 != numberRangeLooksIon) or (numberAzimuthLooks2 != numberAzimuthLooksIon)): ionrectfile = 'filt_ion_'+dateZero+ml3+'.ion' (np.zeros((length3, width3), dtype=np.float32)).astype(np.float32).tofile(ionrectfile) create_xml(ionrectfile, width3, length3, 'float') else: ionrectfile = 'filt_ion_'+dateZero+ml2+'.ion' (np.zeros((length, width), dtype=np.float32)).astype(np.float32).tofile(ionrectfile) create_xml(ionrectfile, width, length, 'float') os.chdir(cdir)
def runSlcMosaic(self): '''mosaic SLCs ''' if not self.doDenseOffset: print( '\ndense offset not requested, skip this and the remaining steps...' ) return if not ((self._insar.modeCombination == 0) or (self._insar.modeCombination == 1)): print( 'dense offset only support spotligh-spotlight and stripmap-stripmap pairs' ) return catalog = isceobj.Catalog.createCatalog(self._insar.procDoc.name) self.updateParamemetersFromUser() referenceTrack = self._insar.loadTrack(reference=True) secondaryTrack = self._insar.loadTrack(reference=False) denseOffsetDir = 'dense_offset' os.makedirs(denseOffsetDir, exist_ok=True) os.chdir(denseOffsetDir) ################################################## # estimate reference and secondary frame offsets ################################################## if len(referenceTrack.frames) > 1: matchingMode = 1 #if reference offsets from matching are not already computed if self.frameOffsetMatching == False: offsetReference = frameOffset(referenceTrack, self._insar.referenceSlc, self._insar.referenceFrameOffset, crossCorrelation=True, matchingMode=matchingMode) offsetSecondary = frameOffset(secondaryTrack, self._insar.secondarySlc, self._insar.secondaryFrameOffset, crossCorrelation=True, matchingMode=matchingMode) if self.frameOffsetMatching == False: self._insar.frameRangeOffsetMatchingReference = offsetReference[2] self._insar.frameAzimuthOffsetMatchingReference = offsetReference[ 3] self._insar.frameRangeOffsetMatchingSecondary = offsetSecondary[2] self._insar.frameAzimuthOffsetMatchingSecondary = offsetSecondary[3] ################################################## # mosaic slc ################################################## numberOfFrames = len(referenceTrack.frames) if numberOfFrames == 1: import shutil #frameDir = os.path.join('f1_{}/mosaic'.format(self._insar.referenceFrames[0])) frameDir = os.path.join('f1_{}/s{}'.format( self._insar.referenceFrames[0], self._insar.startingSwath)) if not os.path.isfile(self._insar.referenceSlc): if os.path.isfile( os.path.join('../', frameDir, self._insar.referenceSlc)): os.symlink( os.path.join('../', frameDir, self._insar.referenceSlc), self._insar.referenceSlc) #shutil.copy2() can overwrite shutil.copy2( os.path.join('../', frameDir, self._insar.referenceSlc + '.vrt'), self._insar.referenceSlc + '.vrt') shutil.copy2( os.path.join('../', frameDir, self._insar.referenceSlc + '.xml'), self._insar.referenceSlc + '.xml') if not os.path.isfile(self._insar.secondarySlc): if os.path.isfile( os.path.join('../', frameDir, self._insar.secondarySlc)): os.symlink( os.path.join('../', frameDir, self._insar.secondarySlc), self._insar.secondarySlc) shutil.copy2( os.path.join('../', frameDir, self._insar.secondarySlc + '.vrt'), self._insar.secondarySlc + '.vrt') shutil.copy2( os.path.join('../', frameDir, self._insar.secondarySlc + '.xml'), self._insar.secondarySlc + '.xml') #update track parameters ######################################################### #mosaic size referenceTrack.numberOfSamples = referenceTrack.frames[0].swaths[ 0].numberOfSamples referenceTrack.numberOfLines = referenceTrack.frames[0].swaths[ 0].numberOfLines #NOTE THAT WE ARE STILL USING SINGLE LOOK PARAMETERS HERE #range parameters referenceTrack.startingRange = referenceTrack.frames[0].swaths[ 0].startingRange referenceTrack.rangeSamplingRate = referenceTrack.frames[0].swaths[ 0].rangeSamplingRate referenceTrack.rangePixelSize = referenceTrack.frames[0].swaths[ 0].rangePixelSize #azimuth parameters referenceTrack.sensingStart = referenceTrack.frames[0].swaths[ 0].sensingStart referenceTrack.prf = referenceTrack.frames[0].swaths[0].prf referenceTrack.azimuthPixelSize = referenceTrack.frames[0].swaths[ 0].azimuthPixelSize referenceTrack.azimuthLineInterval = referenceTrack.frames[0].swaths[ 0].azimuthLineInterval referenceTrack.dopplerVsPixel = referenceTrack.frames[0].swaths[ 0].dopplerVsPixel #update track parameters, secondary ######################################################### #mosaic size secondaryTrack.numberOfSamples = secondaryTrack.frames[0].swaths[ 0].numberOfSamples secondaryTrack.numberOfLines = secondaryTrack.frames[0].swaths[ 0].numberOfLines #NOTE THAT WE ARE STILL USING SINGLE LOOK PARAMETERS HERE #range parameters secondaryTrack.startingRange = secondaryTrack.frames[0].swaths[ 0].startingRange secondaryTrack.rangeSamplingRate = secondaryTrack.frames[0].swaths[ 0].rangeSamplingRate secondaryTrack.rangePixelSize = secondaryTrack.frames[0].swaths[ 0].rangePixelSize #azimuth parameters secondaryTrack.sensingStart = secondaryTrack.frames[0].swaths[ 0].sensingStart secondaryTrack.prf = secondaryTrack.frames[0].swaths[0].prf secondaryTrack.azimuthPixelSize = secondaryTrack.frames[0].swaths[ 0].azimuthPixelSize secondaryTrack.azimuthLineInterval = secondaryTrack.frames[0].swaths[ 0].azimuthLineInterval secondaryTrack.dopplerVsPixel = secondaryTrack.frames[0].swaths[ 0].dopplerVsPixel else: #mosaic reference slc ######################################################### #choose offsets rangeOffsets = self._insar.frameRangeOffsetMatchingReference azimuthOffsets = self._insar.frameAzimuthOffsetMatchingReference #list of input files slcs = [] for i, frameNumber in enumerate(self._insar.referenceFrames): frameDir = 'f{}_{}'.format(i + 1, frameNumber) swathDir = 's{}'.format(self._insar.startingSwath) slcs.append( os.path.join('../', frameDir, swathDir, self._insar.referenceSlc)) #note that track parameters are updated after mosaicking #parameters update is checked, it is OK. frameMosaic(referenceTrack, slcs, self._insar.referenceSlc, rangeOffsets, azimuthOffsets, 1, 1, updateTrack=True, phaseCompensation=True, resamplingMethod=2) create_xml(self._insar.referenceSlc, referenceTrack.numberOfSamples, referenceTrack.numberOfLines, 'slc') referenceTrack.dopplerVsPixel = computeTrackDoppler(referenceTrack) #mosaic secondary slc ######################################################### #choose offsets rangeOffsets = self._insar.frameRangeOffsetMatchingSecondary azimuthOffsets = self._insar.frameAzimuthOffsetMatchingSecondary #list of input files slcs = [] for i, frameNumber in enumerate(self._insar.referenceFrames): frameDir = 'f{}_{}'.format(i + 1, frameNumber) swathDir = 's{}'.format(self._insar.startingSwath) slcs.append( os.path.join('../', frameDir, swathDir, self._insar.secondarySlc)) #note that track parameters are updated after mosaicking #parameters update is checked, it is OK. frameMosaic(secondaryTrack, slcs, self._insar.secondarySlc, rangeOffsets, azimuthOffsets, 1, 1, updateTrack=True, phaseCompensation=True, resamplingMethod=2) create_xml(self._insar.secondarySlc, secondaryTrack.numberOfSamples, secondaryTrack.numberOfLines, 'slc') secondaryTrack.dopplerVsPixel = computeTrackDoppler(secondaryTrack) #save parameter file inside denseoffset directory self._insar.saveProduct(referenceTrack, self._insar.referenceTrackParameter) self._insar.saveProduct(secondaryTrack, self._insar.secondaryTrackParameter) os.chdir('../') catalog.printToLog(logger, "runSlcMosaic") self._insar.procDoc.addAllFromCatalog(catalog)
def cropSlc(orbit, swath, slc, orbit2, swath2, edge=0, useVirtualFile=True): from isceobj.Alos2Proc.Alos2ProcPublic import find_vrt_keyword from isceobj.Alos2Proc.Alos2ProcPublic import create_xml ''' orbit: orbit of the image to be cropped swath: swath of the image to be cropped slc: image to be cropped orbit2: orbit of the other image swath2: swath of the other image ''' #find topleft and lowerright corners #all indices start with 0 corner = [] for x in [[0, 0], [swath2.numberOfLines - 1, swath2.numberOfSamples - 1]]: line2 = x[0] sample2 = x[1] rg2 = swath2.startingRange + swath2.rangePixelSize * sample2 az2 = swath2.sensingStart + datetime.timedelta(seconds=line2 / swath2.prf) llh2 = orbit2.rdr2geo(az2, rg2) az, rg = orbit.geo2rdr(llh2) line = (az - swath.sensingStart).total_seconds() * swath.prf sample = (rg - swath.startingRange) / swath.rangePixelSize corner.append([line, sample]) #image (to be cropped) bounds firstLine = 0 lastLine = swath.numberOfLines - 1 firstSample = 0 lastSample = swath.numberOfSamples - 1 #the othe image bounds in image (to be cropped) #add edge #edge = 9 firstLine2 = int(corner[0][0] - edge) lastLine2 = int(corner[1][0] + edge) firstSample2 = int(corner[0][1] - edge) lastSample2 = int(corner[1][1] + edge) #image (to be cropped) output bounds firstLine3 = max(firstLine, firstLine2) lastLine3 = min(lastLine, lastLine2) firstSample3 = max(firstSample, firstSample2) lastSample3 = min(lastSample, lastSample2) numberOfSamples3 = lastSample3 - firstSample3 + 1 numberOfLines3 = lastLine3 - firstLine3 + 1 #check if there is overlap if lastLine3 - firstLine3 + 1 < 1000: raise Exception( 'azimuth overlap < 1000 lines, not enough area for InSAR\n') if lastSample3 - firstSample3 + 1 < 1000: raise Exception( 'range overlap < 1000 samples, not enough area for InSAR\n') #check if there is a need to crop image if abs(firstLine3-firstLine) < 100 and abs(lastLine3-lastLine) < 100 and \ abs(firstSample3-firstSample) < 100 and abs(lastSample3-lastSample) < 100: print('no need to crop {}. nothing is done by crop.'.format(slc)) return #crop image if useVirtualFile: #vrt SourceFilename = find_vrt_keyword(slc + '.vrt', 'SourceFilename') ImageOffset = int(find_vrt_keyword(slc + '.vrt', 'ImageOffset')) PixelOffset = int(find_vrt_keyword(slc + '.vrt', 'PixelOffset')) LineOffset = int(find_vrt_keyword(slc + '.vrt', 'LineOffset')) #overwrite vrt and xml img = isceobj.createImage() img.load(slc + '.xml') img.width = numberOfSamples3 img.length = numberOfLines3 img.renderHdr() #overrite vrt with open(slc + '.vrt', 'w') as fid: fid.write('''<VRTDataset rasterXSize="{0}" rasterYSize="{1}"> <VRTRasterBand band="1" dataType="CFloat32" subClass="VRTRawRasterBand"> <SourceFilename relativeToVRT="0">{2}</SourceFilename> <ByteOrder>MSB</ByteOrder> <ImageOffset>{3}</ImageOffset> <PixelOffset>8</PixelOffset> <LineOffset>{4}</LineOffset> </VRTRasterBand> </VRTDataset>'''.format( numberOfSamples3, numberOfLines3, SourceFilename, ImageOffset + firstLine3 * LineOffset + firstSample3 * 8, LineOffset)) else: #read and crop data with open(slc, 'rb') as f: f.seek( firstLine3 * swath.numberOfSamples * np.dtype(np.complex64).itemsize, 0) data = np.fromfile(f, dtype=np.complex64, count=numberOfLines3 * swath.numberOfSamples)\ .reshape(numberOfLines3,swath.numberOfSamples) data2 = data[:, firstSample3:lastSample3 + 1] #overwrite original data2.astype(np.complex64).tofile(slc) #creat new vrt and xml os.remove(slc + '.xml') os.remove(slc + '.vrt') create_xml(slc, numberOfSamples3, numberOfLines3, 'slc') #update parameters #update doppler and azfmrate first dop = np.polyval(swath.dopplerVsPixel[::-1], np.arange(swath.numberOfSamples)) dop3 = dop[firstSample3:lastSample3 + 1] p = np.polyfit(np.arange(numberOfSamples3), dop3, 3) swath.dopplerVsPixel = [p[3], p[2], p[1], p[0]] azfmrate = np.polyval(swath.azimuthFmrateVsPixel[::-1], np.arange(swath.numberOfSamples)) azfmrate3 = azfmrate[firstSample3:lastSample3 + 1] p = np.polyfit(np.arange(numberOfSamples3), azfmrate3, 3) swath.azimuthFmrateVsPixel = [p[3], p[2], p[1], p[0]] swath.numberOfSamples = numberOfSamples3 swath.numberOfLines = numberOfLines3 swath.startingRange += firstSample3 * swath.rangePixelSize swath.sensingStart += datetime.timedelta(seconds=firstLine3 / swath.prf)
def runIonFilt(self): '''compute and filter ionospheric phase ''' catalog = isceobj.Catalog.createCatalog(self._insar.procDoc.name) self.updateParamemetersFromUser() if not self.doIon: catalog.printToLog(logger, "runIonFilt") self._insar.procDoc.addAllFromCatalog(catalog) return masterTrack = self._insar.loadTrack(master=True) slaveTrack = self._insar.loadTrack(master=False) from isceobj.Alos2Proc.runIonSubband import defineIonDir ionDir = defineIonDir() subbandPrefix = ['lower', 'upper'] ionCalDir = os.path.join(ionDir['ion'], ionDir['ionCal']) if not os.path.exists(ionCalDir): os.makedirs(ionCalDir) os.chdir(ionCalDir) ############################################################ # STEP 1. compute ionospheric phase ############################################################ from isceobj.Constants import SPEED_OF_LIGHT from isceobj.Alos2Proc.Alos2ProcPublic import create_xml ################################### #SET PARAMETERS HERE #THESE SHOULD BE GOOD ENOUGH, NO NEED TO SET IN setup(self) corThresholdAdj = 0.85 ################################### print('\ncomputing ionosphere') #get files ml2 = '_{}rlks_{}alks'.format(self._insar.numberRangeLooks1*self._insar.numberRangeLooksIon, self._insar.numberAzimuthLooks1*self._insar.numberAzimuthLooksIon) lowerUnwfile = subbandPrefix[0]+ml2+'.unw' upperUnwfile = subbandPrefix[1]+ml2+'.unw' corfile = 'diff'+ml2+'.cor' #use image size from lower unwrapped interferogram img = isceobj.createImage() img.load(lowerUnwfile + '.xml') width = img.width length = img.length lowerUnw = (np.fromfile(lowerUnwfile, dtype=np.float32).reshape(length*2, width))[1:length*2:2, :] upperUnw = (np.fromfile(upperUnwfile, dtype=np.float32).reshape(length*2, width))[1:length*2:2, :] cor = (np.fromfile(corfile, dtype=np.float32).reshape(length*2, width))[1:length*2:2, :] #amp = (np.fromfile(corfile, dtype=np.float32).reshape(length*2, width))[0:length*2:2, :] #masked out user-specified areas if self.maskedAreasIon != None: maskedAreas = reformatMaskedAreas(self.maskedAreasIon, length, width) for area in maskedAreas: lowerUnw[area[0]:area[1], area[2]:area[3]] = 0 upperUnw[area[0]:area[1], area[2]:area[3]] = 0 cor[area[0]:area[1], area[2]:area[3]] = 0 #compute ionosphere fl = SPEED_OF_LIGHT / self._insar.subbandRadarWavelength[0] fu = SPEED_OF_LIGHT / self._insar.subbandRadarWavelength[1] adjFlag = 1 ionos = computeIonosphere(lowerUnw, upperUnw, cor, fl, fu, adjFlag, corThresholdAdj, 0) #dump ionosphere ionfile = 'ion'+ml2+'.ion' # ion = np.zeros((length*2, width), dtype=np.float32) # ion[0:length*2:2, :] = amp # ion[1:length*2:2, :] = ionos # ion.astype(np.float32).tofile(ionfile) # img.filename = ionfile # img.extraFilename = ionfile + '.vrt' # img.renderHdr() ionos.astype(np.float32).tofile(ionfile) create_xml(ionfile, width, length, 'float') ############################################################ # STEP 2. filter ionospheric phase ############################################################ ################################################# #SET PARAMETERS HERE #if applying polynomial fitting #False: no fitting, True: with fitting fit = self.fitIon #gaussian filtering window size size_max = self.filteringWinsizeMaxIon size_min = self.filteringWinsizeMinIon #THESE SHOULD BE GOOD ENOUGH, NO NEED TO SET IN setup(self) corThresholdIon = 0.85 ################################################# print('\nfiltering ionosphere') ionfile = 'ion'+ml2+'.ion' corfile = 'diff'+ml2+'.cor' ionfiltfile = 'filt_ion'+ml2+'.ion' img = isceobj.createImage() img.load(ionfile + '.xml') width = img.width length = img.length #ion = (np.fromfile(ionfile, dtype=np.float32).reshape(length*2, width))[1:length*2:2, :] ion = np.fromfile(ionfile, dtype=np.float32).reshape(length, width) cor = (np.fromfile(corfile, dtype=np.float32).reshape(length*2, width))[1:length*2:2, :] #amp = (np.fromfile(ionfile, dtype=np.float32).reshape(length*2, width))[0:length*2:2, :] #masked out user-specified areas if self.maskedAreasIon != None: maskedAreas = reformatMaskedAreas(self.maskedAreasIon, length, width) for area in maskedAreas: ion[area[0]:area[1], area[2]:area[3]] = 0 cor[area[0]:area[1], area[2]:area[3]] = 0 #remove possible wired values in coherence cor[np.nonzero(cor<0)] = 0.0 cor[np.nonzero(cor>1)] = 0.0 # #applying water body mask here # waterBodyFile = 'wbd'+ml2+'.wbd' # if os.path.isfile(waterBodyFile): # print('applying water body mask to coherence used to compute ionospheric phase') # wbd = np.fromfile(waterBodyFile, dtype=np.int8).reshape(length, width) # cor[np.nonzero(wbd!=0)] = 0.00001 if fit: ion_fit = weight_fitting(ion, cor, width, length, 1, 1, 1, 1, 2, corThresholdIon) ion -= ion_fit * (ion!=0) #minimize the effect of low coherence pixels #cor[np.nonzero( (cor<0.85)*(cor!=0) )] = 0.00001 #filt = adaptive_gaussian(ion, cor, size_max, size_min) #cor**14 should be a good weight to use. 22-APR-2018 filt = adaptive_gaussian(ion, cor**14, size_max, size_min) if fit: filt += ion_fit * (filt!=0) # ion = np.zeros((length*2, width), dtype=np.float32) # ion[0:length*2:2, :] = amp # ion[1:length*2:2, :] = filt # ion.astype(np.float32).tofile(ionfiltfile) # img.filename = ionfiltfile # img.extraFilename = ionfiltfile + '.vrt' # img.renderHdr() filt.astype(np.float32).tofile(ionfiltfile) create_xml(ionfiltfile, width, length, 'float') ############################################################ # STEP 3. resample ionospheric phase ############################################################ from contrib.alos2proc_f.alos2proc_f import rect from isceobj.Alos2Proc.Alos2ProcPublic import create_xml from scipy.interpolate import interp1d import shutil ################################################# #SET PARAMETERS HERE #interpolation method interpolationMethod = 1 ################################################# print('\ninterpolate ionosphere') ml3 = '_{}rlks_{}alks'.format(self._insar.numberRangeLooks1*self._insar.numberRangeLooks2, self._insar.numberAzimuthLooks1*self._insar.numberAzimuthLooks2) ionfiltfile = 'filt_ion'+ml2+'.ion' #ionrectfile = 'filt_ion'+ml3+'.ion' ionrectfile = self._insar.multilookIon img = isceobj.createImage() img.load(ionfiltfile + '.xml') width2 = img.width length2 = img.length img = isceobj.createImage() img.load(os.path.join('../../', ionDir['insar'], self._insar.multilookDifferentialInterferogram) + '.xml') width3 = img.width length3 = img.length #number of range looks output nrlo = self._insar.numberRangeLooks1*self._insar.numberRangeLooks2 #number of range looks input nrli = self._insar.numberRangeLooks1*self._insar.numberRangeLooksIon #number of azimuth looks output nalo = self._insar.numberAzimuthLooks1*self._insar.numberAzimuthLooks2 #number of azimuth looks input nali = self._insar.numberAzimuthLooks1*self._insar.numberAzimuthLooksIon if (self._insar.numberRangeLooks2 != self._insar.numberRangeLooksIon) or \ (self._insar.numberAzimuthLooks2 != self._insar.numberAzimuthLooksIon): #this should be faster using fortran if interpolationMethod == 0: rect(ionfiltfile, ionrectfile, width2,length2, width3,length3, nrlo/nrli, 0.0, 0.0, nalo/nali, (nrlo-nrli)/(2.0*nrli), (nalo-nali)/(2.0*nali), 'REAL','Bilinear') #finer, but slower method else: ionfilt = np.fromfile(ionfiltfile, dtype=np.float32).reshape(length2, width2) index2 = np.linspace(0, width2-1, num=width2, endpoint=True) index3 = np.linspace(0, width3-1, num=width3, endpoint=True) * nrlo/nrli + (nrlo-nrli)/(2.0*nrli) ionrect = np.zeros((length3, width3), dtype=np.float32) for i in range(length2): f = interp1d(index2, ionfilt[i,:], kind='cubic', fill_value="extrapolate") ionrect[i, :] = f(index3) index2 = np.linspace(0, length2-1, num=length2, endpoint=True) index3 = np.linspace(0, length3-1, num=length3, endpoint=True) * nalo/nali + (nalo-nali)/(2.0*nali) for j in range(width3): f = interp1d(index2, ionrect[0:length2, j], kind='cubic', fill_value="extrapolate") ionrect[:, j] = f(index3) ionrect.astype(np.float32).tofile(ionrectfile) del ionrect create_xml(ionrectfile, width3, length3, 'float') os.rename(ionrectfile, os.path.join('../../insar', ionrectfile)) os.rename(ionrectfile+'.vrt', os.path.join('../../insar', ionrectfile)+'.vrt') os.rename(ionrectfile+'.xml', os.path.join('../../insar', ionrectfile)+'.xml') os.chdir('../../insar') else: shutil.copyfile(ionfiltfile, os.path.join('../../insar', ionrectfile)) os.chdir('../../insar') create_xml(ionrectfile, width3, length3, 'float') #now we are in 'insar' ############################################################ # STEP 4. correct interferogram ############################################################ from isceobj.Alos2Proc.Alos2ProcPublic import renameFile from isceobj.Alos2Proc.Alos2ProcPublic import runCmd if self.applyIon: print('\ncorrect interferogram') if os.path.isfile(self._insar.multilookDifferentialInterferogramOriginal): print('original interferogram: {} is already here, do not rename: {}'.format(self._insar.multilookDifferentialInterferogramOriginal, self._insar.multilookDifferentialInterferogram)) else: print('renaming {} to {}'.format(self._insar.multilookDifferentialInterferogram, self._insar.multilookDifferentialInterferogramOriginal)) renameFile(self._insar.multilookDifferentialInterferogram, self._insar.multilookDifferentialInterferogramOriginal) cmd = "imageMath.py -e='a*exp(-1.0*J*b)' --a={} --b={} -s BIP -t cfloat -o {}".format( self._insar.multilookDifferentialInterferogramOriginal, self._insar.multilookIon, self._insar.multilookDifferentialInterferogram) runCmd(cmd) else: print('\nionospheric phase estimation finished, but correction of interfeorgram not requested') os.chdir('../') catalog.printToLog(logger, "runIonFilt") self._insar.procDoc.addAllFromCatalog(catalog)
def runSwathMosaic(self): '''mosaic subswaths ''' catalog = isceobj.Catalog.createCatalog(self._insar.procDoc.name) self.updateParamemetersFromUser() referenceTrack = self._insar.loadTrack(reference=True) secondaryTrack = self._insar.loadTrack(reference=False) for i, frameNumber in enumerate(self._insar.referenceFrames): frameDir = 'f{}_{}'.format(i+1, frameNumber) os.chdir(frameDir) mosaicDir = 'mosaic' os.makedirs(mosaicDir, exist_ok=True) os.chdir(mosaicDir) if self._insar.endingSwath-self._insar.startingSwath+1 == 1: import shutil swathDir = 's{}'.format(referenceTrack.frames[i].swaths[0].swathNumber) if not os.path.isfile(self._insar.interferogram): os.symlink(os.path.join('../', swathDir, self._insar.interferogram), self._insar.interferogram) shutil.copy2(os.path.join('../', swathDir, self._insar.interferogram+'.vrt'), self._insar.interferogram+'.vrt') shutil.copy2(os.path.join('../', swathDir, self._insar.interferogram+'.xml'), self._insar.interferogram+'.xml') if not os.path.isfile(self._insar.amplitude): os.symlink(os.path.join('../', swathDir, self._insar.amplitude), self._insar.amplitude) shutil.copy2(os.path.join('../', swathDir, self._insar.amplitude+'.vrt'), self._insar.amplitude+'.vrt') shutil.copy2(os.path.join('../', swathDir, self._insar.amplitude+'.xml'), self._insar.amplitude+'.xml') # os.rename(os.path.join('../', swathDir, self._insar.interferogram), self._insar.interferogram) # os.rename(os.path.join('../', swathDir, self._insar.interferogram+'.vrt'), self._insar.interferogram+'.vrt') # os.rename(os.path.join('../', swathDir, self._insar.interferogram+'.xml'), self._insar.interferogram+'.xml') # os.rename(os.path.join('../', swathDir, self._insar.amplitude), self._insar.amplitude) # os.rename(os.path.join('../', swathDir, self._insar.amplitude+'.vrt'), self._insar.amplitude+'.vrt') # os.rename(os.path.join('../', swathDir, self._insar.amplitude+'.xml'), self._insar.amplitude+'.xml') #update frame parameters ######################################################### frame = referenceTrack.frames[i] infImg = isceobj.createImage() infImg.load(self._insar.interferogram+'.xml') #mosaic size frame.numberOfSamples = infImg.width frame.numberOfLines = infImg.length #NOTE THAT WE ARE STILL USING SINGLE LOOK PARAMETERS HERE #range parameters frame.startingRange = frame.swaths[0].startingRange frame.rangeSamplingRate = frame.swaths[0].rangeSamplingRate frame.rangePixelSize = frame.swaths[0].rangePixelSize #azimuth parameters frame.sensingStart = frame.swaths[0].sensingStart frame.prf = frame.swaths[0].prf frame.azimuthPixelSize = frame.swaths[0].azimuthPixelSize frame.azimuthLineInterval = frame.swaths[0].azimuthLineInterval #update frame parameters, secondary ######################################################### frame = secondaryTrack.frames[i] #mosaic size frame.numberOfSamples = int(frame.swaths[0].numberOfSamples/self._insar.numberRangeLooks1) frame.numberOfLines = int(frame.swaths[0].numberOfLines/self._insar.numberAzimuthLooks1) #NOTE THAT WE ARE STILL USING SINGLE LOOK PARAMETERS HERE #range parameters frame.startingRange = frame.swaths[0].startingRange frame.rangeSamplingRate = frame.swaths[0].rangeSamplingRate frame.rangePixelSize = frame.swaths[0].rangePixelSize #azimuth parameters frame.sensingStart = frame.swaths[0].sensingStart frame.prf = frame.swaths[0].prf frame.azimuthPixelSize = frame.swaths[0].azimuthPixelSize frame.azimuthLineInterval = frame.swaths[0].azimuthLineInterval os.chdir('../') #save parameter file self._insar.saveProduct(referenceTrack.frames[i], self._insar.referenceFrameParameter) self._insar.saveProduct(secondaryTrack.frames[i], self._insar.secondaryFrameParameter) os.chdir('../') continue #choose offsets numberOfFrames = len(referenceTrack.frames) numberOfSwaths = len(referenceTrack.frames[i].swaths) if self.swathOffsetMatching: #no need to do this as the API support 2-d list #rangeOffsets = (np.array(self._insar.swathRangeOffsetMatchingReference)).reshape(numberOfFrames, numberOfSwaths) #azimuthOffsets = (np.array(self._insar.swathAzimuthOffsetMatchingReference)).reshape(numberOfFrames, numberOfSwaths) rangeOffsets = self._insar.swathRangeOffsetMatchingReference azimuthOffsets = self._insar.swathAzimuthOffsetMatchingReference else: #rangeOffsets = (np.array(self._insar.swathRangeOffsetGeometricalReference)).reshape(numberOfFrames, numberOfSwaths) #azimuthOffsets = (np.array(self._insar.swathAzimuthOffsetGeometricalReference)).reshape(numberOfFrames, numberOfSwaths) rangeOffsets = self._insar.swathRangeOffsetGeometricalReference azimuthOffsets = self._insar.swathAzimuthOffsetGeometricalReference rangeOffsets = rangeOffsets[i] azimuthOffsets = azimuthOffsets[i] #list of input files inputInterferograms = [] inputAmplitudes = [] for j, swathNumber in enumerate(range(self._insar.startingSwath, self._insar.endingSwath + 1)): swathDir = 's{}'.format(swathNumber) inputInterferograms.append(os.path.join('../', swathDir, self._insar.interferogram)) inputAmplitudes.append(os.path.join('../', swathDir, self._insar.amplitude)) #note that frame parameters are updated after mosaicking #mosaic amplitudes swathMosaic(referenceTrack.frames[i], inputAmplitudes, self._insar.amplitude, rangeOffsets, azimuthOffsets, self._insar.numberRangeLooks1, self._insar.numberAzimuthLooks1, resamplingMethod=0) #mosaic interferograms swathMosaic(referenceTrack.frames[i], inputInterferograms, self._insar.interferogram, rangeOffsets, azimuthOffsets, self._insar.numberRangeLooks1, self._insar.numberAzimuthLooks1, updateFrame=True, resamplingMethod=1) create_xml(self._insar.amplitude, referenceTrack.frames[i].numberOfSamples, referenceTrack.frames[i].numberOfLines, 'amp') create_xml(self._insar.interferogram, referenceTrack.frames[i].numberOfSamples, referenceTrack.frames[i].numberOfLines, 'int') #update secondary frame parameters here #no matching for secondary, always use geometry rangeOffsets = self._insar.swathRangeOffsetGeometricalSecondary azimuthOffsets = self._insar.swathAzimuthOffsetGeometricalSecondary rangeOffsets = rangeOffsets[i] azimuthOffsets = azimuthOffsets[i] swathMosaicParameters(secondaryTrack.frames[i], rangeOffsets, azimuthOffsets, self._insar.numberRangeLooks1, self._insar.numberAzimuthLooks1) os.chdir('../') #save parameter file self._insar.saveProduct(referenceTrack.frames[i], self._insar.referenceFrameParameter) self._insar.saveProduct(secondaryTrack.frames[i], self._insar.secondaryFrameParameter) os.chdir('../') #mosaic spectral diversity interferograms for i, frameNumber in enumerate(self._insar.referenceFrames): frameDir = 'f{}_{}'.format(i+1, frameNumber) os.chdir(frameDir) mosaicDir = 'mosaic' os.makedirs(mosaicDir, exist_ok=True) os.chdir(mosaicDir) if self._insar.endingSwath-self._insar.startingSwath+1 == 1: import shutil swathDir = 's{}'.format(referenceTrack.frames[i].swaths[0].swathNumber) for sdFile in self._insar.interferogramSd: if not os.path.isfile(sdFile): os.symlink(os.path.join('../', swathDir, 'spectral_diversity', sdFile), sdFile) shutil.copy2(os.path.join('../', swathDir, 'spectral_diversity', sdFile+'.vrt'), sdFile+'.vrt') shutil.copy2(os.path.join('../', swathDir, 'spectral_diversity', sdFile+'.xml'), sdFile+'.xml') os.chdir('../') os.chdir('../') continue #choose offsets numberOfFrames = len(referenceTrack.frames) numberOfSwaths = len(referenceTrack.frames[i].swaths) if self.swathOffsetMatching: #no need to do this as the API support 2-d list #rangeOffsets = (np.array(self._insar.swathRangeOffsetMatchingReference)).reshape(numberOfFrames, numberOfSwaths) #azimuthOffsets = (np.array(self._insar.swathAzimuthOffsetMatchingReference)).reshape(numberOfFrames, numberOfSwaths) rangeOffsets = self._insar.swathRangeOffsetMatchingReference azimuthOffsets = self._insar.swathAzimuthOffsetMatchingReference else: #rangeOffsets = (np.array(self._insar.swathRangeOffsetGeometricalReference)).reshape(numberOfFrames, numberOfSwaths) #azimuthOffsets = (np.array(self._insar.swathAzimuthOffsetGeometricalReference)).reshape(numberOfFrames, numberOfSwaths) rangeOffsets = self._insar.swathRangeOffsetGeometricalReference azimuthOffsets = self._insar.swathAzimuthOffsetGeometricalReference rangeOffsets = rangeOffsets[i] azimuthOffsets = azimuthOffsets[i] #list of input files inputSd = [[], [], []] for j, swathNumber in enumerate(range(self._insar.startingSwath, self._insar.endingSwath + 1)): swathDir = 's{}'.format(swathNumber) for k, sdFile in enumerate(self._insar.interferogramSd): inputSd[k].append(os.path.join('../', swathDir, 'spectral_diversity', sdFile)) #mosaic spectral diversity interferograms for inputSdList, outputSdFile in zip(inputSd, self._insar.interferogramSd): swathMosaic(referenceTrack.frames[i], inputSdList, outputSdFile, rangeOffsets, azimuthOffsets, self._insar.numberRangeLooks1, self._insar.numberAzimuthLooks1, updateFrame=False, phaseCompensation=True, pcRangeLooks=5, pcAzimuthLooks=5, filt=True, resamplingMethod=1) for sdFile in self._insar.interferogramSd: create_xml(sdFile, referenceTrack.frames[i].numberOfSamples, referenceTrack.frames[i].numberOfLines, 'int') os.chdir('../') os.chdir('../') catalog.printToLog(logger, "runSwathMosaic") self._insar.procDoc.addAllFromCatalog(catalog)
def resampleBursts(masterSwath, slaveSwath, masterBurstDir, slaveBurstDir, slaveBurstResampledDir, interferogramDir, masterBurstPrefix, slaveBurstPrefix, slaveBurstResampledPrefix, interferogramPrefix, rangeOffset, azimuthOffset, rangeOffsetResidual=0, azimuthOffsetResidual=0): import os import datetime import numpy as np import numpy.matlib from contrib.alos2proc.alos2proc import resamp if not os.path.exists(slaveBurstResampledDir): os.makedirs(slaveBurstResampledDir) if not os.path.exists(interferogramDir): os.makedirs(interferogramDir) #get burst file names masterBurstSlc = [ masterBurstPrefix + '_%02d.slc' % (i + 1) for i in range(masterSwath.numberOfBursts) ] slaveBurstSlc = [ slaveBurstPrefix + '_%02d.slc' % (i + 1) for i in range(slaveSwath.numberOfBursts) ] slaveBurstSlcResampled = [ slaveBurstPrefix + '_%02d.slc' % (i + 1) for i in range(masterSwath.numberOfBursts) ] interferogram = [ interferogramPrefix + '_%02d.int' % (i + 1) for i in range(masterSwath.numberOfBursts) ] length = masterSwath.burstSlcNumberOfLines width = masterSwath.burstSlcNumberOfSamples lengthSlave = slaveSwath.burstSlcNumberOfLines widthSlave = slaveSwath.burstSlcNumberOfSamples #slave burst slc start times slaveBurstStartTimesSlc = [slaveSwath.firstBurstSlcStartTime + \ datetime.timedelta(seconds=slaveSwath.burstSlcFirstLineOffsets[i]*slaveSwath.azimuthLineInterval) \ for i in range(slaveSwath.numberOfBursts)] #slave burst raw start times slaveBurstStartTimesRaw = [slaveSwath.firstBurstRawStartTime + \ datetime.timedelta(seconds=i*slaveSwath.burstCycleLength/slaveSwath.prf) \ for i in range(slaveSwath.numberOfBursts)] for i in range(masterSwath.numberOfBursts): ########################################################################## # 1. get offsets and corresponding slave burst ########################################################################## #range offset with open(rangeOffset, 'rb') as f: f.seek( masterSwath.burstSlcFirstLineOffsets[i] * width * np.dtype(np.float32).itemsize, 0) rgoffBurst = np.fromfile(f, dtype=np.float32, count=length * width).reshape( length, width) if type(rangeOffsetResidual) == np.ndarray: residual = rangeOffsetResidual[ 0 + masterSwath.burstSlcFirstLineOffsets[i]:length + masterSwath.burstSlcFirstLineOffsets[i], :] rgoffBurst[np.nonzero( rgoffBurst != -999999.0)] += residual[np.nonzero( rgoffBurst != -999999.0)] else: rgoffBurst[np.nonzero( rgoffBurst != -999999.0)] += rangeOffsetResidual #azimuth offset with open(azimuthOffset, 'rb') as f: f.seek( masterSwath.burstSlcFirstLineOffsets[i] * width * np.dtype(np.float32).itemsize, 0) azoffBurst = np.fromfile(f, dtype=np.float32, count=length * width).reshape( length, width) if type(azimuthOffsetResidual) == np.ndarray: residual = azimuthOffsetResidual[ 0 + masterSwath.burstSlcFirstLineOffsets[i]:length + masterSwath.burstSlcFirstLineOffsets[i], :] azoffBurst[np.nonzero( azoffBurst != -999999.0)] += residual[np.nonzero( azoffBurst != -999999.0)] else: azoffBurst[np.nonzero( azoffBurst != -999999.0)] += azimuthOffsetResidual #find the corresponding slave burst #get mean offset to use #remove BAD_VALUE = -999999.0 as defined in geo2rdr.f90 #single precision is not accurate enough to compute mean azoffBurstMean = np.mean( azoffBurst[np.nonzero(azoffBurst != -999999.0)], dtype=np.float64) iSlave = -1 for j in range(slaveSwath.numberOfBursts): if abs(masterSwath.burstSlcFirstLineOffsets[i] + azoffBurstMean - slaveSwath.burstSlcFirstLineOffsets[j]) < ( masterSwath.burstLength / masterSwath.prf * 2.0) / masterSwath.azimuthLineInterval: iSlave = j break #output zero resampled burst/interferogram if no slave burst found if iSlave == -1: print('\nburst pair, master: %2d, slave: no' % (i + 1)) #output an interferogram with all pixels set to zero os.chdir(interferogramDir) np.zeros((length, width), dtype=np.complex64).astype( np.complex64).tofile(interferogram[i]) create_xml(interferogram[i], width, length, 'int') os.chdir('../') #output a resampled slave image with all pixels set to zero os.chdir(slaveBurstResampledDir) np.zeros((length, width), dtype=np.complex64).astype( np.complex64).tofile(slaveBurstSlcResampled[i]) create_xml(slaveBurstSlcResampled[i], width, length, 'slc') os.chdir('../') continue else: print('\nburst pair, master: %2d, slave: %3d' % (i + 1, iSlave + 1)) #adjust azimuth offset accordingly, since original azimuth offset assumes master and slave start with sensingStart azoffBurst -= (slaveSwath.burstSlcFirstLineOffsets[iSlave] - masterSwath.burstSlcFirstLineOffsets[i]) ########################################################################## # 2. compute deramp and reramp signals ########################################################################## cj = np.complex64(1j) tbase = (slaveBurstStartTimesSlc[iSlave] - (slaveBurstStartTimesRaw[iSlave] + \ datetime.timedelta(seconds=(slaveSwath.burstLength - 1.0) / 2.0 / slaveSwath.prf))).total_seconds() #compute deramp signal index1 = np.matlib.repmat(np.arange(widthSlave), lengthSlave, 1) index2 = np.matlib.repmat( np.arange(lengthSlave).reshape(lengthSlave, 1), 1, widthSlave) ka = slaveSwath.azimuthFmrateVsPixel[3] * index1**3 + slaveSwath.azimuthFmrateVsPixel[2] * index1**2 + \ slaveSwath.azimuthFmrateVsPixel[1] * index1 + slaveSwath.azimuthFmrateVsPixel[0] #use the convention that ka > 0 ka = -ka t = tbase + index2 * slaveSwath.azimuthLineInterval deramp = np.exp(cj * np.pi * (-ka) * t**2) #compute reramp signal index1 = np.matlib.repmat(np.arange(width), length, 1) + rgoffBurst index2 = np.matlib.repmat( np.arange(length).reshape(length, 1), 1, width) + azoffBurst ka = slaveSwath.azimuthFmrateVsPixel[3] * index1**3 + slaveSwath.azimuthFmrateVsPixel[2] * index1**2 + \ slaveSwath.azimuthFmrateVsPixel[1] * index1 + slaveSwath.azimuthFmrateVsPixel[0] #use the convention that ka > 0 ka = -ka t = tbase + index2 * slaveSwath.azimuthLineInterval reramp = np.exp(cj * np.pi * (ka) * t**2) ########################################################################## # 3. resample slave burst ########################################################################## #go to slave directory to do resampling os.chdir(slaveBurstDir) #output offsets rgoffBurstFile = "burst_rg.off" azoffBurstFile = "burst_az.off" rgoffBurst.astype(np.float32).tofile(rgoffBurstFile) azoffBurst.astype(np.float32).tofile(azoffBurstFile) #deramp slave burst slaveBurstDerampedFile = "slave.slc" sburst = np.fromfile(slaveBurstSlc[iSlave], dtype=np.complex64).reshape( lengthSlave, widthSlave) (deramp * sburst).astype(np.complex64).tofile(slaveBurstDerampedFile) create_xml(slaveBurstDerampedFile, widthSlave, lengthSlave, 'slc') #resampled slave burst slaveBurstResampFile = 'slave_resamp.slc' #resample slave burst #now doppler has bigger impact now, as it's value is about 35 Hz (azimuth resampling frequency is now only 1/20 * PRF) #we don't know if this doppler value is accurate or not, so we set it to zero, which seems to give best resampling result #otherwise if it is not accurate and we still use it, it will significantly affect resampling result dopplerVsPixel = slaveSwath.dopplerVsPixel dopplerVsPixel = [0.0, 0.0, 0.0, 0.0] resamp(slaveBurstDerampedFile, slaveBurstResampFile, rgoffBurstFile, azoffBurstFile, width, length, 1.0 / slaveSwath.azimuthLineInterval, dopplerVsPixel, rgcoef=[0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], azcoef=[0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], azpos_off=0.0) #read resampled slave burst and reramp sburstResamp = reramp * (np.fromfile( slaveBurstResampFile, dtype=np.complex64).reshape(length, width)) #clear up os.remove(rgoffBurstFile) os.remove(azoffBurstFile) os.remove(slaveBurstDerampedFile) os.remove(slaveBurstDerampedFile + '.vrt') os.remove(slaveBurstDerampedFile + '.xml') os.remove(slaveBurstResampFile) os.remove(slaveBurstResampFile + '.vrt') os.remove(slaveBurstResampFile + '.xml') os.chdir('../') ########################################################################## # 4. dump results ########################################################################## #dump resampled slave burst os.chdir(slaveBurstResampledDir) sburstResamp.astype(np.complex64).tofile(slaveBurstSlcResampled[i]) create_xml(slaveBurstSlcResampled[i], width, length, 'slc') os.chdir('../') #dump burst interferogram mburst = np.fromfile(os.path.join(masterBurstDir, masterBurstSlc[i]), dtype=np.complex64).reshape(length, width) os.chdir(interferogramDir) (mburst * np.conj(sburstResamp)).astype(np.complex64).tofile( interferogram[i]) create_xml(interferogram[i], width, length, 'int') os.chdir('../')
def runFrameMosaic(self): '''mosaic frames ''' catalog = isceobj.Catalog.createCatalog(self._insar.procDoc.name) self.updateParamemetersFromUser() masterTrack = self._insar.loadTrack(master=True) slaveTrack = self._insar.loadTrack(master=False) mosaicDir = 'insar' os.makedirs(mosaicDir, exist_ok=True) os.chdir(mosaicDir) numberOfFrames = len(masterTrack.frames) if numberOfFrames == 1: import shutil frameDir = os.path.join('f1_{}/mosaic'.format( self._insar.masterFrames[0])) if not os.path.isfile(self._insar.interferogram): os.symlink( os.path.join('../', frameDir, self._insar.interferogram), self._insar.interferogram) #shutil.copy2() can overwrite shutil.copy2( os.path.join('../', frameDir, self._insar.interferogram + '.vrt'), self._insar.interferogram + '.vrt') shutil.copy2( os.path.join('../', frameDir, self._insar.interferogram + '.xml'), self._insar.interferogram + '.xml') if not os.path.isfile(self._insar.amplitude): os.symlink(os.path.join('../', frameDir, self._insar.amplitude), self._insar.amplitude) shutil.copy2( os.path.join('../', frameDir, self._insar.amplitude + '.vrt'), self._insar.amplitude + '.vrt') shutil.copy2( os.path.join('../', frameDir, self._insar.amplitude + '.xml'), self._insar.amplitude + '.xml') # os.rename(os.path.join('../', frameDir, self._insar.interferogram), self._insar.interferogram) # os.rename(os.path.join('../', frameDir, self._insar.interferogram+'.vrt'), self._insar.interferogram+'.vrt') # os.rename(os.path.join('../', frameDir, self._insar.interferogram+'.xml'), self._insar.interferogram+'.xml') # os.rename(os.path.join('../', frameDir, self._insar.amplitude), self._insar.amplitude) # os.rename(os.path.join('../', frameDir, self._insar.amplitude+'.vrt'), self._insar.amplitude+'.vrt') # os.rename(os.path.join('../', frameDir, self._insar.amplitude+'.xml'), self._insar.amplitude+'.xml') #update track parameters ######################################################### #mosaic size masterTrack.numberOfSamples = masterTrack.frames[0].numberOfSamples masterTrack.numberOfLines = masterTrack.frames[0].numberOfLines #NOTE THAT WE ARE STILL USING SINGLE LOOK PARAMETERS HERE #range parameters masterTrack.startingRange = masterTrack.frames[0].startingRange masterTrack.rangeSamplingRate = masterTrack.frames[0].rangeSamplingRate masterTrack.rangePixelSize = masterTrack.frames[0].rangePixelSize #azimuth parameters masterTrack.sensingStart = masterTrack.frames[0].sensingStart masterTrack.prf = masterTrack.frames[0].prf masterTrack.azimuthPixelSize = masterTrack.frames[0].azimuthPixelSize masterTrack.azimuthLineInterval = masterTrack.frames[ 0].azimuthLineInterval #update track parameters, slave ######################################################### #mosaic size slaveTrack.numberOfSamples = slaveTrack.frames[0].numberOfSamples slaveTrack.numberOfLines = slaveTrack.frames[0].numberOfLines #NOTE THAT WE ARE STILL USING SINGLE LOOK PARAMETERS HERE #range parameters slaveTrack.startingRange = slaveTrack.frames[0].startingRange slaveTrack.rangeSamplingRate = slaveTrack.frames[0].rangeSamplingRate slaveTrack.rangePixelSize = slaveTrack.frames[0].rangePixelSize #azimuth parameters slaveTrack.sensingStart = slaveTrack.frames[0].sensingStart slaveTrack.prf = slaveTrack.frames[0].prf slaveTrack.azimuthPixelSize = slaveTrack.frames[0].azimuthPixelSize slaveTrack.azimuthLineInterval = slaveTrack.frames[ 0].azimuthLineInterval else: #choose offsets if self.frameOffsetMatching: rangeOffsets = self._insar.frameRangeOffsetMatchingMaster azimuthOffsets = self._insar.frameAzimuthOffsetMatchingMaster else: rangeOffsets = self._insar.frameRangeOffsetGeometricalMaster azimuthOffsets = self._insar.frameAzimuthOffsetGeometricalMaster #list of input files inputInterferograms = [] inputAmplitudes = [] for i, frameNumber in enumerate(self._insar.masterFrames): frameDir = 'f{}_{}'.format(i + 1, frameNumber) inputInterferograms.append( os.path.join('../', frameDir, 'mosaic', self._insar.interferogram)) inputAmplitudes.append( os.path.join('../', frameDir, 'mosaic', self._insar.amplitude)) #note that track parameters are updated after mosaicking #mosaic amplitudes frameMosaic(masterTrack, inputAmplitudes, self._insar.amplitude, rangeOffsets, azimuthOffsets, self._insar.numberRangeLooks1, self._insar.numberAzimuthLooks1, updateTrack=False, phaseCompensation=False, resamplingMethod=0) #mosaic interferograms frameMosaic(masterTrack, inputInterferograms, self._insar.interferogram, rangeOffsets, azimuthOffsets, self._insar.numberRangeLooks1, self._insar.numberAzimuthLooks1, updateTrack=True, phaseCompensation=True, resamplingMethod=1) create_xml(self._insar.amplitude, masterTrack.numberOfSamples, masterTrack.numberOfLines, 'amp') create_xml(self._insar.interferogram, masterTrack.numberOfSamples, masterTrack.numberOfLines, 'int') #update slave parameters here #do not match for slave, always use geometrical rangeOffsets = self._insar.frameRangeOffsetGeometricalSlave azimuthOffsets = self._insar.frameAzimuthOffsetGeometricalSlave frameMosaicParameters(slaveTrack, rangeOffsets, azimuthOffsets, self._insar.numberRangeLooks1, self._insar.numberAzimuthLooks1) os.chdir('../') #save parameter file self._insar.saveProduct(masterTrack, self._insar.masterTrackParameter) self._insar.saveProduct(slaveTrack, self._insar.slaveTrackParameter) #mosaic spectral diversity inteferograms mosaicDir = 'sd' os.makedirs(mosaicDir, exist_ok=True) os.chdir(mosaicDir) numberOfFrames = len(masterTrack.frames) if numberOfFrames == 1: import shutil frameDir = os.path.join('f1_{}/mosaic'.format( self._insar.masterFrames[0])) for sdFile in self._insar.interferogramSd: if not os.path.isfile(sdFile): os.symlink(os.path.join('../', frameDir, sdFile), sdFile) shutil.copy2(os.path.join('../', frameDir, sdFile + '.vrt'), sdFile + '.vrt') shutil.copy2(os.path.join('../', frameDir, sdFile + '.xml'), sdFile + '.xml') else: #choose offsets if self.frameOffsetMatching: rangeOffsets = self._insar.frameRangeOffsetMatchingMaster azimuthOffsets = self._insar.frameAzimuthOffsetMatchingMaster else: rangeOffsets = self._insar.frameRangeOffsetGeometricalMaster azimuthOffsets = self._insar.frameAzimuthOffsetGeometricalMaster #list of input files inputSd = [[], [], []] for i, frameNumber in enumerate(self._insar.masterFrames): frameDir = 'f{}_{}'.format(i + 1, frameNumber) for k, sdFile in enumerate(self._insar.interferogramSd): inputSd[k].append( os.path.join('../', frameDir, 'mosaic', sdFile)) #mosaic spectral diversity interferograms for inputSdList, outputSdFile in zip(inputSd, self._insar.interferogramSd): frameMosaic(masterTrack, inputSdList, outputSdFile, rangeOffsets, azimuthOffsets, self._insar.numberRangeLooks1, self._insar.numberAzimuthLooks1, updateTrack=False, phaseCompensation=True, resamplingMethod=1) for sdFile in self._insar.interferogramSd: create_xml(sdFile, masterTrack.numberOfSamples, masterTrack.numberOfLines, 'int') os.chdir('../') catalog.printToLog(logger, "runFrameMosaic") self._insar.procDoc.addAllFromCatalog(catalog)
def swathMosaic(frame, inputFiles, outputfile, rangeOffsets, azimuthOffsets, numberOfRangeLooks, numberOfAzimuthLooks, updateFrame=False, phaseCompensation=False, phaseDiff=None, phaseDiffFixed=None, snapThreshold=None, snapSwath=None, pcRangeLooks=1, pcAzimuthLooks=4, filt=False, resamplingMethod=0): ''' mosaic swaths #PART 1. REGULAR INPUT PARAMTERS frame: frame inputFiles: input file list outputfile: output mosaic file rangeOffsets: range offsets azimuthOffsets: azimuth offsets numberOfRangeLooks: number of range looks of the input files numberOfAzimuthLooks: number of azimuth looks of the input files updateFrame: whether update frame parameters #PART 2. PARAMETERS FOR COMPUTING PHASE DIFFERENCE BETWEEN SUBSWATHS phaseCompensation: whether do phase compensation for each swath phaseDiff: pre-computed compensation phase for each swath phaseDiffFixed: if provided, the estimated value will snap to one of these values, which is nearest to the estimated one. snapThreshold: this is used with phaseDiffFixed snapSwath: indicate whether snap to fixed values for each swath phase diff, must be specified if phaseDiffFixed!=None pcRangeLooks: number of range looks to take when compute swath phase difference pcAzimuthLooks: number of azimuth looks to take when compute swath phase difference filt: whether do filtering when compute swath phase difference #PART 3. RESAMPLING METHOD resamplingMethod: 0: amp resampling. 1: int resampling. ''' from contrib.alos2proc_f.alos2proc_f import rect_with_looks from contrib.alos2proc.alos2proc import mosaicsubswath from isceobj.Alos2Proc.Alos2ProcPublic import multilook from isceobj.Alos2Proc.Alos2ProcPublic import cal_coherence_1 from isceobj.Alos2Proc.Alos2ProcPublic import filterInterferogram from isceobj.Alos2Proc.Alos2ProcPublic import computePhaseDiff from isceobj.Alos2Proc.Alos2ProcPublic import snap numberOfSwaths = len(frame.swaths) swaths = frame.swaths rangeScale = [] azimuthScale = [] rectWidth = [] rectLength = [] for i in range(numberOfSwaths): rangeScale.append(swaths[0].rangePixelSize / swaths[i].rangePixelSize) azimuthScale.append(swaths[0].azimuthLineInterval / swaths[i].azimuthLineInterval) if i == 0: rectWidth.append( int(swaths[i].numberOfSamples / numberOfRangeLooks)) rectLength.append( int(swaths[i].numberOfLines / numberOfAzimuthLooks)) else: rectWidth.append( round(1.0 / rangeScale[i] * int(swaths[i].numberOfSamples / numberOfRangeLooks))) rectLength.append( round(1.0 / azimuthScale[i] * int(swaths[i].numberOfLines / numberOfAzimuthLooks))) #rectWidth.append( int(1.0 / rangeScale[i] * int(swaths[i].numberOfSamples / numberOfRangeLooks)) ) #rectLength.append( int(1.0 / azimuthScale[i] * int(swaths[i].numberOfLines / numberOfAzimuthLooks)) ) #convert original offset to offset for images with looks #use list instead of np.array to make it consistent with the rest of the code rangeOffsets1 = [i / numberOfRangeLooks for i in rangeOffsets] azimuthOffsets1 = [i / numberOfAzimuthLooks for i in azimuthOffsets] #get offset relative to the first frame rangeOffsets2 = [0.0] azimuthOffsets2 = [0.0] for i in range(1, numberOfSwaths): rangeOffsets2.append(0.0) azimuthOffsets2.append(0.0) for j in range(1, i + 1): rangeOffsets2[i] += rangeOffsets1[j] azimuthOffsets2[i] += azimuthOffsets1[j] #resample each swath rinfs = [] for i, inf in enumerate(inputFiles): rinfs.append("{}_{}{}".format( os.path.splitext(os.path.basename(inf))[0], i, os.path.splitext(os.path.basename(inf))[1])) #do not resample first swath if i == 0: if os.path.isfile(rinfs[i]): os.remove(rinfs[i]) os.symlink(inf, rinfs[i]) else: #no need to resample if (abs(rangeOffsets2[i] - round(rangeOffsets2[i])) < 0.0001) and ( abs(azimuthOffsets2[i] - round(azimuthOffsets2[i])) < 0.0001): if os.path.isfile(rinfs[i]): os.remove(rinfs[i]) os.symlink(inf, rinfs[i]) #all of the following use of rangeOffsets2/azimuthOffsets2 is inside int(), we do the following in case it is like #4.99999999999... rangeOffsets2[i] = round(rangeOffsets2[i]) azimuthOffsets2[i] = round(azimuthOffsets2[i]) else: infImg = isceobj.createImage() infImg.load(inf + '.xml') rangeOffsets2Frac = rangeOffsets2[i] - int(rangeOffsets2[i]) azimuthOffsets2Frac = azimuthOffsets2[i] - int( azimuthOffsets2[i]) if resamplingMethod == 0: rect_with_looks(inf, rinfs[i], infImg.width, infImg.length, rectWidth[i], rectLength[i], rangeScale[i], 0.0, 0.0, azimuthScale[i], rangeOffsets2Frac * rangeScale[i], azimuthOffsets2Frac * azimuthScale[i], 1, 1, 1, 1, 'COMPLEX', 'Bilinear') elif resamplingMethod == 1: #decompose amplitude and phase phaseFile = 'phase' amplitudeFile = 'amplitude' data = np.fromfile(inf, dtype=np.complex64).reshape( infImg.length, infImg.width) phase = np.exp(np.complex64(1j) * np.angle(data)) phase[np.nonzero(data == 0)] = 0 phase.astype(np.complex64).tofile(phaseFile) amplitude = np.absolute(data) amplitude.astype(np.float32).tofile(amplitudeFile) #resampling phaseRectFile = 'phaseRect' amplitudeRectFile = 'amplitudeRect' rect_with_looks(phaseFile, phaseRectFile, infImg.width, infImg.length, rectWidth[i], rectLength[i], rangeScale[i], 0.0, 0.0, azimuthScale[i], rangeOffsets2Frac * rangeScale[i], azimuthOffsets2Frac * azimuthScale[i], 1, 1, 1, 1, 'COMPLEX', 'Sinc') rect_with_looks(amplitudeFile, amplitudeRectFile, infImg.width, infImg.length, rectWidth[i], rectLength[i], rangeScale[i], 0.0, 0.0, azimuthScale[i], rangeOffsets2Frac * rangeScale[i], azimuthOffsets2Frac * azimuthScale[i], 1, 1, 1, 1, 'REAL', 'Bilinear') #recombine amplitude and phase phase = np.fromfile(phaseRectFile, dtype=np.complex64).reshape( rectLength[i], rectWidth[i]) amplitude = np.fromfile(amplitudeRectFile, dtype=np.float32).reshape( rectLength[i], rectWidth[i]) (phase * amplitude).astype(np.complex64).tofile(rinfs[i]) #tidy up os.remove(phaseFile) os.remove(amplitudeFile) os.remove(phaseRectFile) os.remove(amplitudeRectFile) #determine output width and length #actually no need to calculate in range direction xs = [] xe = [] ys = [] ye = [] for i in range(numberOfSwaths): if i == 0: xs.append(0) xe.append(rectWidth[i] - 1) ys.append(0) ye.append(rectLength[i] - 1) else: xs.append(0 - int(rangeOffsets2[i])) xe.append(rectWidth[i] - 1 - int(rangeOffsets2[i])) ys.append(0 - int(azimuthOffsets2[i])) ye.append(rectLength[i] - 1 - int(azimuthOffsets2[i])) (xmin, xminIndex) = min((v, i) for i, v in enumerate(xs)) (xmax, xmaxIndex) = max((v, i) for i, v in enumerate(xe)) (ymin, yminIndex) = min((v, i) for i, v in enumerate(ys)) (ymax, ymaxIndex) = max((v, i) for i, v in enumerate(ye)) outWidth = xmax - xmin + 1 outLength = ymax - ymin + 1 #prepare offset for mosaicing rangeOffsets3 = [] azimuthOffsets3 = [] for i in range(numberOfSwaths): azimuthOffsets3.append( int(azimuthOffsets2[i]) - int(azimuthOffsets2[yminIndex])) if i != 0: rangeOffsets3.append( int(rangeOffsets2[i]) - int(rangeOffsets2[i - 1])) else: rangeOffsets3.append(0) delta = int(30 / numberOfRangeLooks) #compute compensation phase for each swath diffMean2 = [0.0 for i in range(numberOfSwaths)] phaseDiffEst = [None for i in range(numberOfSwaths)] #True if: # (1) used diff phase from input # (2) used estimated diff phase after snapping to a fixed diff phase provided #False if: # (1) used purely estimated diff phase phaseDiffSource = ['estimated' for i in range(numberOfSwaths)] # 1. 'estimated': estimated from subswath overlap # 2. 'estimated+snap': estimated from subswath overlap and snap to a fixed value # 3. 'input': pre-computed # confidence level: 3 > 2 > 1 numberOfValidSamples = [None for i in range(numberOfSwaths)] # only record when (filt == False) and (index[0].size >= 4000) if phaseCompensation: #compute swath phase offset diffMean = [0.0] for i in range(1, numberOfSwaths): #no need to estimate diff phase if provided from input ##################################################################### if phaseDiff != None: if phaseDiff[i] != None: diffMean.append(phaseDiff[i]) phaseDiffSource[i] = 'input' print('using pre-computed phase offset given from input') print('phase offset: subswath{} - subswath{}: {}'.format( frame.swaths[i - 1].swathNumber, frame.swaths[i].swathNumber, phaseDiff[i])) continue ##################################################################### #all indexes start with zero, all the computed start/end sample/line indexes are included. #no need to add edge here, as we are going to find first/last nonzero sample/lines later #edge = delta edge = 0 #image i-1 startSample1 = edge + 0 - int(rangeOffsets2[i]) + int( rangeOffsets2[i - 1]) endSample1 = -edge + rectWidth[i - 1] - 1 startLine1 = edge + max( 0 - int(azimuthOffsets2[i]) + int(azimuthOffsets2[i - 1]), 0) endLine1 = -edge + min( rectLength[i] - 1 - int(azimuthOffsets2[i]) + int(azimuthOffsets2[i - 1]), rectLength[i - 1] - 1) data1 = readImage(rinfs[i - 1], rectWidth[i - 1], rectLength[i - 1], startSample1, endSample1, startLine1, endLine1) #image i startSample2 = edge + 0 endSample2 = -edge + rectWidth[i - 1] - 1 - int( rangeOffsets2[i - 1]) + int(rangeOffsets2[i]) startLine2 = edge + max( 0 - int(azimuthOffsets2[i - 1]) + int(azimuthOffsets2[i]), 0) endLine2 = -edge + min( rectLength[i - 1] - 1 - int(azimuthOffsets2[i - 1]) + int(azimuthOffsets2[i]), rectLength[i] - 1) data2 = readImage(rinfs[i], rectWidth[i], rectLength[i], startSample2, endSample2, startLine2, endLine2) #remove edge due to incomplete covolution in resampling edge = 9 (startLine0, endLine0, startSample0, endSample0) = findNonzero( np.logical_and((data1 != 0), (data2 != 0))) data1 = data1[startLine0 + edge:endLine0 + 1 - edge, startSample0 + edge:endSample0 + 1 - edge] data2 = data2[startLine0 + edge:endLine0 + 1 - edge, startSample0 + edge:endSample0 + 1 - edge] #take looks data1 = multilook(data1, pcAzimuthLooks, pcRangeLooks) data2 = multilook(data2, pcAzimuthLooks, pcRangeLooks) #filter if filt: data1 /= (np.absolute(data1) + (data1 == 0)) data2 /= (np.absolute(data2) + (data2 == 0)) data1 = filterInterferogram(data1, 3.0, 64, 1) data2 = filterInterferogram(data2, 3.0, 64, 1) #get difference dataDiff = data1 * np.conj(data2) cor = cal_coherence_1(dataDiff, win=5) index = np.nonzero(np.logical_and(cor > 0.85, dataDiff != 0)) DEBUG = False if DEBUG: from isceobj.Alos2Proc.Alos2ProcPublic import create_xml (length7, width7) = dataDiff.shape filename = 'diff_ori_s{}-s{}.int'.format( frame.swaths[i - 1].swathNumber, frame.swaths[i].swathNumber) dataDiff.astype(np.complex64).tofile(filename) create_xml(filename, width7, length7, 'int') filename = 'cor_ori_s{}-s{}.cor'.format( frame.swaths[i - 1].swathNumber, frame.swaths[i].swathNumber) cor.astype(np.float32).tofile(filename) create_xml(filename, width7, length7, 'float') print('\ncompute phase difference between subswaths {} and {}'. format(frame.swaths[i - 1].swathNumber, frame.swaths[i].swathNumber)) print('number of pixels with coherence > 0.85: {}'.format( index[0].size)) #if already filtered the subswath overlap interferograms (MAI), do not filtered differential interferograms if (filt == False) and (index[0].size < 4000): #coherence too low, filter subswath overlap differential interferogram diffMean0 = 0.0 breakFlag = False for (filterStrength, filterWinSize) in zip([3.0, 9.0], [64, 128]): dataDiff = data1 * np.conj(data2) dataDiff /= (np.absolute(dataDiff) + (dataDiff == 0)) dataDiff = filterInterferogram(dataDiff, filterStrength, filterWinSize, 1) cor = cal_coherence_1(dataDiff, win=7) DEBUG = False if DEBUG: from isceobj.Alos2Proc.Alos2ProcPublic import create_xml (length7, width7) = dataDiff.shape filename = 'diff_filt_s{}-s{}_strength_{}_winsize_{}.int'.format( frame.swaths[i - 1].swathNumber, frame.swaths[i].swathNumber, filterStrength, filterWinSize) dataDiff.astype(np.complex64).tofile(filename) create_xml(filename, width7, length7, 'int') filename = 'cor_filt_s{}-s{}_strength_{}_winsize_{}.cor'.format( frame.swaths[i - 1].swathNumber, frame.swaths[i].swathNumber, filterStrength, filterWinSize) cor.astype(np.float32).tofile(filename) create_xml(filename, width7, length7, 'float') for corth in [0.99999, 0.9999]: index = np.nonzero( np.logical_and(cor > corth, dataDiff != 0)) if index[0].size > 30000: breakFlag = True break if breakFlag: break if index[0].size < 100: diffMean0 = 0.0 print( '\n\nWARNING: too few high coherence pixels for swath phase difference estimation' ) print(' number of high coherence pixels: {}\n\n'. format(index[0].size)) else: print( 'filtered coherence threshold used: {}, number of pixels used: {}' .format(corth, index[0].size)) angle = np.mean(np.angle(dataDiff[index]), dtype=np.float64) diffMean0 += angle data2 *= np.exp(np.complex64(1j) * angle) print( 'phase offset: %15.12f rad with filter strength: %f, window size: %3d' % (diffMean0, filterStrength, filterWinSize)) else: if filt: (diffMean0, numberOfValidSamples[i]) = computePhaseDiff( data1, data2, coherenceWindowSize=5, coherenceThreshold=0.95) else: (diffMean0, numberOfValidSamples[i]) = computePhaseDiff( data1, data2, coherenceWindowSize=5, coherenceThreshold=0.85) if numberOfValidSamples[i] < 100: diffMean0 = 0.0 print( '\n\nWARNING: too few high coherence pixels for swath phase difference estimation' ) print(' number of high coherence pixels: {}\n\n'. format(numberOfValidSamples[i])) #do not record when filt if filt: numberOfValidSamples[i] = None #save purely estimated diff phase phaseDiffEst[i] = diffMean0 #if fixed diff phase provided and the estimated diff phase is close enough to a fixed value, snap to it if phaseDiffFixed != None: if snapSwath[i - 1] == True: (outputValue, snapped) = snap(diffMean0, phaseDiffFixed, snapThreshold) if snapped == True: diffMean0 = outputValue phaseDiffSource[i] = 'estimated+snap' diffMean.append(diffMean0) print('phase offset: subswath{} - subswath{}: {}'.format( frame.swaths[i - 1].swathNumber, frame.swaths[i].swathNumber, diffMean0)) for i in range(1, numberOfSwaths): for j in range(1, i + 1): diffMean2[i] += diffMean[j] #mosaic swaths diffflag = 1 oflag = [0 for i in range(numberOfSwaths)] mosaicsubswath(outputfile, outWidth, outLength, delta, diffflag, numberOfSwaths, rinfs, rectWidth, rangeOffsets3, azimuthOffsets3, diffMean2, oflag) #remove tmp files for x in rinfs: os.remove(x) #update frame parameters if updateFrame: #mosaic size frame.numberOfSamples = outWidth frame.numberOfLines = outLength #NOTE THAT WE ARE STILL USING SINGLE LOOK PARAMETERS HERE #range parameters frame.startingRange = frame.swaths[0].startingRange frame.rangeSamplingRate = frame.swaths[0].rangeSamplingRate frame.rangePixelSize = frame.swaths[0].rangePixelSize #azimuth parameters azimuthTimeOffset = -max([ int(x) for x in azimuthOffsets2 ]) * numberOfAzimuthLooks * frame.swaths[0].azimuthLineInterval frame.sensingStart = frame.swaths[0].sensingStart + datetime.timedelta( seconds=azimuthTimeOffset) frame.prf = frame.swaths[0].prf frame.azimuthPixelSize = frame.swaths[0].azimuthPixelSize frame.azimuthLineInterval = frame.swaths[0].azimuthLineInterval if phaseCompensation: # estimated phase diff, used phase diff, used phase diff source return (phaseDiffEst, diffMean, phaseDiffSource, numberOfValidSamples)
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 ionFilt(self, referenceTrack, catalog=None): from isceobj.Alos2Proc.runIonSubband import defineIonDir ionDir = defineIonDir() subbandPrefix = ['lower', 'upper'] ionCalDir = os.path.join(ionDir['ion'], ionDir['ionCal']) os.makedirs(ionCalDir, exist_ok=True) os.chdir(ionCalDir) log = '' ############################################################ # STEP 1. compute ionospheric phase ############################################################ from isceobj.Constants import SPEED_OF_LIGHT from isceobj.Alos2Proc.Alos2ProcPublic import create_xml ################################### #SET PARAMETERS HERE #THESE SHOULD BE GOOD ENOUGH, NO NEED TO SET IN setup(self) corThresholdAdj = 0.97 corOrderAdj = 20 ################################### print('\ncomputing ionosphere') #get files ml2 = '_{}rlks_{}alks'.format( self._insar.numberRangeLooks1 * self._insar.numberRangeLooksIon, self._insar.numberAzimuthLooks1 * self._insar.numberAzimuthLooksIon) lowerUnwfile = subbandPrefix[0] + ml2 + '.unw' upperUnwfile = subbandPrefix[1] + ml2 + '.unw' corfile = 'diff' + ml2 + '.cor' #use image size from lower unwrapped interferogram img = isceobj.createImage() img.load(lowerUnwfile + '.xml') width = img.width length = img.length lowerUnw = (np.fromfile(lowerUnwfile, dtype=np.float32).reshape( length * 2, width))[1:length * 2:2, :] upperUnw = (np.fromfile(upperUnwfile, dtype=np.float32).reshape( length * 2, width))[1:length * 2:2, :] cor = (np.fromfile(corfile, dtype=np.float32).reshape(length * 2, width))[1:length * 2:2, :] #amp = (np.fromfile(corfile, dtype=np.float32).reshape(length*2, width))[0:length*2:2, :] #masked out user-specified areas if self.maskedAreasIon != None: maskedAreas = reformatMaskedAreas(self.maskedAreasIon, length, width) for area in maskedAreas: lowerUnw[area[0]:area[1], area[2]:area[3]] = 0 upperUnw[area[0]:area[1], area[2]:area[3]] = 0 cor[area[0]:area[1], area[2]:area[3]] = 0 #remove possible wired values in coherence cor[np.nonzero(cor < 0)] = 0.0 cor[np.nonzero(cor > 1)] = 0.0 #remove water body wbd = np.fromfile('wbd' + ml2 + '.wbd', dtype=np.int8).reshape(length, width) cor[np.nonzero(wbd == -1)] = 0.0 #remove small values cor[np.nonzero(cor < corThresholdAdj)] = 0.0 #compute ionosphere fl = SPEED_OF_LIGHT / self._insar.subbandRadarWavelength[0] fu = SPEED_OF_LIGHT / self._insar.subbandRadarWavelength[1] adjFlag = 1 ionos = computeIonosphere(lowerUnw, upperUnw, cor**corOrderAdj, fl, fu, adjFlag, 0) #dump ionosphere ionfile = 'ion' + ml2 + '.ion' # ion = np.zeros((length*2, width), dtype=np.float32) # ion[0:length*2:2, :] = amp # ion[1:length*2:2, :] = ionos # ion.astype(np.float32).tofile(ionfile) # img.filename = ionfile # img.extraFilename = ionfile + '.vrt' # img.renderHdr() ionos.astype(np.float32).tofile(ionfile) create_xml(ionfile, width, length, 'float') ############################################################ # STEP 2. filter ionospheric phase ############################################################ import scipy.signal as ss ################################################# #SET PARAMETERS HERE #fit and filter ionosphere fit = self.fitIon filt = self.filtIon fitAdaptive = self.fitAdaptiveIon filtSecondary = self.filtSecondaryIon if (fit == False) and (filt == False): raise Exception( 'either fit ionosphere or filt ionosphere should be True when doing ionospheric correction\n' ) #filtering window size size_max = self.filteringWinsizeMaxIon size_min = self.filteringWinsizeMinIon size_secondary = self.filteringWinsizeSecondaryIon if size_min > size_max: print( '\n\nWARNING: minimum window size for filtering ionosphere phase {} > maximum window size {}' .format(size_min, size_max)) print(' re-setting maximum window size to {}\n\n'.format( size_min)) size_max = size_min if size_secondary % 2 != 1: size_secondary += 1 print( 'window size of secondary filtering of ionosphere phase should be odd, window size changed to {}' .format(size_secondary)) #coherence threshold for fitting a polynomial corThresholdFit = 0.25 #ionospheric phase standard deviation after filtering std_out0 = self.filterStdIon #std_out0 = 0.1 ################################################# print('\nfiltering ionosphere') #input files ionfile = 'ion' + ml2 + '.ion' #corfile = 'diff'+ml2+'.cor' corLowerfile = subbandPrefix[0] + ml2 + '.cor' corUpperfile = subbandPrefix[1] + ml2 + '.cor' #output files ionfiltfile = 'filt_ion' + ml2 + '.ion' stdfiltfile = 'filt_ion' + ml2 + '.std' windowsizefiltfile = 'filt_ion' + ml2 + '.win' #read data img = isceobj.createImage() img.load(ionfile + '.xml') width = img.width length = img.length ion = np.fromfile(ionfile, dtype=np.float32).reshape(length, width) corLower = (np.fromfile(corLowerfile, dtype=np.float32).reshape( length * 2, width))[1:length * 2:2, :] corUpper = (np.fromfile(corUpperfile, dtype=np.float32).reshape( length * 2, width))[1:length * 2:2, :] cor = (corLower + corUpper) / 2.0 index = np.nonzero(np.logical_or(corLower == 0, corUpper == 0)) cor[index] = 0 del corLower, corUpper #masked out user-specified areas if self.maskedAreasIon != None: maskedAreas = reformatMaskedAreas(self.maskedAreasIon, length, width) for area in maskedAreas: ion[area[0]:area[1], area[2]:area[3]] = 0 cor[area[0]:area[1], area[2]:area[3]] = 0 #remove possible wired values in coherence cor[np.nonzero(cor < 0)] = 0.0 cor[np.nonzero(cor > 1)] = 0.0 #remove water body. Not helpful, just leave it here wbd = np.fromfile('wbd' + ml2 + '.wbd', dtype=np.int8).reshape(length, width) cor[np.nonzero(wbd == -1)] = 0.0 # #applying water body mask here # waterBodyFile = 'wbd'+ml2+'.wbd' # if os.path.isfile(waterBodyFile): # print('applying water body mask to coherence used to compute ionospheric phase') # wbd = np.fromfile(waterBodyFile, dtype=np.int8).reshape(length, width) # cor[np.nonzero(wbd!=0)] = 0.00001 #minimize the effect of low coherence pixels #cor[np.nonzero( (cor<0.85)*(cor!=0) )] = 0.00001 #filt = adaptive_gaussian(ion, cor, size_max, size_min) #cor**14 should be a good weight to use. 22-APR-2018 #filt = adaptive_gaussian_v0(ion, cor**corOrderFilt, size_max, size_min) #1. compute number of looks azimuthBandwidth = 0 for i, frameNumber in enumerate(self._insar.referenceFrames): for j, swathNumber in enumerate( range(self._insar.startingSwath, self._insar.endingSwath + 1)): #azimuthBandwidth += 2270.575 * 0.85 azimuthBandwidth += referenceTrack.frames[i].swaths[ j].azimuthBandwidth azimuthBandwidth = azimuthBandwidth / ( len(self._insar.referenceFrames) * (self._insar.endingSwath - self._insar.startingSwath + 1)) #azimuth number of looks should also apply to burst mode #assume range bandwidth of subband image is 1/3 of orginal range bandwidth, as in runIonSubband.py!!! numberOfLooks = referenceTrack.azimuthLineInterval * self._insar.numberAzimuthLooks1*self._insar.numberAzimuthLooksIon / (1.0/azimuthBandwidth) *\ referenceTrack.frames[0].swaths[0].rangeBandwidth / 3.0 / referenceTrack.rangeSamplingRate * self._insar.numberRangeLooks1*self._insar.numberRangeLooksIon #consider also burst characteristics. In ScanSAR-stripmap interferometry, azimuthBandwidth is from referenceTrack (ScanSAR) if self._insar.modeCombination in [21, 31]: numberOfLooks /= 5.0 if self._insar.modeCombination in [22, 32]: numberOfLooks /= 7.0 if self._insar.modeCombination in [21]: numberOfLooks *= (self._insar.burstSynchronization / 100.0) #numberOfLooks checked print( 'number of looks to be used for computing subband interferogram standard deviation: {}' .format(numberOfLooks)) if catalog is not None: catalog.addItem('number of looks of subband interferograms', numberOfLooks, 'runIonFilt') log += 'number of looks of subband interferograms: {}\n'.format( numberOfLooks) #2. compute standard deviation of the raw ionospheric phase #f0 same as in runIonSubband.py!!! def ion_std(fl, fu, numberOfLooks, cor): ''' compute standard deviation of ionospheric phase fl: lower band center frequency fu: upper band center frequency cor: coherence, must be numpy array ''' f0 = (fl + fu) / 2.0 interferogramVar = (1.0 - cor**2) / (2.0 * numberOfLooks * cor**2 + (cor == 0)) std = fl * fu / f0 / (fu**2 - fl**2) * np.sqrt(fu**2 * interferogramVar + fl**2 * interferogramVar) std[np.nonzero(cor == 0)] = 0 return std std = ion_std(fl, fu, numberOfLooks, cor) #3. compute minimum filter window size for given coherence and standard deviation of filtered ionospheric phase cor2 = np.linspace(0.1, 0.9, num=9, endpoint=True) std2 = ion_std(fl, fu, numberOfLooks, cor2) std_out2 = np.zeros(cor2.size) win2 = np.zeros(cor2.size, dtype=np.int32) for i in range(cor2.size): for size in range(9, 10001, 2): #this window must be the same as those used in adaptive_gaussian!!! gw = gaussian(size, size / 2.0, scale=1.0) scale = 1.0 / np.sum(gw / std2[i]**2) std_out2[i] = scale * np.sqrt(np.sum(gw**2 / std2[i]**2)) win2[i] = size if std_out2[i] <= std_out0: break print( 'if ionospheric phase standard deviation <= {} rad, minimum filtering window size required:' .format(std_out0)) print('coherence window size') print('************************') for x, y in zip(cor2, win2): print(' %5.2f %5d' % (x, y)) print() if catalog is not None: catalog.addItem('coherence value', cor2, 'runIonFilt') catalog.addItem('minimum filter window size', win2, 'runIonFilt') log += 'coherence value: {}\n'.format(cor2) log += 'minimum filter window size: {}\n'.format(win2) #4. filter interferogram #fit ionosphere if fit: #prepare weight wgt = std**2 wgt[np.nonzero(cor < corThresholdFit)] = 0 index = np.nonzero(wgt != 0) wgt[index] = 1.0 / (wgt[index]) #fit ion_fit, coeff = polyfit_2d(ion, wgt, 2) ion -= ion_fit * (ion != 0) #filter the rest of the ionosphere if filt: (ion_filt, std_out, window_size_out) = adaptive_gaussian(ion, std, size_min, size_max, std_out0, fit=fitAdaptive) if filtSecondary: g2d = gaussian(size_secondary, size_secondary / 2.0, scale=1.0) scale = ss.fftconvolve((ion_filt != 0), g2d, mode='same') ion_filt = (ion_filt != 0) * ss.fftconvolve( ion_filt, g2d, mode='same') / (scale + (scale == 0)) if catalog is not None: catalog.addItem('standard deviation of filtered ionospheric phase', std_out0, 'runIonFilt') log += 'standard deviation of filtered ionospheric phase: {}\n'.format( std_out0) #get final results if (fit == True) and (filt == True): ion_final = ion_filt + ion_fit * (ion_filt != 0) elif (fit == True) and (filt == False): ion_final = ion_fit elif (fit == False) and (filt == True): ion_final = ion_filt else: ion_final = ion #output results ion_final.astype(np.float32).tofile(ionfiltfile) create_xml(ionfiltfile, width, length, 'float') if filt == True: std_out.astype(np.float32).tofile(stdfiltfile) create_xml(stdfiltfile, width, length, 'float') window_size_out.astype(np.float32).tofile(windowsizefiltfile) create_xml(windowsizefiltfile, width, length, 'float') os.chdir('../../') return log
def spectralDiversity(referenceSwath, interferogramDir, interferogramPrefix, outputList, numberLooksScanSAR=None, numberRangeLooks=20, numberAzimuthLooks=10, coherenceThreshold=0.85, keep=False, filt=False, filtWinSizeRange=5, filtWinSizeAzimuth=5): ''' numberLooksScanSAR: number of looks of the ScanSAR system numberRangeLooks: number of range looks to take numberAzimuthLooks: number of azimuth looks to take keep: whether keep intermediate files ''' import os import numpy as np from isceobj.Alos2Proc.Alos2ProcPublic import create_multi_index from isceobj.Alos2Proc.Alos2ProcPublic import create_xml from isceobj.Alos2Proc.Alos2ProcPublic import multilook from isceobj.Alos2Proc.Alos2ProcPublic import cal_coherence_1 width = referenceSwath.numberOfSamples length = referenceSwath.numberOfLines lengthBurst = referenceSwath.burstSlcNumberOfLines nBurst = referenceSwath.numberOfBursts azsi = referenceSwath.azimuthLineInterval tc = referenceSwath.burstCycleLength / referenceSwath.prf bursts = [ os.path.join(interferogramDir, interferogramPrefix + '_%02d.int' % (i + 1)) for i in range(referenceSwath.numberOfBursts) ] #################################################### #input parameters rgl = numberRangeLooks azl = numberAzimuthLooks cor_th = coherenceThreshold nls0 = lengthBurst / (referenceSwath.burstSlcFirstLineOffsets[nBurst - 1] / (nBurst - 1.0)) print('number of looks of the ScanSAR system: {}'.format(nls0)) if numberLooksScanSAR != None: nls = numberLooksScanSAR else: nls = int(nls0) print('number of looks to be used: {}'.format(nls)) #################################################### #read burst interferograms inf = np.zeros((length, width, nls), dtype=np.complex64) cnt = np.zeros((length, width), dtype=np.int8) for i in range(nBurst): if (i + 1) % 5 == 0 or (i + 1) == nBurst: print('reading burst %02d' % (i + 1)) burst = np.fromfile(bursts[i], dtype=np.complex64).reshape(lengthBurst, width) #subset for the burst cntBurst = cnt[0 + referenceSwath.burstSlcFirstLineOffsets[i]:lengthBurst + referenceSwath.burstSlcFirstLineOffsets[i], :] infBurst = inf[0 + referenceSwath.burstSlcFirstLineOffsets[i]:lengthBurst + referenceSwath.burstSlcFirstLineOffsets[i], :, :] #set number of non-zero pixels cntBurst[np.nonzero(burst)] += 1 #get index index1 = np.nonzero(np.logical_and(burst != 0, cntBurst <= nls)) index2 = index1 + (cntBurst[index1] - 1, ) #set values infBurst[index2] = burst[index1] #number of looks for each sample if keep: nlFile = 'number_of_looks.nl' cnt.astype(np.int8).tofile(nlFile) create_xml(nlFile, width, length, 'byte') if filt: import scipy.signal as ss filterKernel = np.ones((filtWinSizeAzimuth, filtWinSizeRange), dtype=np.float64) for i in range(nls): print('filtering look {}'.format(i + 1)) flag = (inf[:, :, i] != 0) #scale = ss.fftconvolve(flag, filterKernel, mode='same') #inf[:,:,i] = flag*ss.fftconvolve(inf[:,:,i], filterKernel, mode='same') / (scale + (scale==0)) #this should be faster? scale = ss.convolve2d(flag, filterKernel, mode='same') inf[:, :, i] = flag * ss.convolve2d( inf[:, :, i], filterKernel, mode='same') / (scale + (scale == 0)) #width and length after multilooking widthm = int(width / rgl) lengthm = int(length / azl) #use the convention that ka > 0 ka = -np.polyval(referenceSwath.azimuthFmrateVsPixel[::-1], create_multi_index(width, rgl)) #get spectral diversity inteferogram offset_sd = [] for i in range(1, nls): print('ouput spectral diversity inteferogram %d' % i) #original spectral diversity inteferogram sd = inf[:, :, 0] * np.conj(inf[:, :, i]) #replace original amplitude with its square root index = np.nonzero(sd != 0) sd[index] /= np.sqrt(np.absolute(sd[index])) sdFile = outputList[i - 1] sd.astype(np.complex64).tofile(sdFile) create_xml(sdFile, width, length, 'int') #multi look sdm = multilook(sd, azl, rgl) cor = cal_coherence_1(sdm) #convert phase to offset offset = np.angle(sdm) / (2.0 * np.pi * ka * tc * i)[None, :] / azsi #compute offset using good samples point_index = np.nonzero( np.logical_and(cor >= cor_th, np.angle(sdm) != 0)) npoint = round(np.size(point_index) / 2) if npoint < 20: print( 'WARNING: too few good samples for spectral diversity at look {}: {}' .format(i, npoint)) offset_sd.append(0) else: offset_sd.append( np.sum(offset[point_index] * cor[point_index]) / np.sum(cor[point_index])) if keep: sdmFile = 'sd_%d_%drlks_%dalks.int' % (i, rgl, azl) sdm.astype(np.complex64).tofile(sdmFile) create_xml(sdmFile, widthm, lengthm, 'int') corFile = 'sd_%d_%drlks_%dalks.cor' % (i, rgl, azl) cor.astype(np.float32).tofile(corFile) create_xml(corFile, widthm, lengthm, 'float') offsetFile = 'sd_%d_%drlks_%dalks.off' % (i, rgl, azl) offset.astype(np.float32).tofile(offsetFile) create_xml(offsetFile, widthm, lengthm, 'float') offset_mean = np.sum(np.array(offset_sd) * np.arange(1, nls)) / np.sum( np.arange(1, nls)) return offset_mean
def runIonSubband(self): '''create subband interferograms ''' catalog = isceobj.Catalog.createCatalog(self._insar.procDoc.name) self.updateParamemetersFromUser() if not self.doIon: catalog.printToLog(logger, "runIonSubband") self._insar.procDoc.addAllFromCatalog(catalog) return masterTrack = self._insar.loadTrack(master=True) slaveTrack = self._insar.loadTrack(master=False) #using 1/3, 1/3, 1/3 band split radarWavelength = masterTrack.radarWavelength rangeBandwidth = masterTrack.frames[0].swaths[0].rangeBandwidth rangeSamplingRate = masterTrack.frames[0].swaths[0].rangeSamplingRate radarWavelengthLower = SPEED_OF_LIGHT / (SPEED_OF_LIGHT / radarWavelength - rangeBandwidth / 3.0) radarWavelengthUpper = SPEED_OF_LIGHT / (SPEED_OF_LIGHT / radarWavelength + rangeBandwidth / 3.0) subbandRadarWavelength = [radarWavelengthLower, radarWavelengthUpper] subbandBandWidth = [ rangeBandwidth / 3.0 / rangeSamplingRate, rangeBandwidth / 3.0 / rangeSamplingRate ] subbandFrequencyCenter = [ -rangeBandwidth / 3.0 / rangeSamplingRate, rangeBandwidth / 3.0 / rangeSamplingRate ] subbandPrefix = ['lower', 'upper'] ''' ionDir = { ionDir['swathMosaic'] : 'mosaic', ionDir['insar'] : 'insar', ionDir['ion'] : 'ion', ionDir['subband'] : ['lower', 'upper'], ionDir['ionCal'] : 'ion_cal' } ''' #define upper level directory names ionDir = defineIonDir() self._insar.subbandRadarWavelength = subbandRadarWavelength ############################################################ # STEP 1. create directories ############################################################ #create and enter 'ion' directory #after finishing each step, we are in this directory if not os.path.exists(ionDir['ion']): os.makedirs(ionDir['ion']) os.chdir(ionDir['ion']) #create insar processing directories for k in range(2): subbandDir = ionDir['subband'][k] for i, frameNumber in enumerate(self._insar.masterFrames): frameDir = 'f{}_{}'.format(i + 1, frameNumber) for j, swathNumber in enumerate( range(self._insar.startingSwath, self._insar.endingSwath + 1)): swathDir = 's{}'.format(swathNumber) fullDir = os.path.join(subbandDir, frameDir, swathDir) if not os.path.exists(fullDir): os.makedirs(fullDir) #create ionospheric phase directory if not os.path.exists(ionDir['ionCal']): os.makedirs(ionDir['ionCal']) ############################################################ # STEP 2. create subband interferograms ############################################################ import numpy as np import stdproc from iscesys.StdOEL.StdOELPy import create_writer from isceobj.Alos2Proc.Alos2ProcPublic import readOffset from contrib.alos2proc.alos2proc import rg_filter for i, frameNumber in enumerate(self._insar.masterFrames): frameDir = 'f{}_{}'.format(i + 1, frameNumber) for j, swathNumber in enumerate( range(self._insar.startingSwath, self._insar.endingSwath + 1)): swathDir = 's{}'.format(swathNumber) #filter master and slave images for slcx in [self._insar.masterSlc, self._insar.slaveSlc]: slc = os.path.join('../', frameDir, swathDir, slcx) slcLower = os.path.join(ionDir['subband'][0], frameDir, swathDir, slcx) slcUpper = os.path.join(ionDir['subband'][1], frameDir, swathDir, slcx) rg_filter(slc, 2, [slcLower, slcUpper], subbandBandWidth, subbandFrequencyCenter, 257, 2048, 0.1, 0, 0.0) #resample for k in range(2): os.chdir(os.path.join(ionDir['subband'][k], frameDir, swathDir)) #recreate xml file to remove the file path #can also use fixImageXml.py? for x in [self._insar.masterSlc, self._insar.slaveSlc]: img = isceobj.createSlcImage() img.load(x + '.xml') img.setFilename(x) img.extraFilename = x + '.vrt' img.setAccessMode('READ') img.renderHdr() ############################################# #1. form interferogram ############################################# masterSwath = masterTrack.frames[i].swaths[j] slaveSwath = slaveTrack.frames[i].swaths[j] refinedOffsets = readOffset( os.path.join('../../../../', frameDir, swathDir, 'cull.off')) intWidth = int(masterSwath.numberOfSamples / self._insar.numberRangeLooks1) intLength = int(masterSwath.numberOfLines / self._insar.numberAzimuthLooks1) dopplerVsPixel = [ i / slaveSwath.prf for i in slaveSwath.dopplerVsPixel ] #master slc mSLC = isceobj.createSlcImage() mSLC.load(self._insar.masterSlc + '.xml') mSLC.setAccessMode('read') mSLC.createImage() #slave slc sSLC = isceobj.createSlcImage() sSLC.load(self._insar.slaveSlc + '.xml') sSLC.setAccessMode('read') sSLC.createImage() #interferogram interf = isceobj.createIntImage() interf.setFilename(self._insar.interferogram) interf.setWidth(intWidth) interf.setAccessMode('write') interf.createImage() #amplitdue amplitude = isceobj.createAmpImage() amplitude.setFilename(self._insar.amplitude) amplitude.setWidth(intWidth) amplitude.setAccessMode('write') amplitude.createImage() #create a writer for resamp stdWriter = create_writer("log", "", True, filename="resamp.log") stdWriter.setFileTag("resamp", "log") stdWriter.setFileTag("resamp", "err") stdWriter.setFileTag("resamp", "out") #set up resampling program now #The setting has been compared with resamp_roi's setting in ROI_pac item by item. #The two kinds of setting are exactly the same. The number of setting items are #exactly the same objResamp = stdproc.createResamp() objResamp.wireInputPort(name='offsets', object=refinedOffsets) objResamp.stdWriter = stdWriter objResamp.setNumberFitCoefficients(6) objResamp.setNumberRangeBin1(masterSwath.numberOfSamples) objResamp.setNumberRangeBin2(slaveSwath.numberOfSamples) objResamp.setStartLine(1) objResamp.setNumberLines(masterSwath.numberOfLines) objResamp.setFirstLineOffset(1) objResamp.setDopplerCentroidCoefficients(dopplerVsPixel) objResamp.setRadarWavelength(subbandRadarWavelength[k]) objResamp.setSlantRangePixelSpacing(slaveSwath.rangePixelSize) objResamp.setNumberRangeLooks(self._insar.numberRangeLooks1) objResamp.setNumberAzimuthLooks( self._insar.numberAzimuthLooks1) objResamp.setFlattenWithOffsetFitFlag(0) objResamp.resamp(mSLC, sSLC, interf, amplitude) #finialize images mSLC.finalizeImage() sSLC.finalizeImage() interf.finalizeImage() amplitude.finalizeImage() stdWriter.finalize() ############################################# #2. trim amplitude ############################################# #using memmap instead, which should be faster, since we only have a few pixels to change amp = np.memmap(self._insar.amplitude, dtype='complex64', mode='r+', shape=(intLength, intWidth)) index = np.nonzero((np.real(amp) == 0) + (np.imag(amp) == 0)) amp[index] = 0 #Deletion flushes memory changes to disk before removing the object: del amp ############################################# #3. delete subband slcs ############################################# os.remove(self._insar.masterSlc) os.remove(self._insar.masterSlc + '.vrt') os.remove(self._insar.masterSlc + '.xml') os.remove(self._insar.slaveSlc) os.remove(self._insar.slaveSlc + '.vrt') os.remove(self._insar.slaveSlc + '.xml') os.chdir('../../../') ############################################################ # STEP 3. mosaic swaths ############################################################ from isceobj.Alos2Proc.runSwathMosaic import swathMosaic from isceobj.Alos2Proc.Alos2ProcPublic import create_xml for k in range(2): os.chdir(ionDir['subband'][k]) for i, frameNumber in enumerate(self._insar.masterFrames): frameDir = 'f{}_{}'.format(i + 1, frameNumber) os.chdir(frameDir) mosaicDir = ionDir['swathMosaic'] if not os.path.exists(mosaicDir): os.makedirs(mosaicDir) os.chdir(mosaicDir) if not ( ((self._insar.modeCombination == 21) or \ (self._insar.modeCombination == 22) or \ (self._insar.modeCombination == 31) or \ (self._insar.modeCombination == 32)) and (self._insar.endingSwath-self._insar.startingSwath+1 > 1) ): import shutil swathDir = 's{}'.format( masterTrack.frames[i].swaths[0].swathNumber) # if not os.path.isfile(self._insar.interferogram): # os.symlink(os.path.join('../', swathDir, self._insar.interferogram), self._insar.interferogram) # shutil.copy2(os.path.join('../', swathDir, self._insar.interferogram+'.vrt'), self._insar.interferogram+'.vrt') # shutil.copy2(os.path.join('../', swathDir, self._insar.interferogram+'.xml'), self._insar.interferogram+'.xml') # if not os.path.isfile(self._insar.amplitude): # os.symlink(os.path.join('../', swathDir, self._insar.amplitude), self._insar.amplitude) # shutil.copy2(os.path.join('../', swathDir, self._insar.amplitude+'.vrt'), self._insar.amplitude+'.vrt') # shutil.copy2(os.path.join('../', swathDir, self._insar.amplitude+'.xml'), self._insar.amplitude+'.xml') os.rename( os.path.join('../', swathDir, self._insar.interferogram), self._insar.interferogram) os.rename( os.path.join('../', swathDir, self._insar.interferogram + '.vrt'), self._insar.interferogram + '.vrt') os.rename( os.path.join('../', swathDir, self._insar.interferogram + '.xml'), self._insar.interferogram + '.xml') os.rename(os.path.join('../', swathDir, self._insar.amplitude), self._insar.amplitude) os.rename( os.path.join('../', swathDir, self._insar.amplitude + '.vrt'), self._insar.amplitude + '.vrt') os.rename( os.path.join('../', swathDir, self._insar.amplitude + '.xml'), self._insar.amplitude + '.xml') #no need to update frame parameters here os.chdir('../') #no need to save parameter file here os.chdir('../') continue #choose offsets numberOfFrames = len(masterTrack.frames) numberOfSwaths = len(masterTrack.frames[i].swaths) if self.swathOffsetMatching: #no need to do this as the API support 2-d list #rangeOffsets = (np.array(self._insar.swathRangeOffsetMatchingMaster)).reshape(numberOfFrames, numberOfSwaths) #azimuthOffsets = (np.array(self._insar.swathAzimuthOffsetMatchingMaster)).reshape(numberOfFrames, numberOfSwaths) rangeOffsets = self._insar.swathRangeOffsetMatchingMaster azimuthOffsets = self._insar.swathAzimuthOffsetMatchingMaster else: #rangeOffsets = (np.array(self._insar.swathRangeOffsetGeometricalMaster)).reshape(numberOfFrames, numberOfSwaths) #azimuthOffsets = (np.array(self._insar.swathAzimuthOffsetGeometricalMaster)).reshape(numberOfFrames, numberOfSwaths) rangeOffsets = self._insar.swathRangeOffsetGeometricalMaster azimuthOffsets = self._insar.swathAzimuthOffsetGeometricalMaster rangeOffsets = rangeOffsets[i] azimuthOffsets = azimuthOffsets[i] #list of input files inputInterferograms = [] inputAmplitudes = [] for j, swathNumber in enumerate( range(self._insar.startingSwath, self._insar.endingSwath + 1)): swathDir = 's{}'.format(swathNumber) inputInterferograms.append( os.path.join('../', swathDir, self._insar.interferogram)) inputAmplitudes.append( os.path.join('../', swathDir, self._insar.amplitude)) #note that frame parameters are updated after mosaicking, here no need to update parameters #mosaic amplitudes swathMosaic(masterTrack.frames[i], inputAmplitudes, self._insar.amplitude, rangeOffsets, azimuthOffsets, self._insar.numberRangeLooks1, self._insar.numberAzimuthLooks1, resamplingMethod=0) #mosaic interferograms swathMosaic(masterTrack.frames[i], inputInterferograms, self._insar.interferogram, rangeOffsets, azimuthOffsets, self._insar.numberRangeLooks1, self._insar.numberAzimuthLooks1, updateFrame=False, phaseCompensation=True, resamplingMethod=1) create_xml(self._insar.amplitude, masterTrack.frames[i].numberOfSamples, masterTrack.frames[i].numberOfLines, 'amp') create_xml(self._insar.interferogram, masterTrack.frames[i].numberOfSamples, masterTrack.frames[i].numberOfLines, 'int') #update slave frame parameters here, here no need to update parameters os.chdir('../') #save parameter file, here no need to save parameter file os.chdir('../') os.chdir('../') ############################################################ # STEP 4. mosaic frames ############################################################ from isceobj.Alos2Proc.runFrameMosaic import frameMosaic from isceobj.Alos2Proc.Alos2ProcPublic import create_xml for k in range(2): os.chdir(ionDir['subband'][k]) mosaicDir = ionDir['insar'] if not os.path.exists(mosaicDir): os.makedirs(mosaicDir) os.chdir(mosaicDir) numberOfFrames = len(masterTrack.frames) if numberOfFrames == 1: import shutil frameDir = os.path.join('f1_{}/mosaic'.format( self._insar.masterFrames[0])) # if not os.path.isfile(self._insar.interferogram): # os.symlink(os.path.join('../', frameDir, self._insar.interferogram), self._insar.interferogram) # #shutil.copy2() can overwrite # shutil.copy2(os.path.join('../', frameDir, self._insar.interferogram+'.vrt'), self._insar.interferogram+'.vrt') # shutil.copy2(os.path.join('../', frameDir, self._insar.interferogram+'.xml'), self._insar.interferogram+'.xml') # if not os.path.isfile(self._insar.amplitude): # os.symlink(os.path.join('../', frameDir, self._insar.amplitude), self._insar.amplitude) # shutil.copy2(os.path.join('../', frameDir, self._insar.amplitude+'.vrt'), self._insar.amplitude+'.vrt') # shutil.copy2(os.path.join('../', frameDir, self._insar.amplitude+'.xml'), self._insar.amplitude+'.xml') os.rename(os.path.join('../', frameDir, self._insar.interferogram), self._insar.interferogram) os.rename( os.path.join('../', frameDir, self._insar.interferogram + '.vrt'), self._insar.interferogram + '.vrt') os.rename( os.path.join('../', frameDir, self._insar.interferogram + '.xml'), self._insar.interferogram + '.xml') os.rename(os.path.join('../', frameDir, self._insar.amplitude), self._insar.amplitude) os.rename( os.path.join('../', frameDir, self._insar.amplitude + '.vrt'), self._insar.amplitude + '.vrt') os.rename( os.path.join('../', frameDir, self._insar.amplitude + '.xml'), self._insar.amplitude + '.xml') #update track parameters, no need to update track parameters here else: #choose offsets if self.frameOffsetMatching: rangeOffsets = self._insar.frameRangeOffsetMatchingMaster azimuthOffsets = self._insar.frameAzimuthOffsetMatchingMaster else: rangeOffsets = self._insar.frameRangeOffsetGeometricalMaster azimuthOffsets = self._insar.frameAzimuthOffsetGeometricalMaster #list of input files inputInterferograms = [] inputAmplitudes = [] for i, frameNumber in enumerate(self._insar.masterFrames): frameDir = 'f{}_{}'.format(i + 1, frameNumber) inputInterferograms.append( os.path.join('../', frameDir, 'mosaic', self._insar.interferogram)) inputAmplitudes.append( os.path.join('../', frameDir, 'mosaic', self._insar.amplitude)) #note that track parameters are updated after mosaicking #mosaic amplitudes frameMosaic(masterTrack, inputAmplitudes, self._insar.amplitude, rangeOffsets, azimuthOffsets, self._insar.numberRangeLooks1, self._insar.numberAzimuthLooks1, updateTrack=False, phaseCompensation=False, resamplingMethod=0) #mosaic interferograms frameMosaic(masterTrack, inputInterferograms, self._insar.interferogram, rangeOffsets, azimuthOffsets, self._insar.numberRangeLooks1, self._insar.numberAzimuthLooks1, updateTrack=False, phaseCompensation=True, resamplingMethod=1) create_xml(self._insar.amplitude, masterTrack.numberOfSamples, masterTrack.numberOfLines, 'amp') create_xml(self._insar.interferogram, masterTrack.numberOfSamples, masterTrack.numberOfLines, 'int') #update slave parameters here, no need to update slave parameters here os.chdir('../') #save parameter file, no need to save parameter file here os.chdir('../') ############################################################ # STEP 5. clear frame processing files ############################################################ import shutil from isceobj.Alos2Proc.Alos2ProcPublic import runCmd for k in range(2): os.chdir(ionDir['subband'][k]) for i, frameNumber in enumerate(self._insar.masterFrames): frameDir = 'f{}_{}'.format(i + 1, frameNumber) shutil.rmtree(frameDir) #cmd = 'rm -rf {}'.format(frameDir) #runCmd(cmd) os.chdir('../') ############################################################ # STEP 6. create differential interferograms ############################################################ import numpy as np from isceobj.Alos2Proc.Alos2ProcPublic import runCmd for k in range(2): os.chdir(ionDir['subband'][k]) insarDir = ionDir['insar'] if not os.path.exists(insarDir): os.makedirs(insarDir) os.chdir(insarDir) rangePixelSize = self._insar.numberRangeLooks1 * masterTrack.rangePixelSize radarWavelength = subbandRadarWavelength[k] rectRangeOffset = os.path.join('../../../', insarDir, self._insar.rectRangeOffset) cmd = "imageMath.py -e='a*exp(-1.0*J*b*4.0*{}*{}/{}) * (b!=0)' --a={} --b={} -o {} -t cfloat".format( np.pi, rangePixelSize, radarWavelength, self._insar.interferogram, rectRangeOffset, self._insar.differentialInterferogram) runCmd(cmd) os.chdir('../../') os.chdir('../') catalog.printToLog(logger, "runIonSubband") self._insar.procDoc.addAllFromCatalog(catalog)
def runIonSubband(self): '''create subband interferograms ''' catalog = isceobj.Catalog.createCatalog(self._insar.procDoc.name) self.updateParamemetersFromUser() if not self.doIon: catalog.printToLog(logger, "runIonSubband") self._insar.procDoc.addAllFromCatalog(catalog) return referenceTrack = self._insar.loadTrack(reference=True) secondaryTrack = self._insar.loadTrack(reference=False) #using 1/3, 1/3, 1/3 band split radarWavelength = referenceTrack.radarWavelength rangeBandwidth = referenceTrack.frames[0].swaths[0].rangeBandwidth rangeSamplingRate = referenceTrack.frames[0].swaths[0].rangeSamplingRate radarWavelengthLower = SPEED_OF_LIGHT / (SPEED_OF_LIGHT / radarWavelength - rangeBandwidth / 3.0) radarWavelengthUpper = SPEED_OF_LIGHT / (SPEED_OF_LIGHT / radarWavelength + rangeBandwidth / 3.0) subbandRadarWavelength = [radarWavelengthLower, radarWavelengthUpper] subbandBandWidth = [ rangeBandwidth / 3.0 / rangeSamplingRate, rangeBandwidth / 3.0 / rangeSamplingRate ] subbandFrequencyCenter = [ -rangeBandwidth / 3.0 / rangeSamplingRate, rangeBandwidth / 3.0 / rangeSamplingRate ] subbandPrefix = ['lower', 'upper'] ''' ionDir = { ionDir['swathMosaic'] : 'mosaic', ionDir['insar'] : 'insar', ionDir['ion'] : 'ion', ionDir['subband'] : ['lower', 'upper'], ionDir['ionCal'] : 'ion_cal' } ''' #define upper level directory names ionDir = defineIonDir() self._insar.subbandRadarWavelength = subbandRadarWavelength ############################################################ # STEP 1. create directories ############################################################ #create and enter 'ion' directory #after finishing each step, we are in this directory os.makedirs(ionDir['ion'], exist_ok=True) os.chdir(ionDir['ion']) #create insar processing directories for k in range(2): subbandDir = ionDir['subband'][k] for i, frameNumber in enumerate(self._insar.referenceFrames): frameDir = 'f{}_{}'.format(i + 1, frameNumber) for j, swathNumber in enumerate( range(self._insar.startingSwath, self._insar.endingSwath + 1)): swathDir = 's{}'.format(swathNumber) fullDir = os.path.join(subbandDir, frameDir, swathDir) os.makedirs(fullDir, exist_ok=True) #create ionospheric phase directory os.makedirs(ionDir['ionCal']) ############################################################ # STEP 2. create subband interferograms ############################################################ import shutil import numpy as np from contrib.alos2proc.alos2proc import rg_filter from isceobj.Alos2Proc.Alos2ProcPublic import resampleBursts from isceobj.Alos2Proc.Alos2ProcPublic import mosaicBurstAmplitude from isceobj.Alos2Proc.Alos2ProcPublic import mosaicBurstInterferogram from isceobj.Alos2Proc.Alos2ProcPublic import create_xml for i, frameNumber in enumerate(self._insar.referenceFrames): frameDir = 'f{}_{}'.format(i + 1, frameNumber) for j, swathNumber in enumerate( range(self._insar.startingSwath, self._insar.endingSwath + 1)): swathDir = 's{}'.format(swathNumber) #filter reference and secondary images for burstPrefix, swath in zip([ self._insar.referenceBurstPrefix, self._insar.secondaryBurstPrefix ], [ referenceTrack.frames[i].swaths[j], secondaryTrack.frames[i].swaths[j] ]): slcDir = os.path.join('../', frameDir, swathDir, burstPrefix) slcLowerDir = os.path.join(ionDir['subband'][0], frameDir, swathDir, burstPrefix) slcUpperDir = os.path.join(ionDir['subband'][1], frameDir, swathDir, burstPrefix) os.makedirs(slcLowerDir, exist_ok=True) os.makedirs(slcUpperDir, exist_ok=True) for k in range(swath.numberOfBursts): print('processing burst: %02d' % (k + 1)) slc = os.path.join(slcDir, burstPrefix + '_%02d.slc' % (k + 1)) slcLower = os.path.join( slcLowerDir, burstPrefix + '_%02d.slc' % (k + 1)) slcUpper = os.path.join( slcUpperDir, burstPrefix + '_%02d.slc' % (k + 1)) rg_filter(slc, 2, [slcLower, slcUpper], subbandBandWidth, subbandFrequencyCenter, 257, 2048, 0.1, 0, 0.0) #resample for l in range(2): os.chdir(os.path.join(ionDir['subband'][l], frameDir, swathDir)) #recreate xml file to remove the file path #can also use fixImageXml.py? for burstPrefix, swath in zip([ self._insar.referenceBurstPrefix, self._insar.secondaryBurstPrefix ], [ referenceTrack.frames[i].swaths[j], secondaryTrack.frames[i].swaths[j] ]): os.chdir(burstPrefix) for k in range(swath.numberOfBursts): slc = burstPrefix + '_%02d.slc' % (k + 1) img = isceobj.createSlcImage() img.load(slc + '.xml') img.setFilename(slc) img.extraFilename = slc + '.vrt' img.setAccessMode('READ') img.renderHdr() os.chdir('../') ############################################# #1. form interferogram ############################################# referenceSwath = referenceTrack.frames[i].swaths[j] secondarySwath = secondaryTrack.frames[i].swaths[j] #set up resampling parameters width = referenceSwath.numberOfSamples length = referenceSwath.numberOfLines polyCoeff = self._insar.rangeResidualOffsetCc[i][j] rgIndex = (np.arange(width) - polyCoeff[-1][0]) / polyCoeff[-1][1] azIndex = (np.arange(length) - polyCoeff[-1][2]) / polyCoeff[-1][3] 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 azimuthOffset = self._insar.azimuthResidualOffsetCc[i][j] secondaryBurstResampledDir = self._insar.secondaryBurstPrefix + '_2_coreg_cc' interferogramDir = 'burst_interf_2_coreg_cc' interferogramPrefix = self._insar.referenceBurstPrefix + '-' + self._insar.secondaryBurstPrefix resampleBursts( referenceSwath, secondarySwath, self._insar.referenceBurstPrefix, self._insar.secondaryBurstPrefix, secondaryBurstResampledDir, interferogramDir, self._insar.referenceBurstPrefix, self._insar.secondaryBurstPrefix, self._insar.secondaryBurstPrefix, interferogramPrefix, os.path.join( '../../../../{}/{}'.format(frameDir, swathDir), self._insar.rangeOffset), os.path.join( '../../../../{}/{}'.format(frameDir, swathDir), self._insar.azimuthOffset), rangeOffsetResidual=rangeOffset, azimuthOffsetResidual=azimuthOffset) os.chdir(self._insar.referenceBurstPrefix) mosaicBurstAmplitude(referenceSwath, self._insar.referenceBurstPrefix, self._insar.referenceMagnitude, numberOfLooksThreshold=4) os.chdir('../') os.chdir(secondaryBurstResampledDir) mosaicBurstAmplitude(referenceSwath, self._insar.secondaryBurstPrefix, self._insar.secondaryMagnitude, numberOfLooksThreshold=4) os.chdir('../') os.chdir(interferogramDir) mosaicBurstInterferogram(referenceSwath, interferogramPrefix, self._insar.interferogram, numberOfLooksThreshold=4) os.chdir('../') amp = np.zeros((referenceSwath.numberOfLines, 2 * referenceSwath.numberOfSamples), dtype=np.float32) amp[0:, 1:referenceSwath.numberOfSamples*2:2] = np.fromfile(os.path.join(secondaryBurstResampledDir, self._insar.secondaryMagnitude), \ dtype=np.float32).reshape(referenceSwath.numberOfLines, referenceSwath.numberOfSamples) amp[0:, 0:referenceSwath.numberOfSamples*2:2] = np.fromfile(os.path.join(self._insar.referenceBurstPrefix, self._insar.referenceMagnitude), \ dtype=np.float32).reshape(referenceSwath.numberOfLines, referenceSwath.numberOfSamples) amp.astype(np.float32).tofile(self._insar.amplitude) create_xml(self._insar.amplitude, referenceSwath.numberOfSamples, referenceSwath.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') ############################################# #2. delete subband slcs ############################################# shutil.rmtree(self._insar.referenceBurstPrefix) shutil.rmtree(self._insar.secondaryBurstPrefix) shutil.rmtree(secondaryBurstResampledDir) shutil.rmtree(interferogramDir) os.chdir('../../../') ############################################################ # STEP 3. mosaic swaths ############################################################ from isceobj.Alos2Proc.runSwathMosaic import swathMosaic from isceobj.Alos2Proc.Alos2ProcPublic import create_xml for k in range(2): os.chdir(ionDir['subband'][k]) for i, frameNumber in enumerate(self._insar.referenceFrames): frameDir = 'f{}_{}'.format(i + 1, frameNumber) os.chdir(frameDir) mosaicDir = 'mosaic' os.makedirs(mosaicDir, exist_ok=True) os.chdir(mosaicDir) if self._insar.endingSwath - self._insar.startingSwath + 1 == 1: import shutil swathDir = 's{}'.format( referenceTrack.frames[i].swaths[0].swathNumber) # if not os.path.isfile(self._insar.interferogram): # os.symlink(os.path.join('../', swathDir, self._insar.interferogram), self._insar.interferogram) # shutil.copy2(os.path.join('../', swathDir, self._insar.interferogram+'.vrt'), self._insar.interferogram+'.vrt') # shutil.copy2(os.path.join('../', swathDir, self._insar.interferogram+'.xml'), self._insar.interferogram+'.xml') # if not os.path.isfile(self._insar.amplitude): # os.symlink(os.path.join('../', swathDir, self._insar.amplitude), self._insar.amplitude) # shutil.copy2(os.path.join('../', swathDir, self._insar.amplitude+'.vrt'), self._insar.amplitude+'.vrt') # shutil.copy2(os.path.join('../', swathDir, self._insar.amplitude+'.xml'), self._insar.amplitude+'.xml') os.rename( os.path.join('../', swathDir, self._insar.interferogram), self._insar.interferogram) os.rename( os.path.join('../', swathDir, self._insar.interferogram + '.vrt'), self._insar.interferogram + '.vrt') os.rename( os.path.join('../', swathDir, self._insar.interferogram + '.xml'), self._insar.interferogram + '.xml') os.rename(os.path.join('../', swathDir, self._insar.amplitude), self._insar.amplitude) os.rename( os.path.join('../', swathDir, self._insar.amplitude + '.vrt'), self._insar.amplitude + '.vrt') os.rename( os.path.join('../', swathDir, self._insar.amplitude + '.xml'), self._insar.amplitude + '.xml') os.chdir('../') os.chdir('../') continue #choose offsets numberOfFrames = len(referenceTrack.frames) numberOfSwaths = len(referenceTrack.frames[i].swaths) if self.swathOffsetMatching: #no need to do this as the API support 2-d list #rangeOffsets = (np.array(self._insar.swathRangeOffsetMatchingReference)).reshape(numberOfFrames, numberOfSwaths) #azimuthOffsets = (np.array(self._insar.swathAzimuthOffsetMatchingReference)).reshape(numberOfFrames, numberOfSwaths) rangeOffsets = self._insar.swathRangeOffsetMatchingReference azimuthOffsets = self._insar.swathAzimuthOffsetMatchingReference else: #rangeOffsets = (np.array(self._insar.swathRangeOffsetGeometricalReference)).reshape(numberOfFrames, numberOfSwaths) #azimuthOffsets = (np.array(self._insar.swathAzimuthOffsetGeometricalReference)).reshape(numberOfFrames, numberOfSwaths) rangeOffsets = self._insar.swathRangeOffsetGeometricalReference azimuthOffsets = self._insar.swathAzimuthOffsetGeometricalReference rangeOffsets = rangeOffsets[i] azimuthOffsets = azimuthOffsets[i] #list of input files inputInterferograms = [] inputAmplitudes = [] phaseDiff = [None] for j, swathNumber in enumerate( range(self._insar.startingSwath, self._insar.endingSwath + 1)): swathDir = 's{}'.format(swathNumber) inputInterferograms.append( os.path.join('../', swathDir, self._insar.interferogram)) inputAmplitudes.append( os.path.join('../', swathDir, self._insar.amplitude)) #compute phase needed to be compensated using startingRange if j >= 1: #phaseDiffSwath1 = -4.0 * np.pi * (referenceTrack.frames[i].swaths[j-1].startingRange - secondaryTrack.frames[i].swaths[j-1].startingRange)/subbandRadarWavelength[k] #phaseDiffSwath2 = -4.0 * np.pi * (referenceTrack.frames[i].swaths[j].startingRange - secondaryTrack.frames[i].swaths[j].startingRange)/subbandRadarWavelength[k] phaseDiffSwath1 = +4.0 * np.pi * referenceTrack.frames[i].swaths[j-1].startingRange * (1.0/radarWavelength - 1.0/subbandRadarWavelength[k]) \ -4.0 * np.pi * secondaryTrack.frames[i].swaths[j-1].startingRange * (1.0/radarWavelength - 1.0/subbandRadarWavelength[k]) phaseDiffSwath2 = +4.0 * np.pi * referenceTrack.frames[i].swaths[j].startingRange * (1.0/radarWavelength - 1.0/subbandRadarWavelength[k]) \ -4.0 * np.pi * secondaryTrack.frames[i].swaths[j].startingRange * (1.0/radarWavelength - 1.0/subbandRadarWavelength[k]) if referenceTrack.frames[i].swaths[j-1].startingRange - secondaryTrack.frames[i].swaths[j-1].startingRange == \ referenceTrack.frames[i].swaths[j].startingRange - secondaryTrack.frames[i].swaths[j].startingRange: #phaseDiff.append(phaseDiffSwath2 - phaseDiffSwath1) #if reference and secondary versions are all before or after version 2.025 (starting range error < 0.5 m), #it should be OK to do the above. #see results in neom where it meets the above requirement, but there is still phase diff #to be less risky, we do not input values here phaseDiff.append(None) else: phaseDiff.append(None) #note that frame parameters are updated after mosaicking #mosaic amplitudes swathMosaic(referenceTrack.frames[i], inputAmplitudes, self._insar.amplitude, rangeOffsets, azimuthOffsets, self._insar.numberRangeLooks1, self._insar.numberAzimuthLooks1, resamplingMethod=0) #mosaic interferograms #These are for ALOS-2, may need to change for ALOS-4! phaseDiffFixed = [ 0.0, 0.4754024578084084, 0.9509913179406437, 1.4261648478671614, 2.179664007520499, 2.6766909968024932, 3.130810857 ] snapThreshold = 0.2 #the above preparetions only applies to 'self._insar.modeCombination == 21' #looks like it also works for 31 (scansarNominalModes-stripmapModes) if self._insar.modeCombination != 21: phaseDiff = None phaseDiffFixed = None snapThreshold = None (phaseDiffEst, phaseDiffUsed, phaseDiffSource) = swathMosaic(referenceTrack.frames[i], inputInterferograms, self._insar.interferogram, rangeOffsets, azimuthOffsets, self._insar.numberRangeLooks1, self._insar.numberAzimuthLooks1, updateFrame=False, phaseCompensation=True, phaseDiff=phaseDiff, phaseDiffFixed=phaseDiffFixed, snapThreshold=snapThreshold, pcRangeLooks=1, pcAzimuthLooks=3, filt=False, resamplingMethod=1) #the first item is meaningless for all the following list, so only record the following items if phaseDiff == None: phaseDiff = [ None for iii in range(self._insar.startingSwath, self._insar.endingSwath + 1) ] catalog.addItem( '{} subswath phase difference input'.format( ionDir['subband'][k]), phaseDiff[1:], 'runIonSubband') catalog.addItem( '{} subswath phase difference estimated'.format( ionDir['subband'][k]), phaseDiffEst[1:], 'runIonSubband') catalog.addItem( '{} subswath phase difference used'.format( ionDir['subband'][k]), phaseDiffUsed[1:], 'runIonSubband') catalog.addItem( '{} subswath phase difference used source'.format( ionDir['subband'][k]), phaseDiffSource[1:], 'runIonSubband') #check if there is value around 3.130810857, which may not be stable phaseDiffUnstableExist = False for xxx in phaseDiffUsed: if abs(abs(xxx) - 3.130810857) < 0.2: phaseDiffUnstableExist = True catalog.addItem( '{} subswath phase difference unstable exists'.format( ionDir['subband'][k]), phaseDiffUnstableExist, 'runIonSubband') create_xml(self._insar.amplitude, referenceTrack.frames[i].numberOfSamples, referenceTrack.frames[i].numberOfLines, 'amp') create_xml(self._insar.interferogram, referenceTrack.frames[i].numberOfSamples, referenceTrack.frames[i].numberOfLines, 'int') os.chdir('../') os.chdir('../') os.chdir('../') ############################################################ # STEP 4. mosaic frames ############################################################ from isceobj.Alos2Proc.runFrameMosaic import frameMosaic from isceobj.Alos2Proc.Alos2ProcPublic import create_xml for k in range(2): os.chdir(ionDir['subband'][k]) mosaicDir = 'insar' os.makedirs(mosaicDir, exist_ok=True) os.chdir(mosaicDir) numberOfFrames = len(referenceTrack.frames) if numberOfFrames == 1: import shutil frameDir = os.path.join('f1_{}/mosaic'.format( self._insar.referenceFrames[0])) # if not os.path.isfile(self._insar.interferogram): # os.symlink(os.path.join('../', frameDir, self._insar.interferogram), self._insar.interferogram) # #shutil.copy2() can overwrite # shutil.copy2(os.path.join('../', frameDir, self._insar.interferogram+'.vrt'), self._insar.interferogram+'.vrt') # shutil.copy2(os.path.join('../', frameDir, self._insar.interferogram+'.xml'), self._insar.interferogram+'.xml') # if not os.path.isfile(self._insar.amplitude): # os.symlink(os.path.join('../', frameDir, self._insar.amplitude), self._insar.amplitude) # shutil.copy2(os.path.join('../', frameDir, self._insar.amplitude+'.vrt'), self._insar.amplitude+'.vrt') # shutil.copy2(os.path.join('../', frameDir, self._insar.amplitude+'.xml'), self._insar.amplitude+'.xml') os.rename(os.path.join('../', frameDir, self._insar.interferogram), self._insar.interferogram) os.rename( os.path.join('../', frameDir, self._insar.interferogram + '.vrt'), self._insar.interferogram + '.vrt') os.rename( os.path.join('../', frameDir, self._insar.interferogram + '.xml'), self._insar.interferogram + '.xml') os.rename(os.path.join('../', frameDir, self._insar.amplitude), self._insar.amplitude) os.rename( os.path.join('../', frameDir, self._insar.amplitude + '.vrt'), self._insar.amplitude + '.vrt') os.rename( os.path.join('../', frameDir, self._insar.amplitude + '.xml'), self._insar.amplitude + '.xml') else: #choose offsets if self.frameOffsetMatching: rangeOffsets = self._insar.frameRangeOffsetMatchingReference azimuthOffsets = self._insar.frameAzimuthOffsetMatchingReference else: rangeOffsets = self._insar.frameRangeOffsetGeometricalReference azimuthOffsets = self._insar.frameAzimuthOffsetGeometricalReference #list of input files inputInterferograms = [] inputAmplitudes = [] for i, frameNumber in enumerate(self._insar.referenceFrames): frameDir = 'f{}_{}'.format(i + 1, frameNumber) inputInterferograms.append( os.path.join('../', frameDir, 'mosaic', self._insar.interferogram)) inputAmplitudes.append( os.path.join('../', frameDir, 'mosaic', self._insar.amplitude)) #note that track parameters are updated after mosaicking #mosaic amplitudes frameMosaic(referenceTrack, inputAmplitudes, self._insar.amplitude, rangeOffsets, azimuthOffsets, self._insar.numberRangeLooks1, self._insar.numberAzimuthLooks1, updateTrack=False, phaseCompensation=False, resamplingMethod=0) #mosaic interferograms frameMosaic(referenceTrack, inputInterferograms, self._insar.interferogram, rangeOffsets, azimuthOffsets, self._insar.numberRangeLooks1, self._insar.numberAzimuthLooks1, updateTrack=False, phaseCompensation=True, resamplingMethod=1) create_xml(self._insar.amplitude, referenceTrack.numberOfSamples, referenceTrack.numberOfLines, 'amp') create_xml(self._insar.interferogram, referenceTrack.numberOfSamples, referenceTrack.numberOfLines, 'int') os.chdir('../') os.chdir('../') ############################################################ # STEP 5. clear frame processing files ############################################################ import shutil from isceobj.Alos2Proc.Alos2ProcPublic import runCmd for k in range(2): os.chdir(ionDir['subband'][k]) for i, frameNumber in enumerate(self._insar.referenceFrames): frameDir = 'f{}_{}'.format(i + 1, frameNumber) shutil.rmtree(frameDir) #cmd = 'rm -rf {}'.format(frameDir) #runCmd(cmd) os.chdir('../') ############################################################ # STEP 6. create differential interferograms ############################################################ import numpy as np from isceobj.Alos2Proc.Alos2ProcPublic import runCmd for k in range(2): os.chdir(ionDir['subband'][k]) insarDir = ionDir['insar'] os.makedirs(insarDir, exist_ok=True) os.chdir(insarDir) rangePixelSize = self._insar.numberRangeLooks1 * referenceTrack.rangePixelSize radarWavelength = subbandRadarWavelength[k] rectRangeOffset = os.path.join('../../../', insarDir, self._insar.rectRangeOffset) cmd = "imageMath.py -e='a*exp(-1.0*J*b*4.0*{}*{}/{}) * (b!=0)' --a={} --b={} -o {} -t cfloat".format( np.pi, rangePixelSize, radarWavelength, self._insar.interferogram, rectRangeOffset, self._insar.differentialInterferogram) runCmd(cmd) os.chdir('../../') os.chdir('../') catalog.printToLog(logger, "runIonSubband") self._insar.procDoc.addAllFromCatalog(catalog)
def swathMosaic(frame, inputFiles, outputfile, rangeOffsets, azimuthOffsets, numberOfRangeLooks, numberOfAzimuthLooks, updateFrame=False, phaseCompensation=False, pcRangeLooks=1, pcAzimuthLooks=4, filt=False, resamplingMethod=0): ''' mosaic swaths frame: frame inputFiles: input file list output file: output mosaic file rangeOffsets: range offsets azimuthOffsets: azimuth offsets numberOfRangeLooks: number of range looks of the input files numberOfAzimuthLooks: number of azimuth looks of the input files phaseCompensation: whether do phase compensation for each swath pcRangeLooks: number of range looks to take when compute swath phase difference pcAzimuthLooks: number of azimuth looks to take when compute swath phase difference filt: whether do filtering when compute swath phase difference resamplingMethod: 0: amp resampling. 1: int resampling. ''' from contrib.alos2proc_f.alos2proc_f import rect_with_looks from contrib.alos2proc.alos2proc import mosaicsubswath from isceobj.Alos2Proc.Alos2ProcPublic import multilook from isceobj.Alos2Proc.Alos2ProcPublic import cal_coherence_1 from isceobj.Alos2Proc.Alos2ProcPublic import filterInterferogram numberOfSwaths = len(frame.swaths) swaths = frame.swaths rangeScale = [] azimuthScale = [] rectWidth = [] rectLength = [] for i in range(numberOfSwaths): rangeScale.append(swaths[0].rangePixelSize / swaths[i].rangePixelSize) azimuthScale.append(swaths[0].azimuthLineInterval / swaths[i].azimuthLineInterval) if i == 0: rectWidth.append( int(swaths[i].numberOfSamples / numberOfRangeLooks)) rectLength.append( int(swaths[i].numberOfLines / numberOfAzimuthLooks)) else: rectWidth.append( int(1.0 / rangeScale[i] * int(swaths[i].numberOfSamples / numberOfRangeLooks))) rectLength.append( int(1.0 / azimuthScale[i] * int(swaths[i].numberOfLines / numberOfAzimuthLooks))) #convert original offset to offset for images with looks #use list instead of np.array to make it consistent with the rest of the code rangeOffsets1 = [i / numberOfRangeLooks for i in rangeOffsets] azimuthOffsets1 = [i / numberOfAzimuthLooks for i in azimuthOffsets] #get offset relative to the first frame rangeOffsets2 = [0.0] azimuthOffsets2 = [0.0] for i in range(1, numberOfSwaths): rangeOffsets2.append(0.0) azimuthOffsets2.append(0.0) for j in range(1, i + 1): rangeOffsets2[i] += rangeOffsets1[j] azimuthOffsets2[i] += azimuthOffsets1[j] #resample each swath rinfs = [] for i, inf in enumerate(inputFiles): rinfs.append("{}_{}{}".format( os.path.splitext(os.path.basename(inf))[0], i, os.path.splitext(os.path.basename(inf))[1])) #do not resample first swath if i == 0: if os.path.isfile(rinfs[i]): os.remove(rinfs[i]) os.symlink(inf, rinfs[i]) else: infImg = isceobj.createImage() infImg.load(inf + '.xml') rangeOffsets2Frac = rangeOffsets2[i] - int(rangeOffsets2[i]) azimuthOffsets2Frac = azimuthOffsets2[i] - int(azimuthOffsets2[i]) if resamplingMethod == 0: rect_with_looks(inf, rinfs[i], infImg.width, infImg.length, rectWidth[i], rectLength[i], rangeScale[i], 0.0, 0.0, azimuthScale[i], rangeOffsets2Frac * rangeScale[i], azimuthOffsets2Frac * azimuthScale[i], 1, 1, 1, 1, 'COMPLEX', 'Bilinear') elif resamplingMethod == 1: #decompose amplitude and phase phaseFile = 'phase' amplitudeFile = 'amplitude' data = np.fromfile(inf, dtype=np.complex64).reshape( infImg.length, infImg.width) phase = np.exp(np.complex64(1j) * np.angle(data)) phase[np.nonzero(data == 0)] = 0 phase.astype(np.complex64).tofile(phaseFile) amplitude = np.absolute(data) amplitude.astype(np.float32).tofile(amplitudeFile) #resampling phaseRectFile = 'phaseRect' amplitudeRectFile = 'amplitudeRect' rect_with_looks(phaseFile, phaseRectFile, infImg.width, infImg.length, rectWidth[i], rectLength[i], rangeScale[i], 0.0, 0.0, azimuthScale[i], rangeOffsets2Frac * rangeScale[i], azimuthOffsets2Frac * azimuthScale[i], 1, 1, 1, 1, 'COMPLEX', 'Sinc') rect_with_looks(amplitudeFile, amplitudeRectFile, infImg.width, infImg.length, rectWidth[i], rectLength[i], rangeScale[i], 0.0, 0.0, azimuthScale[i], rangeOffsets2Frac * rangeScale[i], azimuthOffsets2Frac * azimuthScale[i], 1, 1, 1, 1, 'REAL', 'Bilinear') #recombine amplitude and phase phase = np.fromfile(phaseRectFile, dtype=np.complex64).reshape( rectLength[i], rectWidth[i]) amplitude = np.fromfile(amplitudeRectFile, dtype=np.float32).reshape( rectLength[i], rectWidth[i]) (phase * amplitude).astype(np.complex64).tofile(rinfs[i]) #tidy up os.remove(phaseFile) os.remove(amplitudeFile) os.remove(phaseRectFile) os.remove(amplitudeRectFile) #determine output width and length #actually no need to calculate in range direction xs = [] xe = [] ys = [] ye = [] for i in range(numberOfSwaths): if i == 0: xs.append(0) xe.append(rectWidth[i] - 1) ys.append(0) ye.append(rectLength[i] - 1) else: xs.append(0 - int(rangeOffsets2[i])) xe.append(rectWidth[i] - 1 - int(rangeOffsets2[i])) ys.append(0 - int(azimuthOffsets2[i])) ye.append(rectLength[i] - 1 - int(azimuthOffsets2[i])) (xmin, xminIndex) = min((v, i) for i, v in enumerate(xs)) (xmax, xmaxIndex) = max((v, i) for i, v in enumerate(xe)) (ymin, yminIndex) = min((v, i) for i, v in enumerate(ys)) (ymax, ymaxIndex) = max((v, i) for i, v in enumerate(ye)) outWidth = xmax - xmin + 1 outLength = ymax - ymin + 1 #prepare offset for mosaicing rangeOffsets3 = [] azimuthOffsets3 = [] for i in range(numberOfSwaths): azimuthOffsets3.append( int(azimuthOffsets2[i]) - int(azimuthOffsets2[yminIndex])) if i != 0: rangeOffsets3.append( int(rangeOffsets2[i]) - int(rangeOffsets2[i - 1])) else: rangeOffsets3.append(0) delta = int(30 / numberOfRangeLooks) #compute compensation phase for each swath diffMean2 = [0.0 for i in range(numberOfSwaths)] if phaseCompensation: #compute swath phase offset diffMean = [0.0] for i in range(1, numberOfSwaths): #all indexes start with zero, all the computed start/end sample/line indexes are included. #no need to add edge here, as we are going to find first/last nonzero sample/lines later #edge = delta edge = 0 #image i-1 startSample1 = edge + 0 - int(rangeOffsets2[i]) + int( rangeOffsets2[i - 1]) endSample1 = -edge + rectWidth[i - 1] - 1 startLine1 = edge + max( 0 - int(azimuthOffsets2[i]) + int(azimuthOffsets2[i - 1]), 0) endLine1 = -edge + min( rectLength[i] - 1 - int(azimuthOffsets2[i]) + int(azimuthOffsets2[i - 1]), rectLength[i - 1] - 1) data1 = readImage(rinfs[i - 1], rectWidth[i - 1], rectLength[i - 1], startSample1, endSample1, startLine1, endLine1) #image i startSample2 = edge + 0 endSample2 = -edge + rectWidth[i - 1] - 1 - int( rangeOffsets2[i - 1]) + int(rangeOffsets2[i]) startLine2 = edge + max( 0 - int(azimuthOffsets2[i - 1]) + int(azimuthOffsets2[i]), 0) endLine2 = -edge + min( rectLength[i - 1] - 1 - int(azimuthOffsets2[i - 1]) + int(azimuthOffsets2[i]), rectLength[i] - 1) data2 = readImage(rinfs[i], rectWidth[i], rectLength[i], startSample2, endSample2, startLine2, endLine2) #remove edge due to incomplete covolution in resampling edge = 9 (startLine0, endLine0, startSample0, endSample0) = findNonzero( np.logical_and((data1 != 0), (data2 != 0))) data1 = data1[startLine0 + edge:endLine0 + 1 - edge, startSample0 + edge:endSample0 + 1 - edge] data2 = data2[startLine0 + edge:endLine0 + 1 - edge, startSample0 + edge:endSample0 + 1 - edge] #take looks data1 = multilook(data1, pcAzimuthLooks, pcRangeLooks) data2 = multilook(data2, pcAzimuthLooks, pcRangeLooks) #filter if filt: data1 /= (np.absolute(data1) + (data1 == 0)) data2 /= (np.absolute(data2) + (data2 == 0)) data1 = filterInterferogram(data1, 3.0, 64, 1) data2 = filterInterferogram(data2, 3.0, 64, 1) #get difference corth = 0.87 if filt: corth = 0.90 diffMean0 = 0.0 for k in range(5): dataDiff = data1 * np.conj(data2) cor = cal_coherence_1(dataDiff, win=3) index = np.nonzero(np.logical_and(cor > corth, dataDiff != 0)) if index[0].size < 100: diffMean0 = 0.0 print( '\n\nWARNING: too few high coherence pixels for swath phase difference estimation between swath {} and {}' .format(i - 1, i)) print(' : first swath swath number: 0\n\n') break angle = np.mean(np.angle(dataDiff[index]), dtype=np.float64) diffMean0 += angle data2 *= np.exp(np.complex64(1j) * angle) print('phase offset: %15.12f rad after loop: %3d' % (diffMean0, k)) DEBUG = False if DEBUG and (k == 0): from isceobj.Alos2Proc.Alos2ProcPublic import create_xml (lengthxx, widthxx) = dataDiff.shape filtnamePrefix = 'subswath{}_subswath{}_loop{}'.format( frame.swaths[i - 1].swathNumber, frame.swaths[i].swathNumber, k) cor.astype(np.float32).tofile(filtnamePrefix + '.cor') create_xml(filtnamePrefix + '.cor', widthxx, lengthxx, 'float') dataDiff.astype(np.complex64).tofile(filtnamePrefix + '.int') create_xml(filtnamePrefix + '.int', widthxx, lengthxx, 'int') diffMean.append(diffMean0) print('phase offset: subswath{} - subswath{}: {}'.format( frame.swaths[i - 1].swathNumber, frame.swaths[i].swathNumber, diffMean0)) for i in range(1, numberOfSwaths): for j in range(1, i + 1): diffMean2[i] += diffMean[j] #mosaic swaths diffflag = 1 oflag = [0 for i in range(numberOfSwaths)] mosaicsubswath(outputfile, outWidth, outLength, delta, diffflag, numberOfSwaths, rinfs, rectWidth, rangeOffsets3, azimuthOffsets3, diffMean2, oflag) #remove tmp files for x in rinfs: os.remove(x) #update frame parameters if updateFrame: #mosaic size frame.numberOfSamples = outWidth frame.numberOfLines = outLength #NOTE THAT WE ARE STILL USING SINGLE LOOK PARAMETERS HERE #range parameters frame.startingRange = frame.swaths[0].startingRange frame.rangeSamplingRate = frame.swaths[0].rangeSamplingRate frame.rangePixelSize = frame.swaths[0].rangePixelSize #azimuth parameters azimuthTimeOffset = -max([ int(x) for x in azimuthOffsets2 ]) * numberOfAzimuthLooks * frame.swaths[0].azimuthLineInterval frame.sensingStart = frame.swaths[0].sensingStart + datetime.timedelta( seconds=azimuthTimeOffset) frame.prf = frame.swaths[0].prf frame.azimuthPixelSize = frame.swaths[0].azimuthPixelSize frame.azimuthLineInterval = frame.swaths[0].azimuthLineInterval
def runSwathMosaic(self): '''mosaic subswaths ''' catalog = isceobj.Catalog.createCatalog(self._insar.procDoc.name) self.updateParamemetersFromUser() masterTrack = self._insar.loadTrack(master=True) slaveTrack = self._insar.loadTrack(master=False) for i, frameNumber in enumerate(self._insar.masterFrames): frameDir = 'f{}_{}'.format(i + 1, frameNumber) os.chdir(frameDir) mosaicDir = 'mosaic' os.makedirs(mosaicDir, exist_ok=True) os.chdir(mosaicDir) if not ( ((self._insar.modeCombination == 21) or \ (self._insar.modeCombination == 22) or \ (self._insar.modeCombination == 31) or \ (self._insar.modeCombination == 32)) and (self._insar.endingSwath-self._insar.startingSwath+1 > 1) ): import shutil swathDir = 's{}'.format( masterTrack.frames[i].swaths[0].swathNumber) if not os.path.isfile(self._insar.interferogram): os.symlink( os.path.join('../', swathDir, self._insar.interferogram), self._insar.interferogram) shutil.copy2( os.path.join('../', swathDir, self._insar.interferogram + '.vrt'), self._insar.interferogram + '.vrt') shutil.copy2( os.path.join('../', swathDir, self._insar.interferogram + '.xml'), self._insar.interferogram + '.xml') if not os.path.isfile(self._insar.amplitude): os.symlink( os.path.join('../', swathDir, self._insar.amplitude), self._insar.amplitude) shutil.copy2( os.path.join('../', swathDir, self._insar.amplitude + '.vrt'), self._insar.amplitude + '.vrt') shutil.copy2( os.path.join('../', swathDir, self._insar.amplitude + '.xml'), self._insar.amplitude + '.xml') # os.rename(os.path.join('../', swathDir, self._insar.interferogram), self._insar.interferogram) # os.rename(os.path.join('../', swathDir, self._insar.interferogram+'.vrt'), self._insar.interferogram+'.vrt') # os.rename(os.path.join('../', swathDir, self._insar.interferogram+'.xml'), self._insar.interferogram+'.xml') # os.rename(os.path.join('../', swathDir, self._insar.amplitude), self._insar.amplitude) # os.rename(os.path.join('../', swathDir, self._insar.amplitude+'.vrt'), self._insar.amplitude+'.vrt') # os.rename(os.path.join('../', swathDir, self._insar.amplitude+'.xml'), self._insar.amplitude+'.xml') #update frame parameters ######################################################### frame = masterTrack.frames[i] infImg = isceobj.createImage() infImg.load(self._insar.interferogram + '.xml') #mosaic size frame.numberOfSamples = infImg.width frame.numberOfLines = infImg.length #NOTE THAT WE ARE STILL USING SINGLE LOOK PARAMETERS HERE #range parameters frame.startingRange = frame.swaths[0].startingRange frame.rangeSamplingRate = frame.swaths[0].rangeSamplingRate frame.rangePixelSize = frame.swaths[0].rangePixelSize #azimuth parameters frame.sensingStart = frame.swaths[0].sensingStart frame.prf = frame.swaths[0].prf frame.azimuthPixelSize = frame.swaths[0].azimuthPixelSize frame.azimuthLineInterval = frame.swaths[0].azimuthLineInterval #update frame parameters, slave ######################################################### frame = slaveTrack.frames[i] #mosaic size frame.numberOfSamples = int(frame.swaths[0].numberOfSamples / self._insar.numberRangeLooks1) frame.numberOfLines = int(frame.swaths[0].numberOfLines / self._insar.numberAzimuthLooks1) #NOTE THAT WE ARE STILL USING SINGLE LOOK PARAMETERS HERE #range parameters frame.startingRange = frame.swaths[0].startingRange frame.rangeSamplingRate = frame.swaths[0].rangeSamplingRate frame.rangePixelSize = frame.swaths[0].rangePixelSize #azimuth parameters frame.sensingStart = frame.swaths[0].sensingStart frame.prf = frame.swaths[0].prf frame.azimuthPixelSize = frame.swaths[0].azimuthPixelSize frame.azimuthLineInterval = frame.swaths[0].azimuthLineInterval os.chdir('../') #save parameter file self._insar.saveProduct(masterTrack.frames[i], self._insar.masterFrameParameter) self._insar.saveProduct(slaveTrack.frames[i], self._insar.slaveFrameParameter) os.chdir('../') continue #choose offsets numberOfFrames = len(masterTrack.frames) numberOfSwaths = len(masterTrack.frames[i].swaths) if self.swathOffsetMatching: #no need to do this as the API support 2-d list #rangeOffsets = (np.array(self._insar.swathRangeOffsetMatchingMaster)).reshape(numberOfFrames, numberOfSwaths) #azimuthOffsets = (np.array(self._insar.swathAzimuthOffsetMatchingMaster)).reshape(numberOfFrames, numberOfSwaths) rangeOffsets = self._insar.swathRangeOffsetMatchingMaster azimuthOffsets = self._insar.swathAzimuthOffsetMatchingMaster else: #rangeOffsets = (np.array(self._insar.swathRangeOffsetGeometricalMaster)).reshape(numberOfFrames, numberOfSwaths) #azimuthOffsets = (np.array(self._insar.swathAzimuthOffsetGeometricalMaster)).reshape(numberOfFrames, numberOfSwaths) rangeOffsets = self._insar.swathRangeOffsetGeometricalMaster azimuthOffsets = self._insar.swathAzimuthOffsetGeometricalMaster rangeOffsets = rangeOffsets[i] azimuthOffsets = azimuthOffsets[i] #list of input files inputInterferograms = [] inputAmplitudes = [] for j, swathNumber in enumerate( range(self._insar.startingSwath, self._insar.endingSwath + 1)): swathDir = 's{}'.format(swathNumber) inputInterferograms.append( os.path.join('../', swathDir, self._insar.interferogram)) inputAmplitudes.append( os.path.join('../', swathDir, self._insar.amplitude)) #note that frame parameters are updated after mosaicking #mosaic amplitudes swathMosaic(masterTrack.frames[i], inputAmplitudes, self._insar.amplitude, rangeOffsets, azimuthOffsets, self._insar.numberRangeLooks1, self._insar.numberAzimuthLooks1, resamplingMethod=0) #mosaic interferograms swathMosaic(masterTrack.frames[i], inputInterferograms, self._insar.interferogram, rangeOffsets, azimuthOffsets, self._insar.numberRangeLooks1, self._insar.numberAzimuthLooks1, updateFrame=True, resamplingMethod=1) create_xml(self._insar.amplitude, masterTrack.frames[i].numberOfSamples, masterTrack.frames[i].numberOfLines, 'amp') create_xml(self._insar.interferogram, masterTrack.frames[i].numberOfSamples, masterTrack.frames[i].numberOfLines, 'int') #update slave frame parameters here #no matching for slave, always use geometry rangeOffsets = self._insar.swathRangeOffsetGeometricalSlave azimuthOffsets = self._insar.swathAzimuthOffsetGeometricalSlave rangeOffsets = rangeOffsets[i] azimuthOffsets = azimuthOffsets[i] swathMosaicParameters(slaveTrack.frames[i], rangeOffsets, azimuthOffsets, self._insar.numberRangeLooks1, self._insar.numberAzimuthLooks1) os.chdir('../') #save parameter file self._insar.saveProduct(masterTrack.frames[i], self._insar.masterFrameParameter) self._insar.saveProduct(slaveTrack.frames[i], self._insar.slaveFrameParameter) os.chdir('../') catalog.printToLog(logger, "runSwathMosaic") self._insar.procDoc.addAllFromCatalog(catalog)
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 runIonUwrap(self): '''unwrap subband interferograms ''' catalog = isceobj.Catalog.createCatalog(self._insar.procDoc.name) self.updateParamemetersFromUser() if not self.doIon: catalog.printToLog(logger, "runIonUwrap") self._insar.procDoc.addAllFromCatalog(catalog) return referenceTrack = self._insar.loadTrack(reference=True) secondaryTrack = self._insar.loadTrack(reference=False) wbdFile = os.path.abspath(self._insar.wbd) from isceobj.Alos2Proc.runIonSubband import defineIonDir ionDir = defineIonDir() subbandPrefix = ['lower', 'upper'] ionCalDir = os.path.join(ionDir['ion'], ionDir['ionCal']) os.makedirs(ionCalDir, exist_ok=True) os.chdir(ionCalDir) ############################################################ # STEP 1. take looks ############################################################ from isceobj.Alos2Proc.Alos2ProcPublic import create_xml from contrib.alos2proc.alos2proc import look from isceobj.Alos2Proc.Alos2ProcPublic import waterBodyRadar ml2 = '_{}rlks_{}alks'.format(self._insar.numberRangeLooks1*self._insar.numberRangeLooksIon, self._insar.numberAzimuthLooks1*self._insar.numberAzimuthLooksIon) for k in range(2): fullbandDir = os.path.join('../../', ionDir['insar']) subbandDir = os.path.join('../', ionDir['subband'][k], ionDir['insar']) prefix = subbandPrefix[k] amp = isceobj.createImage() amp.load(os.path.join(subbandDir, self._insar.amplitude)+'.xml') width = amp.width length = amp.length width2 = int(width / self._insar.numberRangeLooksIon) length2 = int(length / self._insar.numberAzimuthLooksIon) #take looks look(os.path.join(subbandDir, self._insar.differentialInterferogram), prefix+ml2+'.int', width, self._insar.numberRangeLooksIon, self._insar.numberAzimuthLooksIon, 4, 0, 1) create_xml(prefix+ml2+'.int', width2, length2, 'int') look(os.path.join(subbandDir, self._insar.amplitude), prefix+ml2+'.amp', width, self._insar.numberRangeLooksIon, self._insar.numberAzimuthLooksIon, 4, 1, 1) create_xml(prefix+ml2+'.amp', width2, length2, 'amp') # #water body # if k == 0: # wbdOutFile = os.path.join(fullbandDir, self._insar.wbdOut) # if os.path.isfile(wbdOutFile): # look(wbdOutFile, 'wbd'+ml2+'.wbd', width, self._insar.numberRangeLooksIon, self._insar.numberAzimuthLooksIon, 0, 0, 1) # create_xml('wbd'+ml2+'.wbd', width2, length2, 'byte') #water body if k == 0: look(os.path.join(fullbandDir, self._insar.latitude), 'lat'+ml2+'.lat', width, self._insar.numberRangeLooksIon, self._insar.numberAzimuthLooksIon, 3, 0, 1) look(os.path.join(fullbandDir, self._insar.longitude), 'lon'+ml2+'.lon', width, self._insar.numberRangeLooksIon, self._insar.numberAzimuthLooksIon, 3, 0, 1) create_xml('lat'+ml2+'.lat', width2, length2, 'double') create_xml('lon'+ml2+'.lon', width2, length2, 'double') waterBodyRadar('lat'+ml2+'.lat', 'lon'+ml2+'.lon', wbdFile, 'wbd'+ml2+'.wbd') ############################################################ # STEP 2. compute coherence ############################################################ from isceobj.Alos2Proc.Alos2ProcPublic import cal_coherence lowerbandInterferogramFile = subbandPrefix[0]+ml2+'.int' upperbandInterferogramFile = subbandPrefix[1]+ml2+'.int' lowerbandAmplitudeFile = subbandPrefix[0]+ml2+'.amp' upperbandAmplitudeFile = subbandPrefix[1]+ml2+'.amp' lowerbandCoherenceFile = subbandPrefix[0]+ml2+'.cor' upperbandCoherenceFile = subbandPrefix[1]+ml2+'.cor' coherenceFile = 'diff'+ml2+'.cor' lowerint = np.fromfile(lowerbandInterferogramFile, dtype=np.complex64).reshape(length2, width2) upperint = np.fromfile(upperbandInterferogramFile, dtype=np.complex64).reshape(length2, width2) loweramp = np.fromfile(lowerbandAmplitudeFile, dtype=np.float32).reshape(length2, width2*2) upperamp = np.fromfile(upperbandAmplitudeFile, dtype=np.float32).reshape(length2, width2*2) #compute coherence only using interferogram #here I use differential interferogram of lower and upper band interferograms #so that coherence is not affected by fringes cord = cal_coherence(lowerint*np.conjugate(upperint), win=3, edge=4) cor = np.zeros((length2*2, width2), dtype=np.float32) cor[0:length2*2:2, :] = np.sqrt( (np.absolute(lowerint)+np.absolute(upperint))/2.0 ) cor[1:length2*2:2, :] = cord cor.astype(np.float32).tofile(coherenceFile) create_xml(coherenceFile, width2, length2, 'cor') #create lower and upper band coherence files #lower amp1 = loweramp[:, 0:width2*2:2] amp2 = loweramp[:, 1:width2*2:2] cor[1:length2*2:2, :] = np.absolute(lowerint)/(amp1+(amp1==0))/(amp2+(amp2==0))*(amp1!=0)*(amp2!=0) cor.astype(np.float32).tofile(lowerbandCoherenceFile) create_xml(lowerbandCoherenceFile, width2, length2, 'cor') #upper amp1 = upperamp[:, 0:width2*2:2] amp2 = upperamp[:, 1:width2*2:2] cor[1:length2*2:2, :] = np.absolute(upperint)/(amp1+(amp1==0))/(amp2+(amp2==0))*(amp1!=0)*(amp2!=0) cor.astype(np.float32).tofile(upperbandCoherenceFile) create_xml(upperbandCoherenceFile, width2, length2, 'cor') ############################################################ # STEP 3. filtering subband interferograms ############################################################ from contrib.alos2filter.alos2filter import psfilt1 from isceobj.Alos2Proc.Alos2ProcPublic import runCmd from isceobj.Alos2Proc.Alos2ProcPublic import create_xml from mroipac.icu.Icu import Icu if self.filterSubbandInt: for k in range(2): toBeFiltered = 'tmp.int' if self.removeMagnitudeBeforeFilteringSubbandInt: cmd = "imageMath.py -e='a/(abs(a)+(a==0))' --a={} -o {} -t cfloat -s BSQ".format(subbandPrefix[k]+ml2+'.int', toBeFiltered) else: #scale the inteferogram, otherwise its magnitude is too large for filtering cmd = "imageMath.py -e='a/100000.0' --a={} -o {} -t cfloat -s BSQ".format(subbandPrefix[k]+ml2+'.int', toBeFiltered) runCmd(cmd) intImage = isceobj.createIntImage() intImage.load(toBeFiltered + '.xml') width = intImage.width length = intImage.length windowSize = self.filterWinsizeSubbandInt stepSize = self.filterStepsizeSubbandInt psfilt1(toBeFiltered, 'filt_'+subbandPrefix[k]+ml2+'.int', width, self.filterStrengthSubbandInt, windowSize, stepSize) create_xml('filt_'+subbandPrefix[k]+ml2+'.int', width, length, 'int') os.remove(toBeFiltered) os.remove(toBeFiltered + '.vrt') os.remove(toBeFiltered + '.xml') #create phase sigma for phase unwrapping #recreate filtered image filtImage = isceobj.createIntImage() filtImage.load('filt_'+subbandPrefix[k]+ml2+'.int' + '.xml') filtImage.setAccessMode('read') filtImage.createImage() #amplitude image ampImage = isceobj.createAmpImage() ampImage.load(subbandPrefix[k]+ml2+'.amp' + '.xml') ampImage.setAccessMode('read') ampImage.createImage() #phase sigma correlation image phsigImage = isceobj.createImage() phsigImage.setFilename(subbandPrefix[k]+ml2+'.phsig') phsigImage.setWidth(width) phsigImage.dataType='FLOAT' phsigImage.bands = 1 phsigImage.setImageType('cor') phsigImage.setAccessMode('write') phsigImage.createImage() icu = Icu(name='insarapp_filter_icu') icu.configure() icu.unwrappingFlag = False icu.icu(intImage = filtImage, ampImage=ampImage, phsigImage=phsigImage) phsigImage.renderHdr() filtImage.finalizeImage() ampImage.finalizeImage() phsigImage.finalizeImage() ############################################################ # STEP 4. phase unwrapping ############################################################ from isceobj.Alos2Proc.Alos2ProcPublic import snaphuUnwrap for k in range(2): tmid = referenceTrack.sensingStart + datetime.timedelta(seconds=(self._insar.numberAzimuthLooks1-1.0)/2.0*referenceTrack.azimuthLineInterval+ referenceTrack.numberOfLines/2.0*self._insar.numberAzimuthLooks1*referenceTrack.azimuthLineInterval) if self.filterSubbandInt: toBeUnwrapped = 'filt_'+subbandPrefix[k]+ml2+'.int' coherenceFile = subbandPrefix[k]+ml2+'.phsig' else: toBeUnwrapped = subbandPrefix[k]+ml2+'.int' coherenceFile = 'diff'+ml2+'.cor' snaphuUnwrap(referenceTrack, tmid, toBeUnwrapped, coherenceFile, subbandPrefix[k]+ml2+'.unw', self._insar.numberRangeLooks1*self._insar.numberRangeLooksIon, self._insar.numberAzimuthLooks1*self._insar.numberAzimuthLooksIon, costMode = 'SMOOTH',initMethod = 'MCF', defomax = 2, initOnly = True) os.chdir('../../') catalog.printToLog(logger, "runIonUwrap") self._insar.procDoc.addAllFromCatalog(catalog)
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)