635 lines
30 KiB
Python
635 lines
30 KiB
Python
#
|
|
# Author: Cunren Liang
|
|
# Copyright 2015-present, NASA-JPL/Caltech
|
|
#
|
|
|
|
import os
|
|
import glob
|
|
import logging
|
|
import datetime
|
|
import numpy as np
|
|
|
|
import isceobj
|
|
from isceobj.Alos2Proc.Alos2ProcPublic import create_xml
|
|
|
|
logger = logging.getLogger('isce.alos2insar.runSwathMosaic')
|
|
|
|
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 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
|
|
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:
|
|
diffMean0 = 0.0
|
|
for k in range(30):
|
|
dataDiff = data1 * np.conj(data2)
|
|
cor = cal_coherence_1(dataDiff, win=5)
|
|
if filt:
|
|
index = np.nonzero(np.logical_and(cor>0.95, dataDiff!=0))
|
|
else:
|
|
index = np.nonzero(np.logical_and(cor>0.85, dataDiff!=0))
|
|
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))
|
|
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
|
|
(length7, width7)=dataDiff.shape
|
|
filename = 'diff_ori_s{}-s{}_loop_{}.int'.format(frame.swaths[i-1].swathNumber, frame.swaths[i].swathNumber, k)
|
|
dataDiff.astype(np.complex64).tofile(filename)
|
|
create_xml(filename, width7, length7, 'int')
|
|
filename = 'cor_ori_s{}-s{}_loop_{}.cor'.format(frame.swaths[i-1].swathNumber, frame.swaths[i].swathNumber, k)
|
|
cor.astype(np.float32).tofile(filename)
|
|
create_xml(filename, width7, length7, 'float')
|
|
|
|
|
|
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 swathMosaicParameters(frame, rangeOffsets, azimuthOffsets, numberOfRangeLooks, numberOfAzimuthLooks):
|
|
'''
|
|
mosaic swaths (this is simplified version of swathMosaic to update parameters only)
|
|
|
|
frame: frame
|
|
rangeOffsets: range offsets
|
|
azimuthOffsets: azimuth offsets
|
|
numberOfRangeLooks: number of range looks of the input files
|
|
numberOfAzimuthLooks: number of azimuth looks of the input files
|
|
'''
|
|
|
|
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]
|
|
|
|
#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
|
|
|
|
#update frame parameters
|
|
#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 readImage(inputfile, numberOfSamples, numberOfLines, startSample, endSample, startLine, endLine):
|
|
'''
|
|
read a chunk of image
|
|
the indexes (startSample, endSample, startLine, endLine) are included and start with zero
|
|
|
|
memmap is not used, because it is much slower
|
|
'''
|
|
data = np.zeros((endLine-startLine+1, endSample-startSample+1), dtype=np.complex64)
|
|
with open(inputfile,'rb') as fp:
|
|
#for i in range(endLine-startLine+1):
|
|
for i in range(startLine, endLine+1):
|
|
fp.seek((i*numberOfSamples+startSample)*8, 0)
|
|
data[i-startLine] = np.fromfile(fp, dtype=np.complex64, count=endSample-startSample+1)
|
|
return data
|
|
|
|
|
|
def findNonzero_v1(data):
|
|
'''
|
|
find the first/last non-zero line/sample
|
|
all indexes start from zero
|
|
'''
|
|
indexes = np.nonzero(data)
|
|
|
|
#first line last line first sample last sample
|
|
return (indexes[0][0], indexes[0][-1], indexes[1][0], indexes[1][-1])
|
|
|
|
|
|
def findNonzero(data, lineRatio=0.5, sampleRatio=0.5):
|
|
'''
|
|
find the first/last non-zero line/sample
|
|
all indexes start from zero
|
|
'''
|
|
import numpy as np
|
|
|
|
(length, width)=data.shape
|
|
|
|
lineIndex = (np.nonzero(np.sum((data!=0), axis=1) > width*lineRatio))[0]
|
|
sampleIndex = (np.nonzero(np.sum((data!=0), axis=0) > length*sampleRatio))[0]
|
|
|
|
#first line last line first sample last sample
|
|
return (lineIndex[0], lineIndex[-1], sampleIndex[0], sampleIndex[-1])
|
|
|
|
|