448 lines
9.6 KiB
Python
448 lines
9.6 KiB
Python
#! /usr/bin/env python
|
|
|
|
#################################################################
|
|
|
|
### This program is part of PyINT v2.1 ###
|
|
|
|
### Copy Right (c): 2017-2019, Yunmeng Cao ###
|
|
|
|
### Author: Yunmeng Cao ###
|
|
|
|
### Contact : ymcmrs@gmail.com ###
|
|
|
|
#################################################################
|
|
|
|
|
|
|
|
import numpy as np
|
|
|
|
import os
|
|
|
|
import sys
|
|
|
|
import argparse
|
|
|
|
import subprocess
|
|
|
|
import re
|
|
|
|
|
|
|
|
from pyint import _utils as ut
|
|
|
|
|
|
|
|
INTRODUCTION = '''
|
|
|
|
-------------------------------------------------------------------
|
|
|
|
Unwrap differential interferogram using SNAPHU.
|
|
|
|
|
|
|
|
'''
|
|
|
|
|
|
|
|
EXAMPLE = '''
|
|
|
|
Usage:
|
|
|
|
unwrap_snaphu.py projectName Mdate Sdate
|
|
|
|
unwrap_snaphu.py PacayaT163TsxHhA 20150102 20150601
|
|
|
|
-------------------------------------------------------------------
|
|
|
|
'''
|
|
|
|
|
|
|
|
def cmdLineParse():
|
|
|
|
parser = argparse.ArgumentParser(description='Unwrap differential interferogram using SNAPHU.',\
|
|
|
|
formatter_class=argparse.RawTextHelpFormatter,\
|
|
|
|
epilog=INTRODUCTION+'\n'+EXAMPLE)
|
|
|
|
|
|
|
|
parser.add_argument('projectName', help='projectName for processing.')
|
|
|
|
parser.add_argument('Mdate', help='Master date.')
|
|
|
|
parser.add_argument('Sdate', help='Slave date.')
|
|
|
|
|
|
|
|
inps = parser.parse_args()
|
|
|
|
return inps
|
|
|
|
|
|
|
|
def run_command(cmd):
|
|
|
|
print(f"Running: {cmd}")
|
|
|
|
status = subprocess.call(cmd, shell=True)
|
|
|
|
if status != 0:
|
|
|
|
print(f"Error running command: {cmd}")
|
|
|
|
sys.exit(1)
|
|
|
|
|
|
|
|
def extract_value(s):
|
|
|
|
"""Extract numeric value from string that may contain units"""
|
|
|
|
# Remove any non-numeric characters except decimal point and minus sign
|
|
|
|
return re.sub(r'[^\d\.\-]', '', s)
|
|
|
|
|
|
|
|
def main(argv):
|
|
|
|
inps = cmdLineParse()
|
|
|
|
projectName = inps.projectName
|
|
|
|
Mdate = inps.Mdate
|
|
|
|
Sdate = inps.Sdate
|
|
|
|
|
|
|
|
scratchDir = os.getenv('SCRATCHDIR')
|
|
|
|
templateDir = os.getenv('TEMPLATEDIR')
|
|
|
|
templateFile = templateDir + "/" + projectName + ".template"
|
|
|
|
templateDict = ut.update_template(templateFile)
|
|
|
|
rlks = templateDict['range_looks']
|
|
|
|
azlks = templateDict['azimuth_looks']
|
|
|
|
|
|
|
|
processDir = scratchDir + '/' + projectName + "/PROCESS"
|
|
|
|
slcDir = scratchDir + '/' + projectName + "/SLC"
|
|
|
|
rslcDir = scratchDir + '/' + projectName + '/RSLC'
|
|
|
|
ifgDir = scratchDir + '/' + projectName + '/ifgrams'
|
|
|
|
|
|
|
|
Pair = Mdate + '-' + Sdate
|
|
|
|
workDir = ifgDir + '/' + Pair
|
|
|
|
|
|
|
|
# Create working directory if not exists
|
|
|
|
os.makedirs(workDir, exist_ok=True)
|
|
|
|
|
|
|
|
# Copy required files for processing
|
|
|
|
Mamp0 = rslcDir + '/' + Mdate + '/' + Mdate + '_' + rlks + 'rlks.amp'
|
|
|
|
MampPar0 = rslcDir + '/' + Mdate + '/' + Mdate + '_' + rlks + 'rlks.amp.par'
|
|
|
|
Samp0 = rslcDir + '/' + Sdate + '/' + Sdate + '_' + rlks + 'rlks.amp'
|
|
|
|
SampPar0 = rslcDir + '/' + Sdate + '/' + Sdate + '_' + rlks + 'rlks.amp.par'
|
|
|
|
|
|
|
|
Mamp = workDir + '/' + Mdate + '_' + rlks + 'rlks.amp'
|
|
|
|
MampPar = workDir + '/' + Mdate + '_' + rlks + 'rlks.amp.par'
|
|
|
|
Samp = workDir + '/' + Sdate + '_' + rlks + 'rlks.amp'
|
|
|
|
SampPar = workDir + '/' + Sdate + '_' + rlks + 'rlks.amp.par'
|
|
|
|
off_par = workDir + '/' + Pair + '_' + rlks + 'rlks.off'
|
|
|
|
ut.copy_file(Mamp0, Mamp)
|
|
|
|
ut.copy_file(Samp0, Samp)
|
|
|
|
ut.copy_file(MampPar0, MampPar)
|
|
|
|
ut.copy_file(SampPar0, SampPar)
|
|
|
|
|
|
|
|
# Define input/output files
|
|
|
|
int_dir = workDir
|
|
|
|
rootname = Pair + '_' + rlks + 'rlks'
|
|
|
|
int_file = int_dir + '/' + rootname + '.diff_filt'
|
|
|
|
cor_file = int_dir + '/' + rootname + '.diff_filt.cor'
|
|
|
|
|
|
|
|
# Read parameters from par files
|
|
|
|
width = ut.read_gamma_par(off_par, 'read', 'interferogram_azimuth_lines:')
|
|
length = ut.read_gamma_par(off_par, 'read', 'interferogram_width:')
|
|
#length = ut.read_gamma_par(MampPar, 'read', 'azimuth_lines')
|
|
row = ut.read_gamma_par(off_par, 'read', 'interferogram_azimuth_lines:')
|
|
col = ut.read_gamma_par(off_par, 'read', 'interferogram_width:')
|
|
pos = ut.read_gamma_par(MampPar, 'read', 'sar_to_earth_center')
|
|
earth = ut.read_gamma_par(MampPar, 'read', 'earth_radius_below_sensor')
|
|
near = ut.read_gamma_par(MampPar, 'read', 'near_range_slc')
|
|
dr = ut.read_gamma_par(off_par, 'read', 'interferogram_range_pixel_spacing:')
|
|
da_flight = ut.read_gamma_par(off_par, 'read', 'interferogram_azimuth_pixel_spacing:')
|
|
rangeres = ut.read_gamma_par(MampPar, 'read', 'range_pixel_spacing')
|
|
azres = ut.read_gamma_par(MampPar, 'read', 'azimuth_pixel_spacing')
|
|
nrange = ut.read_gamma_par(off_par, 'read', 'interferogram_range_looks:')
|
|
nazi = ut.read_gamma_par(off_par, 'read', 'interferogram_azimuth_looks:')
|
|
|
|
|
|
# Extract numeric values
|
|
earth = extract_value(earth)
|
|
pos = extract_value(pos)
|
|
near = extract_value(near)
|
|
dr = extract_value(dr)
|
|
da_flight = extract_value(da_flight)
|
|
nrange = extract_value(nrange)
|
|
nazi = extract_value(nazi)
|
|
rangeres = extract_value(rangeres)
|
|
azres = extract_value(azres)
|
|
|
|
alt = str(float(pos) - float(earth))
|
|
da = str(float(da_flight) * float(earth) / (float(earth) + float(alt)))
|
|
ncor = str(float(dr) * float(da) / (float(rangeres) * float(azres)))
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Create SNAPHU configuration file
|
|
|
|
conf_file = workDir + '/' + rootname + '.snaphuconf'
|
|
|
|
with open(conf_file, 'w') as f:
|
|
|
|
f.write(f"STATCOSTMODE SMOOTH\n")
|
|
|
|
f.write(f"INFILE {rootname}.int\n")
|
|
|
|
f.write(f"LINELENGTH {width}\n") # 使用原始宽度
|
|
|
|
f.write(f"OUTFILE {rootname}.unw\n")
|
|
|
|
f.write(f"CORRFILE {rootname}.cor\n")
|
|
|
|
f.write(f"LOGFILE {rootname}.snaphulog\n")
|
|
|
|
f.write(f"\n")
|
|
|
|
f.write(f"PIECEFIRSTROW 1\n")
|
|
|
|
f.write(f"PIECEFIRSTCOL 1\n")
|
|
|
|
f.write(f"PIECENROW {length}\n") # 使用原始长度
|
|
|
|
f.write(f"PIECENCOL {width}\n") # 使用原始宽度
|
|
|
|
f.write(f"ALTITUDE {alt}\n")
|
|
|
|
f.write(f"EARTHRADIUS {earth}\n")
|
|
|
|
f.write(f"NEARRANGE {near}\n")
|
|
|
|
f.write(f"BASELINE 0.000000\n")
|
|
|
|
f.write(f"BASELINEANGLE_DEG 0.000000\n")
|
|
|
|
f.write(f"TRANSMITMODE REPEATPASS\n")
|
|
|
|
f.write(f"DR {dr}\n")
|
|
|
|
f.write(f"DA {da}\n")
|
|
|
|
f.write(f"RANGERES {rangeres}\n")
|
|
|
|
f.write(f"AZRES {azres}\n")
|
|
|
|
f.write(f"LAMBDA 0.0556\n")
|
|
|
|
f.write(f"NLOOKSRANGE {nrange}\n")
|
|
|
|
f.write(f"NLOOKSAZ {nazi}\n")
|
|
|
|
f.write(f"NLOOKSOTHER 1\n")
|
|
|
|
f.write(f"NCORRLOOKS {ncor}\n")
|
|
|
|
f.write(f"\n")
|
|
|
|
f.write(f"CONNCOMPFILE {rootname}.byt\n")
|
|
|
|
f.write(f"MAXNCOMPS 32\n")
|
|
|
|
f.write(f"\n")
|
|
|
|
f.write(f"INFILEFORMAT COMPLEX_DATA\n")
|
|
|
|
f.write(f"OUTFILEFORMAT ALT_LINE_DATA\n")
|
|
|
|
f.write(f"CORRFILEFORMAT FLOAT_DATA\n")
|
|
|
|
f.write(f"VERBOSE FALSE\n")
|
|
|
|
|
|
|
|
# Swap bytes for input files
|
|
|
|
run_command(f"swap_bytes {int_file} {rootname}.int 4")
|
|
|
|
run_command(f"swap_bytes {cor_file} {rootname}.cor 4")
|
|
|
|
|
|
|
|
# Run SNAPHU
|
|
|
|
run_command(f"snaphu -f {conf_file}")
|
|
|
|
|
|
|
|
# Post-processing steps
|
|
|
|
xmin = "0"
|
|
|
|
ymin = "0"
|
|
|
|
xmax = width
|
|
|
|
ymax = length
|
|
|
|
|
|
|
|
# 获取SNAPHU输出文件的尺寸
|
|
|
|
unwrapped_file = f"{rootname}.unw"
|
|
new_width = str(int(xmax)-int(xmin))
|
|
|
|
# 计算填充量
|
|
|
|
npad_bottom = str(int(length) - int(ymax))
|
|
|
|
npad_right = str(int(width) - int(xmax))
|
|
|
|
|
|
|
|
print(f"Original dimensions: {width}x{length}")
|
|
|
|
print(f"SNAPHU output dimensions: {new_width}x{new_width}")
|
|
|
|
print(f"Padding: bottom={npad_bottom}, right={npad_right}")
|
|
|
|
|
|
|
|
# Zero padding
|
|
|
|
unw_zero_file = rootname + "_zeropad.unw"
|
|
|
|
mask_zero_file = rootname + "_mask_zeropad.unw"
|
|
|
|
mask_zero_file_msk = rootname + "_mask_zeropad.msk"
|
|
|
|
tobegeocodedm = rootname + "_masked.unw"
|
|
|
|
unw_file = rootname + "_msk.unw"
|
|
|
|
|
|
|
|
run_command(f"zeropad_msk {rootname}.unw {width} {ymin} {xmin} {npad_right} {npad_bottom} {unw_zero_file} rmg")
|
|
|
|
|
|
|
|
# Phase and magnitude processing
|
|
|
|
run_command(f"rmg2mag_phs {unw_zero_file} /dev/null phs {width}")
|
|
|
|
run_command(f"swap_bytes phs phs4 4")
|
|
|
|
run_command(f"cpx2mag_phs {rootname}.int pwr /dev/null {width}")
|
|
|
|
run_command(f"mag_phs2rmg pwr phs {unw_zero_file} {width}")
|
|
|
|
|
|
|
|
# Mask processing
|
|
|
|
run_command(f"zeropad_msk {rootname}.byt {width} {ymin} {xmin} {npad_right} {npad_bottom} {mask_zero_file_msk} msk")
|
|
|
|
run_command(f"cpx2mag_phs {rootname}.int pwr phs {width}")
|
|
|
|
run_command(f"mag_phs2rmg pwr {mask_zero_file_msk} {mask_zero_file} {width}")
|
|
|
|
|
|
|
|
# Combine results
|
|
|
|
run_command(f"rmg2mag_phs {unw_zero_file} pwr phs1 {width}")
|
|
|
|
run_command(f"rmg2mag_phs {mask_zero_file} /dev/null phs2 {width}")
|
|
|
|
run_command(f"add_phs phs1 phs2 phs3 {width} {length} 0 1")
|
|
|
|
run_command(f"add_phs pwr phs2 pwr3 {width} {length} 0 1")
|
|
|
|
run_command(f"mag_phs2rmg pwr3 phs3 {tobegeocodedm} {width}")
|
|
|
|
run_command(f"swap_bytes phs3 {unw_file} 4")
|
|
|
|
|
|
|
|
# Clean up temporary files
|
|
|
|
run_command("rm -rf pwr phs phs1 phs2 phs3 pwr3")
|
|
|
|
run_command(f"mv phs4 {unw_zero_file}")
|
|
|
|
|
|
|
|
# Remove copied files
|
|
|
|
os.remove(Mamp)
|
|
|
|
os.remove(Samp)
|
|
|
|
|
|
|
|
print("Unwrapping with SNAPHU is done!")
|
|
|
|
sys.exit(0)
|
|
|
|
|
|
|
|
if __name__ == '__main__':
|
|
|
|
main(sys.argv[:])
|