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 frameMosaic(track, inputFiles, outputfile, rangeOffsets, azimuthOffsets, numberOfRangeLooks, numberOfAzimuthLooks, updateTrack=False, phaseCompensation=False, resamplingMethod=0): ''' mosaic frames track: track 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 updateTrack: whether update track parameters phaseCompensation: whether do phase compensation for each frame resamplingMethod: 0: amp resampling. 1: int resampling. 2: slc resampling ''' import numpy as np from contrib.alos2proc_f.alos2proc_f import rect_with_looks from contrib.alos2proc.alos2proc import resamp from isceobj.Alos2Proc.runSwathMosaic import readImage from isceobj.Alos2Proc.runSwathMosaic import findNonzero from isceobj.Alos2Proc.Alos2ProcPublic import create_xml from isceobj.Alos2Proc.Alos2ProcPublic import find_vrt_file from isceobj.Alos2Proc.Alos2ProcPublic import find_vrt_keyword numberOfFrames = len(track.frames) frames = track.frames rectWidth = [] rectLength = [] for i in range(numberOfFrames): infImg = isceobj.createImage() infImg.load(inputFiles[i] + '.xml') rectWidth.append(infImg.width) rectLength.append(infImg.length) #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, numberOfFrames): 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 frame 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 frame if i == 0: rinfs[i] = inf 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, infImg.width, infImg.length, 1.0, 0.0, 0.0, 1.0, rangeOffsets2Frac, azimuthOffsets2Frac, 1, 1, 1, 1, 'COMPLEX', 'Bilinear') if infImg.getImageType() == 'amp': create_xml(rinfs[i], infImg.width, infImg.length, 'amp') else: create_xml(rinfs[i], infImg.width, infImg.length, 'int') 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, infImg.width, infImg.length, 1.0, 0.0, 0.0, 1.0, rangeOffsets2Frac, azimuthOffsets2Frac, 1, 1, 1, 1, 'COMPLEX', 'Sinc') rect_with_looks(amplitudeFile, amplitudeRectFile, infImg.width, infImg.length, infImg.width, infImg.length, 1.0, 0.0, 0.0, 1.0, rangeOffsets2Frac, azimuthOffsets2Frac, 1, 1, 1, 1, 'REAL', 'Bilinear') #recombine amplitude and phase phase = np.fromfile(phaseRectFile, dtype=np.complex64).reshape( infImg.length, infImg.width) amplitude = np.fromfile(amplitudeRectFile, dtype=np.float32).reshape( infImg.length, infImg.width) (phase * amplitude).astype(np.complex64).tofile(rinfs[i]) #tidy up os.remove(phaseFile) os.remove(amplitudeFile) os.remove(phaseRectFile) os.remove(amplitudeRectFile) if infImg.getImageType() == 'amp': create_xml(rinfs[i], infImg.width, infImg.length, 'amp') else: create_xml(rinfs[i], infImg.width, infImg.length, 'int') else: resamp(inf, rinfs[i], 'fake', 'fake', infImg.width, infImg.length, frames[i].swaths[0].prf, frames[i].swaths[0].dopplerVsPixel, [ rangeOffsets2Frac, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 ], [ azimuthOffsets2Frac, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 ]) create_xml(rinfs[i], infImg.width, infImg.length, 'slc') #determine output width and length #actually no need to calculate in azimuth direction xs = [] xe = [] ys = [] ye = [] for i in range(numberOfFrames): 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 for mosaicing using numpy xs = [x - xmin for x in xs] xe = [x - xmin for x in xe] ys = [y - ymin for y in ys] ye = [y - ymin for y in ye] #compute phase offset if phaseCompensation: phaseOffsetPolynomials = [np.array([0.0])] for i in range(1, numberOfFrames): upperframe = np.zeros((ye[i - 1] - ys[i] + 1, outWidth), dtype=np.complex128) lowerframe = np.zeros((ye[i - 1] - ys[i] + 1, outWidth), dtype=np.complex128) #upper frame if os.path.isfile(rinfs[i - 1]): upperframe[:, xs[i - 1]:xe[i - 1] + 1] = readImage( rinfs[i - 1], rectWidth[i - 1], rectLength[i - 1], 0, rectWidth[i - 1] - 1, ys[i] - ys[i - 1], ye[i - 1] - ys[i - 1]) else: upperframe[:, xs[i - 1]:xe[i - 1] + 1] = readImageFromVrt( rinfs[i - 1], 0, rectWidth[i - 1] - 1, ys[i] - ys[i - 1], ye[i - 1] - ys[i - 1]) #lower frame if os.path.isfile(rinfs[i]): lowerframe[:, xs[i]:xe[i] + 1] = readImage( rinfs[i], rectWidth[i], rectLength[i], 0, rectWidth[i] - 1, 0, ye[i - 1] - ys[i]) else: lowerframe[:, xs[i]:xe[i] + 1] = readImageFromVrt( rinfs[i], 0, rectWidth[i] - 1, 0, ye[i - 1] - ys[i]) #get a polynomial diff = np.sum(upperframe * np.conj(lowerframe), axis=0) (firstLine, lastLine, firstSample, lastSample) = findNonzero(np.reshape(diff, (1, outWidth))) #here i use mean value(deg=0) in case difference is around -pi or pi. deg = 0 p = np.polyfit(np.arange(firstSample, lastSample + 1), np.angle(diff[firstSample:lastSample + 1]), deg) phaseOffsetPolynomials.append(p) #check fit result DEBUG = False if DEBUG: #create a dir and work in this dir diffDir = 'frame_mosaic' os.makedirs(diffDir, exist_ok=True) os.chdir(diffDir) #dump phase difference diffFilename = 'phase_difference_frame{}-frame{}.int'.format( i, i + 1) (upperframe * np.conj(lowerframe)).astype( np.complex64).tofile(diffFilename) create_xml(diffFilename, outWidth, ye[i - 1] - ys[i] + 1, 'int') #plot phase difference vs range import matplotlib.pyplot as plt x = np.arange(firstSample, lastSample + 1) y = np.angle(diff[firstSample:lastSample + 1]) plt.plot(x, y, label='original phase difference') plt.plot(x, np.polyval(p, x), label='fitted phase difference') plt.legend() plt.minorticks_on() plt.tick_params('both', length=10, which='major') plt.tick_params('both', length=5, which='minor') plt.xlabel('Range Sample Number [Samples]') plt.ylabel('Phase Difference [Rad]') plt.savefig('phase_difference_frame{}-frame{}.pdf'.format( i, i + 1)) os.chdir('../') #mosaic file outFp = open(outputfile, 'wb') for i in range(numberOfFrames): print('adding frame: {}'.format(i + 1)) #phase offset in the polynomials if phaseCompensation: cJ = np.complex64(1j) phaseOffset = np.ones(outWidth, dtype=np.complex64) for j in range(i + 1): phaseOffset *= np.exp( cJ * np.polyval(phaseOffsetPolynomials[j], np.arange(outWidth))) #get start line number (starts with zero) if i == 0: ys1 = 0 else: ys1 = int((ye[i - 1] + ys[i]) / 2.0) + 1 - ys[i] #get end line number (start with zero) if i == numberOfFrames - 1: ye1 = rectLength[i] - 1 else: ye1 = int((ye[i] + ys[i + 1]) / 2.0) - ys[i] #get image format inputimage = find_vrt_file(rinfs[i] + '.vrt', 'SourceFilename', relative_path=True) byteorder = find_vrt_keyword(rinfs[i] + '.vrt', 'ByteOrder') if byteorder == 'LSB': swapByte = False else: swapByte = True imageoffset = int(find_vrt_keyword(rinfs[i] + '.vrt', 'ImageOffset')) lineoffset = int(find_vrt_keyword(rinfs[i] + '.vrt', 'LineOffset')) #read image with open(inputimage, 'rb') as fp: for j in range(ys1, ye1 + 1): fp.seek(imageoffset + j * lineoffset, 0) data = np.zeros(outWidth, dtype=np.complex64) if swapByte: tmp = np.fromfile(fp, dtype='>f', count=2 * rectWidth[i]) cJ = np.complex64(1j) data[xs[i]:xe[i] + 1] = tmp[0::2] + cJ * tmp[1::2] else: data[xs[i]:xe[i] + 1] = np.fromfile(fp, dtype=np.complex64, count=rectWidth[i]) if phaseCompensation: data *= phaseOffset data.astype(np.complex64).tofile(outFp) outFp.close() #delete files. DO NOT DELETE THE FIRST ONE!!! for i in range(numberOfFrames): if i == 0: continue os.remove(rinfs[i]) os.remove(rinfs[i] + '.vrt') os.remove(rinfs[i] + '.xml') #update frame parameters if updateTrack: #mosaic size track.numberOfSamples = outWidth track.numberOfLines = outLength #NOTE THAT WE ARE STILL USING SINGLE LOOK PARAMETERS HERE #range parameters track.startingRange = frames[0].startingRange + ( int(rangeOffsets2[0]) - int(rangeOffsets2[xminIndex]) ) * numberOfRangeLooks * frames[0].rangePixelSize track.rangeSamplingRate = frames[0].rangeSamplingRate track.rangePixelSize = frames[0].rangePixelSize #azimuth parameters track.sensingStart = frames[0].sensingStart track.prf = frames[0].prf track.azimuthPixelSize = frames[0].azimuthPixelSize track.azimuthLineInterval = frames[0].azimuthLineInterval
def runPrepareSlc(self): '''Extract images. ''' catalog = isceobj.Catalog.createCatalog(self._insar.procDoc.name) self.updateParamemetersFromUser() referenceTrack = self._insar.loadTrack(reference=True) secondaryTrack = self._insar.loadTrack(reference=False) #################################################### #1. crop slc #################################################### #for ScanSAR-stripmap interferometry, we always crop slcs #for other cases, up to users if ((self._insar.modeCombination == 31) or (self._insar.modeCombination == 32)) or (self.cropSlc): for i, frameNumber in enumerate(self._insar.referenceFrames): frameDir = 'f{}_{}'.format(i + 1, frameNumber) os.chdir(frameDir) for j, swathNumber in enumerate( range(self._insar.startingSwath, self._insar.endingSwath + 1)): swathDir = 's{}'.format(swathNumber) os.chdir(swathDir) print('cropping frame {}, swath {}'.format( frameNumber, swathNumber)) referenceSwath = referenceTrack.frames[i].swaths[j] secondarySwath = secondaryTrack.frames[i].swaths[j] #crop reference cropSlc(referenceTrack.orbit, referenceSwath, self._insar.referenceSlc, secondaryTrack.orbit, secondarySwath, edge=0, useVirtualFile=self.useVirtualFile) #crop secondary, since secondary may go through resampling, we set edge=9 #cropSlc(secondaryTrack.orbit, secondarySwath, self._insar.secondarySlc, referenceTrack.orbit, referenceSwath, edge=9, useVirtualFile=self.useVirtualFile) cropSlc(secondaryTrack.orbit, secondarySwath, self._insar.secondarySlc, referenceTrack.orbit, referenceSwath, edge=0, useVirtualFile=self.useVirtualFile) os.chdir('../') os.chdir('../') #################################################### #2. range-filter slc #################################################### #compute filtering parameters, radarwavelength and range bandwidth should be the same across all swaths and frames centerfreq1 = SPEED_OF_LIGHT / referenceTrack.radarWavelength bandwidth1 = referenceTrack.frames[0].swaths[0].rangeBandwidth centerfreq2 = SPEED_OF_LIGHT / secondaryTrack.radarWavelength bandwidth2 = secondaryTrack.frames[0].swaths[0].rangeBandwidth overlapfreq = overlapFrequency(centerfreq1, bandwidth1, centerfreq2, bandwidth2) if overlapfreq == None: raise Exception('there is no overlap bandwidth in range') overlapbandwidth = overlapfreq[1] - overlapfreq[0] if overlapbandwidth < 3e6: print('overlap bandwidth: {}, percentage: {}%'.format( overlapbandwidth, 100.0 * overlapbandwidth / bandwidth1)) raise Exception('there is not enough overlap bandwidth in range') centerfreq = (overlapfreq[1] + overlapfreq[0]) / 2.0 for i, frameNumber in enumerate(self._insar.referenceFrames): frameDir = 'f{}_{}'.format(i + 1, frameNumber) os.chdir(frameDir) for j, swathNumber in enumerate( range(self._insar.startingSwath, self._insar.endingSwath + 1)): swathDir = 's{}'.format(swathNumber) os.chdir(swathDir) print('range filtering frame {}, swath {}'.format( frameNumber, swathNumber)) referenceSwath = referenceTrack.frames[i].swaths[j] secondarySwath = secondaryTrack.frames[i].swaths[j] # #compute filtering parameters # centerfreq1 = SPEED_OF_LIGHT / referenceTrack.radarWavelength # bandwidth1 = referenceSwath.rangeBandwidth # centerfreq2 = SPEED_OF_LIGHT / secondaryTrack.radarWavelength # bandwidth2 = secondarySwath.rangeBandwidth # overlapfreq = overlapFrequency(centerfreq1, bandwidth1, centerfreq2, bandwidth2) # if overlapfreq == None: # raise Exception('there is no overlap bandwidth in range') # overlapbandwidth = overlapfreq[1] - overlapfreq[0] # if overlapbandwidth < 3e6: # print('overlap bandwidth: {}, percentage: {}%'.format(overlapbandwidth, 100.0*overlapbandwidth/bandwidth1)) # raise Exception('there is not enough overlap bandwidth in range') # centerfreq = (overlapfreq[1] + overlapfreq[0]) / 2.0 #filter reference if abs(centerfreq1 - centerfreq) < 1.0 and (bandwidth1 - 1.0) < overlapbandwidth: print('no need to range filter {}'.format( self._insar.referenceSlc)) else: print('range filter {}'.format(self._insar.referenceSlc)) tmpSlc = 'tmp.slc' rg_filter( self._insar.referenceSlc, 1, [tmpSlc], [overlapbandwidth / referenceSwath.rangeSamplingRate], [(centerfreq - centerfreq1) / referenceSwath.rangeSamplingRate], 257, 2048, 0.1, 0, 0.0) if os.path.isfile(self._insar.referenceSlc): os.remove(self._insar.referenceSlc) os.remove(self._insar.referenceSlc + '.vrt') os.remove(self._insar.referenceSlc + '.xml') img = isceobj.createSlcImage() img.load(tmpSlc + '.xml') #remove original os.remove(tmpSlc + '.vrt') os.remove(tmpSlc + '.xml') os.rename(tmpSlc, self._insar.referenceSlc) #creat new img.setFilename(self._insar.referenceSlc) img.extraFilename = self._insar.referenceSlc + '.vrt' img.setAccessMode('READ') img.renderHdr() referenceTrack.radarWavelength = SPEED_OF_LIGHT / centerfreq referenceSwath.rangeBandwidth = overlapbandwidth #filter secondary if abs(centerfreq2 - centerfreq) < 1.0 and (bandwidth2 - 1.0) < overlapbandwidth: print('no need to range filter {}'.format( self._insar.secondarySlc)) else: print('range filter {}'.format(self._insar.secondarySlc)) tmpSlc = 'tmp.slc' rg_filter( self._insar.secondarySlc, 1, [tmpSlc], [overlapbandwidth / secondarySwath.rangeSamplingRate], [(centerfreq - centerfreq2) / secondarySwath.rangeSamplingRate], 257, 2048, 0.1, 0, 0.0) if os.path.isfile(self._insar.secondarySlc): os.remove(self._insar.secondarySlc) os.remove(self._insar.secondarySlc + '.vrt') os.remove(self._insar.secondarySlc + '.xml') img = isceobj.createSlcImage() img.load(tmpSlc + '.xml') #remove original os.remove(tmpSlc + '.vrt') os.remove(tmpSlc + '.xml') os.rename(tmpSlc, self._insar.secondarySlc) #creat new img.setFilename(self._insar.secondarySlc) img.extraFilename = self._insar.secondarySlc + '.vrt' img.setAccessMode('READ') img.renderHdr() secondaryTrack.radarWavelength = SPEED_OF_LIGHT / centerfreq secondarySwath.rangeBandwidth = overlapbandwidth os.chdir('../') os.chdir('../') #################################################### #3. equalize sample size #################################################### for i, frameNumber in enumerate(self._insar.referenceFrames): frameDir = 'f{}_{}'.format(i + 1, frameNumber) os.chdir(frameDir) for j, swathNumber in enumerate( range(self._insar.startingSwath, self._insar.endingSwath + 1)): swathDir = 's{}'.format(swathNumber) os.chdir(swathDir) print('equalize sample size frame {}, swath {}'.format( frameNumber, swathNumber)) referenceSwath = referenceTrack.frames[i].swaths[j] secondarySwath = secondaryTrack.frames[i].swaths[j] if abs(referenceSwath.rangeSamplingRate - secondarySwath.rangeSamplingRate) < 1.0 and abs( referenceSwath.prf - secondarySwath.prf) < 1.0: print('no need to resample {}.'.format( self._insar.secondarySlc)) else: outWidth = round(secondarySwath.numberOfSamples / secondarySwath.rangeSamplingRate * referenceSwath.rangeSamplingRate) outLength = round(secondarySwath.numberOfLines / secondarySwath.prf * referenceSwath.prf) tmpSlc = 'tmp.slc' resamp(self._insar.secondarySlc, tmpSlc, 'fake', 'fake', outWidth, outLength, secondarySwath.prf, secondarySwath.dopplerVsPixel, rgcoef=[ 0.0, (1.0 / referenceSwath.rangeSamplingRate) / (1.0 / secondarySwath.rangeSamplingRate) - 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 ], azcoef=[ 0.0, 0.0, (1.0 / referenceSwath.prf) / (1.0 / secondarySwath.prf) - 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 ], azpos_off=0.0) if os.path.isfile(self._insar.secondarySlc): os.remove(self._insar.secondarySlc) os.remove(self._insar.secondarySlc + '.vrt') os.remove(self._insar.secondarySlc + '.xml') img = isceobj.createSlcImage() img.load(tmpSlc + '.xml') #remove original os.remove(tmpSlc + '.vrt') os.remove(tmpSlc + '.xml') os.rename(tmpSlc, self._insar.secondarySlc) #creat new img.setFilename(self._insar.secondarySlc) img.extraFilename = self._insar.secondarySlc + '.vrt' img.setAccessMode('READ') img.renderHdr() #update parameters #update doppler and azfmrate first index2 = np.arange(outWidth) index = np.arange(outWidth) * ( 1.0 / referenceSwath.rangeSamplingRate) / ( 1.0 / secondarySwath.rangeSamplingRate) dop = np.polyval(secondarySwath.dopplerVsPixel[::-1], index) p = np.polyfit(index2, dop, 3) secondarySwath.dopplerVsPixel = [p[3], p[2], p[1], p[0]] azfmrate = np.polyval( secondarySwath.azimuthFmrateVsPixel[::-1], index) p = np.polyfit(index2, azfmrate, 3) secondarySwath.azimuthFmrateVsPixel = [p[3], p[2], p[1], p[0]] secondarySwath.numberOfSamples = outWidth secondarySwath.numberOfLines = outLength secondarySwath.prf = referenceSwath.prf secondarySwath.rangeSamplingRate = referenceSwath.rangeSamplingRate secondarySwath.rangePixelSize = referenceSwath.rangePixelSize secondarySwath.azimuthPixelSize = referenceSwath.azimuthPixelSize secondarySwath.azimuthLineInterval = referenceSwath.azimuthLineInterval secondarySwath.prfFraction = referenceSwath.prfFraction os.chdir('../') os.chdir('../') #################################################### #4. mbf #################################################### for i, frameNumber in enumerate(self._insar.referenceFrames): frameDir = 'f{}_{}'.format(i + 1, frameNumber) os.chdir(frameDir) for j, swathNumber in enumerate( range(self._insar.startingSwath, self._insar.endingSwath + 1)): swathDir = 's{}'.format(swathNumber) os.chdir(swathDir) print('azimuth filter frame {}, swath {}'.format( frameNumber, swathNumber)) referenceSwath = referenceTrack.frames[i].swaths[j] secondarySwath = secondaryTrack.frames[i].swaths[j] #using Piyush's code for computing range and azimuth offsets midRange = referenceSwath.startingRange + referenceSwath.rangePixelSize * referenceSwath.numberOfSamples * 0.5 midSensingStart = referenceSwath.sensingStart + datetime.timedelta( seconds=referenceSwath.numberOfLines * 0.5 / referenceSwath.prf) llh = referenceTrack.orbit.rdr2geo(midSensingStart, midRange) slvaz, slvrng = secondaryTrack.orbit.geo2rdr(llh) ###Translate to offsets #at this point, secondary range pixel size and prf should be the same as those of reference rgoff = ((slvrng - secondarySwath.startingRange) / referenceSwath.rangePixelSize ) - referenceSwath.numberOfSamples * 0.5 azoff = ((slvaz - secondarySwath.sensingStart).total_seconds() * referenceSwath.prf) - referenceSwath.numberOfLines * 0.5 #filter reference if not ((self._insar.modeCombination == 21) and (self._insar.burstSynchronization <= self.burstSynchronizationThreshold)): print('no need to azimuth filter {}.'.format( self._insar.referenceSlc)) else: index = np.arange(referenceSwath.numberOfSamples) + rgoff dop = np.polyval(secondarySwath.dopplerVsPixel[::-1], index) p = np.polyfit(index - rgoff, dop, 3) dopplerVsPixelSecondary = [p[3], p[2], p[1], p[0]] tmpSlc = 'tmp.slc' mbf( self._insar.referenceSlc, tmpSlc, referenceSwath.prf, 1.0, referenceSwath.burstLength, referenceSwath.burstCycleLength - referenceSwath.burstLength, self._insar.burstUnsynchronizedTime * referenceSwath.prf, (referenceSwath.burstStartTime - referenceSwath.sensingStart).total_seconds() * referenceSwath.prf, referenceSwath.azimuthFmrateVsPixel, referenceSwath.dopplerVsPixel, dopplerVsPixelSecondary) if os.path.isfile(self._insar.referenceSlc): os.remove(self._insar.referenceSlc) os.remove(self._insar.referenceSlc + '.vrt') os.remove(self._insar.referenceSlc + '.xml') img = isceobj.createSlcImage() img.load(tmpSlc + '.xml') #remove original os.remove(tmpSlc + '.vrt') os.remove(tmpSlc + '.xml') os.rename(tmpSlc, self._insar.referenceSlc) #creat new img.setFilename(self._insar.referenceSlc) img.extraFilename = self._insar.referenceSlc + '.vrt' img.setAccessMode('READ') img.renderHdr() #filter secondary if not( ((self._insar.modeCombination == 21) and (self._insar.burstSynchronization <= self.burstSynchronizationThreshold)) or \ (self._insar.modeCombination == 31) ): print('no need to azimuth filter {}.'.format( self._insar.secondarySlc)) else: index = np.arange(secondarySwath.numberOfSamples) - rgoff dop = np.polyval(referenceSwath.dopplerVsPixel[::-1], index) p = np.polyfit(index + rgoff, dop, 3) dopplerVsPixelReference = [p[3], p[2], p[1], p[0]] tmpSlc = 'tmp.slc' mbf( self._insar.secondarySlc, tmpSlc, secondarySwath.prf, 1.0, secondarySwath.burstLength, secondarySwath.burstCycleLength - secondarySwath.burstLength, -self._insar.burstUnsynchronizedTime * secondarySwath.prf, (secondarySwath.burstStartTime - secondarySwath.sensingStart).total_seconds() * secondarySwath.prf, secondarySwath.azimuthFmrateVsPixel, secondarySwath.dopplerVsPixel, dopplerVsPixelReference) if os.path.isfile(self._insar.secondarySlc): os.remove(self._insar.secondarySlc) os.remove(self._insar.secondarySlc + '.vrt') os.remove(self._insar.secondarySlc + '.xml') img = isceobj.createSlcImage() img.load(tmpSlc + '.xml') #remove original os.remove(tmpSlc + '.vrt') os.remove(tmpSlc + '.xml') os.rename(tmpSlc, self._insar.secondarySlc) #creat new img.setFilename(self._insar.secondarySlc) img.extraFilename = self._insar.secondarySlc + '.vrt' img.setAccessMode('READ') img.renderHdr() os.chdir('../') os.chdir('../') #in case parameters changed self._insar.saveTrack(referenceTrack, reference=True) self._insar.saveTrack(secondaryTrack, reference=False) catalog.printToLog(logger, "runPrepareSlc") self._insar.procDoc.addAllFromCatalog(catalog)
def runSlcMatch(self): '''match a pair of SLCs ''' if not self.doDenseOffset: return if not ((self._insar.modeCombination == 0) or (self._insar.modeCombination == 1)): return catalog = isceobj.Catalog.createCatalog(self._insar.procDoc.name) self.updateParamemetersFromUser() demFile = os.path.abspath(self._insar.dem) wbdFile = os.path.abspath(self._insar.wbd) denseOffsetDir = 'dense_offset' os.makedirs(denseOffsetDir, exist_ok=True) os.chdir(denseOffsetDir) masterTrack = self._insar.loadProduct(self._insar.masterTrackParameter) slaveTrack = self._insar.loadProduct(self._insar.slaveTrackParameter) ######################################################################################### ################################################## # compute geometric offsets ################################################## if self.useGPU and self._insar.hasGPU(): topoGPU(masterTrack, 1, 1, demFile, 'lat.rdr', 'lon.rdr', 'hgt.rdr', 'los.rdr') geo2RdrGPU(slaveTrack, 1, 1, 'lat.rdr', 'lon.rdr', 'hgt.rdr', 'rg.off', 'az.off') else: topoCPU(masterTrack, 1, 1, demFile, 'lat.rdr', 'lon.rdr', 'hgt.rdr', 'los.rdr') geo2RdrCPU(slaveTrack, 1, 1, 'lat.rdr', 'lon.rdr', 'hgt.rdr', 'rg.off', 'az.off') ################################################## # resample SLC ################################################## #SlaveSlcResampled = os.path.splitext(self._insar.slaveSlc)[0]+'_resamp'+os.path.splitext(self._insar.slaveSlc)[1] SlaveSlcResampled = self._insar.slaveSlcCoregistered rangeOffsets2Frac = 0.0 azimuthOffsets2Frac = 0.0 resamp(self._insar.slaveSlc, SlaveSlcResampled, 'rg.off', 'az.off', masterTrack.numberOfSamples, masterTrack.numberOfLines, slaveTrack.prf, slaveTrack.dopplerVsPixel, [rangeOffsets2Frac, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], [azimuthOffsets2Frac, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]) create_xml(SlaveSlcResampled, masterTrack.numberOfSamples, masterTrack.numberOfLines, 'slc') if self.estimateResidualOffset: numberOfOffsets = 800 rangeStep = 50 length = masterTrack.numberOfLines width = masterTrack.numberOfSamples waterBodyRadar('lat.rdr', 'lon.rdr', wbdFile, 'wbd.rdr') wbd=np.memmap('wbd.rdr', dtype=np.int8, mode='r', shape=(length, width)) azimuthStep = int(length/width*rangeStep+0.5) landRatio = np.sum(wbd[0:length:azimuthStep,0:width:rangeStep]!=-1)/(int(length/azimuthStep)*int(width/rangeStep)) del wbd if (landRatio <= 0.00125): print('\n\nWARNING: land area too small for estimating residual slc offsets') print('do not estimate residual offsets\n\n') catalog.addItem('warning message', 'land area too small for estimating residual slc offsets', 'runSlcMatch') else: numberOfOffsets /= landRatio #we use equal number of offsets in range and azimuth here numberOfOffsetsRange = int(np.sqrt(numberOfOffsets)+0.5) numberOfOffsetsAzimuth = int(np.sqrt(numberOfOffsets)+0.5) if numberOfOffsetsRange > int(width/2): numberOfOffsetsRange = int(width/2) if numberOfOffsetsAzimuth > int(length/2): numberOfOffsetsAzimuth = int(length/2) if numberOfOffsetsRange < 10: numberOfOffsetsRange = 10 if numberOfOffsetsAzimuth < 10: numberOfOffsetsAzimuth = 10 ########################################## #2. match using ampcor ########################################## ampcor = Ampcor(name='insarapp_slcs_ampcor') ampcor.configure() mSLC = isceobj.createSlcImage() mSLC.load(self._insar.masterSlc+'.xml') mSLC.setAccessMode('read') mSLC.createImage() sSLC = isceobj.createSlcImage() sSLC.load(SlaveSlcResampled+'.xml') sSLC.setAccessMode('read') sSLC.createImage() ampcor.setImageDataType1('complex') ampcor.setImageDataType2('complex') ampcor.setMasterSlcImage(mSLC) ampcor.setSlaveSlcImage(sSLC) #MATCH REGION #compute an offset at image center to use rgoff = 0.0 azoff = 0.0 #it seems that we cannot use 0, haven't look into the problem if rgoff == 0: rgoff = 1 if azoff == 0: azoff = 1 firstSample = 1 if rgoff < 0: firstSample = int(35 - rgoff) firstLine = 1 if azoff < 0: firstLine = int(35 - azoff) ampcor.setAcrossGrossOffset(rgoff) ampcor.setDownGrossOffset(azoff) ampcor.setFirstSampleAcross(firstSample) ampcor.setLastSampleAcross(mSLC.width) ampcor.setNumberLocationAcross(numberOfOffsetsRange) ampcor.setFirstSampleDown(firstLine) ampcor.setLastSampleDown(mSLC.length) ampcor.setNumberLocationDown(numberOfOffsetsAzimuth) #MATCH PARAMETERS #full-aperture mode if (self._insar.modeCombination == 21) or \ (self._insar.modeCombination == 22) or \ (self._insar.modeCombination == 31) or \ (self._insar.modeCombination == 32): ampcor.setWindowSizeWidth(64) ampcor.setWindowSizeHeight(512) #note this is the half width/length of search area, number of resulting correlation samples: 32*2+1 ampcor.setSearchWindowSizeWidth(32) ampcor.setSearchWindowSizeHeight(32) #triggering full-aperture mode matching ampcor.setWinsizeFilt(8) ampcor.setOversamplingFactorFilt(64) #regular mode else: ampcor.setWindowSizeWidth(64) ampcor.setWindowSizeHeight(64) ampcor.setSearchWindowSizeWidth(16) ampcor.setSearchWindowSizeHeight(16) #REST OF THE STUFF ampcor.setAcrossLooks(1) ampcor.setDownLooks(1) ampcor.setOversamplingFactor(64) ampcor.setZoomWindowSize(16) #1. The following not set #Matching Scale for Sample/Line Directions (-) = 1. 1. #should add the following in Ampcor.py? #if not set, in this case, Ampcor.py'value is also 1. 1. #ampcor.setScaleFactorX(1.) #ampcor.setScaleFactorY(1.) #MATCH THRESHOLDS AND DEBUG DATA #2. The following not set #in roi_pac the value is set to 0 1 #in isce the value is set to 0.001 1000.0 #SNR and Covariance Thresholds (-) = {s1} {s2} #should add the following in Ampcor? #THIS SHOULD BE THE ONLY THING THAT IS DIFFERENT FROM THAT OF ROI_PAC #ampcor.setThresholdSNR(0) #ampcor.setThresholdCov(1) ampcor.setDebugFlag(False) ampcor.setDisplayFlag(False) #in summary, only two things not set which are indicated by 'The following not set' above. #run ampcor ampcor.ampcor() offsets = ampcor.getOffsetField() mSLC.finalizeImage() sSLC.finalizeImage() #3. cull offsets refinedOffsets = cullOffsetsRoipac(offsets, numThreshold=50) if refinedOffsets == None: print('\n\nWARNING: too few offsets left for slc residual offset estimation') print('do not estimate residual offsets\n\n') catalog.addItem('warning message', 'too few offsets left for slc residual offset estimation', 'runSlcMatch') else: rangeOffset, azimuthOffset = meanOffset(refinedOffsets) os.remove(SlaveSlcResampled) os.remove(SlaveSlcResampled+'.vrt') os.remove(SlaveSlcResampled+'.xml') rangeOffsets2Frac = rangeOffset azimuthOffsets2Frac = azimuthOffset resamp(self._insar.slaveSlc, SlaveSlcResampled, 'rg.off', 'az.off', masterTrack.numberOfSamples, masterTrack.numberOfLines, slaveTrack.prf, slaveTrack.dopplerVsPixel, [rangeOffsets2Frac, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], [azimuthOffsets2Frac, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]) create_xml(SlaveSlcResampled, masterTrack.numberOfSamples, masterTrack.numberOfLines, 'slc') catalog.addItem('number of offsets range', numberOfOffsetsRange, 'runSlcMatch') catalog.addItem('number of offsets azimuth', numberOfOffsetsAzimuth, 'runSlcMatch') catalog.addItem('range residual offset after geometric coregistration', rangeOffset, 'runSlcMatch') catalog.addItem('azimuth residual offset after geometric coregistration', azimuthOffset, 'runSlcMatch') if self.deleteGeometryFiles: os.remove('lat.rdr') os.remove('lat.rdr.vrt') os.remove('lat.rdr.xml') os.remove('lon.rdr') os.remove('lon.rdr.vrt') os.remove('lon.rdr.xml') os.remove('hgt.rdr') os.remove('hgt.rdr.vrt') os.remove('hgt.rdr.xml') os.remove('los.rdr') os.remove('los.rdr.vrt') os.remove('los.rdr.xml') # if os.path.isfile('wbd.rdr'): # os.remove('wbd.rdr') # os.remove('wbd.rdr.vrt') # os.remove('wbd.rdr.xml') ######################################################################################### os.chdir('../') catalog.printToLog(logger, "runSlcMatch") self._insar.procDoc.addAllFromCatalog(catalog)