fix(pyint): integrate LT1 gamma import and coreg fixes

This commit is contained in:
2026-04-30 13:54:49 +08:00
parent 6513ff1623
commit 3474e25839
6 changed files with 521 additions and 52 deletions
@@ -0,0 +1,204 @@
# PyINT/Gamma LT-1 集成维护记录
更新时间:2026-04-30
## 1. 背景
本轮工作目标是评估并吸收专家提供的 `D:\Code\PyINT_LT1` 中 LT-1 / Gamma 相关修复,继续推进当前项目内 `PyINT / Gamma` 的 D-InSAR 生产能力。
已有排查结论见:
- `docs/PYINT_GAMMA_AB_FINDINGS_20260420.md`
- `docs/PYINT_GAMMA_INTEGRATION_DESIGN_20260418.md`
之前 A/B 排查已经确认:当前 PyINT/Gamma 的关键问题主要在 LT-1 导入、DEM 几何和 `coreg` 前置链路,不是解缠、地理编码或导出问题。并且旧的 rescue/fallback 曾经掩盖真实 `coreg` 失败,导致流程成功但产物全 0。
## 2. 专家代码判断
专家目录:
`D:\Code\PyINT_LT1`
该目录不是完整 PyINT 替代仓库,而是一组 LT-1 专用脚本补丁,主要包含:
- `down2slc_LT1.py`
- `down2slc_cat_LT1.py`
- `down2slc_LT1_all.py`
- `coreg_gamma.py`
- `coreg_gamma_all.py`
- `generate_rdc_dem.py`
- `makedem_pyint.py`
- `makedem.py`
- `diff/unwrap/geocode` 相关脚本
可吸收价值:
- 修正 LT-1 文件名日期提取偏移。
- 修正 LT-1 批处理错误日志名。
- 改善 `coreg_gamma.py` 中 master/slave 路径、RSLC 路径和 masterDate 选择。
- 增加 master 日期本身的 RSLC 生成处理。
- 对多景拼接场景更明确地区分单片 SLC、update SLC 和最终拼接 SLC。
不能整包覆盖的原因:
- 专家版多个脚本大量使用裸 `os.system()`,部分命令失败不会立即中断。
- 当前项目已经收紧失败语义,要求 Gamma 核心命令失败即失败,避免再次出现“假成功、全 0 结果”。
- 专家版引用 `LT1_precision_orbit.py`,但该文件不在 `D:\Code\PyINT_LT1` 中。
- 当前项目已经有系统级精轨桥接 `backend/app/pyint_pipeline/apply_lt1_precise_orbit.py`,不应退回到未纳管的外部精轨脚本。
- 当前 WSL 环境没有 `csh/tcsh`,不能让 Python 运行链硬依赖 `LT1_import_SLC_from_zipfiles1` 这类 csh 脚本。
## 3. 本轮改动范围
本轮只修改 Gamma/PyINT vendored 脚本,不修改 ISCE2 或 ENVI D-InSAR 生产链。
改动文件:
- `third_party/PyINT/pyint/down2slc_LT1.py`
- `third_party/PyINT/pyint/down2slc_cat_LT1.py`
- `third_party/PyINT/pyint/down2slc_LT1_all.py`
- `third_party/PyINT/pyint/coreg_gamma.py`
- `third_party/PyINT/pyint/generate_rdc_dem.py`
## 4. 已落实策略
### 4.1 LT-1 日期解析
旧实现使用固定切片 `file0[41:48]`,会把 `20241206` 截成 `0241206`
本轮改为从文件名中正则提取 `20\d{6}`,同时兼容 `.tar.gz``.tiff` 输入。
### 4.2 LT-1 单景导入
保留当前 Python 直接调用 `par_LT1_SLC` 的方式,不强制依赖 `csh`
如果运行环境中存在 `par_LT1_SLC_YSLi`
- 额外生成 `.slc.update` / `.slc.update.par`
- 将 update 参数文件中的 `state_vector_*` 合回主 `.slc.par`
- 同时对 `.slc.par``.slc.update.par` 执行当前项目的精轨桥接
如果运行环境中不存在 `par_LT1_SLC_YSLi`
- 继续使用 `par_LT1_SLC` 的输出
- 打印 warning
- 仍执行当前项目的精轨桥接
当前 WSL/Gamma 环境检查结果:
- `par_LT1_SLC` 可用
- `SLC_cat_list.py` 可用
- `par_LT1_SLC_YSLi` 不可用
- `csh/tcsh` 不可用
因此 `par_LT1_SLC_YSLi` 必须保持可选,不能作为硬依赖。
### 4.3 LT-1 多景拼接导入
多景场景改为逐景直接调用 Gamma 导入命令,并明确产出:
- `<date>_<product>.slc`
- `<date>_<product>.slc.par`
- 可选 `<date>_<product>.slc.update`
- 可选 `<date>_<product>.slc.update.par`
拼接时:
- 如果所有分片都有 update SLC,则优先用 update SLC tab 调用 `SLC_cat_list.py`
- 如果 update SLC 不可用,则回退到普通 SLC tab,并打印 warning
- 最终 `<date>.slc.par` 仍会再执行一次当前项目的精轨桥接
### 4.4 错误日志
`down2slc_LT1_all.py` 的错误日志从:
`down2slc_sen_all.err`
修正为:
`down2slc_LT1_all.err`
这能让运行失败时的阶段日志更准确。
### 4.5 coreg / DEM masterDate 兜底
`coreg_gamma.py``generate_rdc_dem.py` 增加 masterDate 实际存在性检查:
- 如果模板中的 `masterDate``SLC/` 下存在,则照常使用。
- 如果不存在,则选择最接近的已有 SLC 日期,并打印提示。
`coreg_gamma.py` 同时增加 master 日期本身处理:
- 如果 `Mdate == Sdate`,直接将 master SLC 复制为 master RSLC。
- 生成 master RSLC 的多视幅度。
- 不再进入 slave coreg 流程。
## 5. 保留的安全边界
本轮没有恢复旧 rescue/fallback。
必须继续保留:
- Gamma 核心命令失败即失败。
- `run_lt1_pyint_pipeline.py` 的全 0 二进制产物检查。
- 当前项目的 LT-1 精轨桥接和运行摘要记录。
- `Task_*` 输入资产适配层。
这几个边界是防止 PyINT/Gamma 再次产出“看似成功但科学结果无效”的关键。
## 6. 已完成验证
已完成静态验证:
```bash
python3 -m py_compile \
third_party/PyINT/pyint/down2slc_LT1.py \
third_party/PyINT/pyint/down2slc_cat_LT1.py \
third_party/PyINT/pyint/down2slc_LT1_all.py \
third_party/PyINT/pyint/coreg_gamma.py \
third_party/PyINT/pyint/generate_rdc_dem.py
```
已完成 diff 检查:
```bash
git diff --check
```
已确认本轮 Git 改动只包含 Gamma/PyINT 文件和本维护文档,不涉及 ISCE2 / ENVI 生产链。
## 7. 后续验证建议
建议用历史失败样例做 A/B
- `D:\Task_Pool\DInSAR\Task_260416_Gamma_PyINT\Task_20230602_20230720`
重点看:
- `down2slc_LT1_all.err`
- `coreg_gamma_all.err`
- `SLC/<date>/orbit_bridge_summary.json`
- `pyint_run_summary.json`
- `diff_filt` / `cor` / `unw` / `geo_unw` 的 all-zero 检查结果
判断标准:
- 不能靠 rescue 跳过失败。
- `coreg` 若失败,应明确失败并留下阶段日志。
- 若流程成功,关键二进制产物不能全 0。
- 精轨桥接 summary 应覆盖 master/slave 日期。
## 8. 建议提交
建议和本轮代码一起提交:
```powershell
git add docs/PYINT_GAMMA_LT1_INTEGRATION_NOTES_20260430.md `
third_party/PyINT/pyint/coreg_gamma.py `
third_party/PyINT/pyint/down2slc_LT1.py `
third_party/PyINT/pyint/down2slc_LT1_all.py `
third_party/PyINT/pyint/down2slc_cat_LT1.py `
third_party/PyINT/pyint/generate_rdc_dem.py
git commit -m "fix(pyint): integrate LT1 gamma import and coreg fixes"
```
+32 -2
View File
@@ -9,10 +9,30 @@ import numpy as np
import os import os
import sys import sys
import argparse import argparse
import re
from pyint import _utils as ut from pyint import _utils as ut
def _resolve_existing_master_date(slc_dir, requested_date):
if not os.path.isdir(slc_dir):
return requested_date
existing_dates = sorted(
item for item in os.listdir(slc_dir)
if re.match(r'^\d{8}$', item) and os.path.isdir(os.path.join(slc_dir, item))
)
if not existing_dates:
return requested_date
if requested_date in existing_dates:
return requested_date
if not requested_date or not re.match(r'^\d{8}$', str(requested_date)):
resolved = existing_dates[0]
else:
resolved = min(existing_dates, key=lambda item: abs(int(item) - int(requested_date)))
print('masterDate %s not found; using existing SLC date: %s' % (requested_date, resolved))
return resolved
def _run_or_raise(call_str, stage): def _run_or_raise(call_str, stage):
rc = os.system(call_str) rc = os.system(call_str)
if rc != 0: if rc != 0:
@@ -75,7 +95,7 @@ def main(argv):
templateDict=ut.update_template(templateFile) templateDict=ut.update_template(templateFile)
rlks = templateDict['range_looks'] rlks = templateDict['range_looks']
azlks = templateDict['azimuth_looks'] azlks = templateDict['azimuth_looks']
Mdate = templateDict['masterDate'] Mdate = _resolve_existing_master_date(slcDir, templateDict['masterDate'])
IFGPair = Mdate + '-' + Sdate IFGPair = Mdate + '-' + Sdate
demDir = scratchDir + '/' + projectName + '/DEM' demDir = scratchDir + '/' + projectName + '/DEM'
@@ -97,6 +117,16 @@ def main(argv):
Srslc0 = SrslcDir + "/" + Sdate + ".rslc0" Srslc0 = SrslcDir + "/" + Sdate + ".rslc0"
SrslcPar0 = SrslcDir + "/" + Sdate + ".rslc0.par" SrslcPar0 = SrslcDir + "/" + Sdate + ".rslc0.par"
if Mdate == Sdate:
Mslc0 = slcDir + '/' + Mdate + '/' + Mdate + '.slc'
MslcPar0 = slcDir + '/' + Mdate + '/' + Mdate + '.slc.par'
ut.copy_file(Mslc0, Srslc)
ut.copy_file(MslcPar0, SrslcPar)
call_str = 'multi_look ' + Srslc + ' ' + SrslcPar + ' ' + Sramp + ' ' + SrampPar + ' ' + rlks + ' ' + azlks
_run_or_raise(call_str, 'master_multi_look_rslc')
print('Master date: copy SLC to RSLC done.')
sys.exit(0)
##################################################### #####################################################
## copy all of the master files into slave folder for parallel processing ## copy all of the master files into slave folder for parallel processing
remove_file = [] remove_file = []
@@ -230,7 +260,7 @@ def main(argv):
for path in ( for path in (
lt0, lt1, mli0, diff0, offs0, snr0, offsets0, coffs0, coffsets0, lt0, lt1, mli0, diff0, offs0, snr0, offsets0, coffs0, coffsets0,
off, offs, snr, offsets, coffs, coffsets, Srslc0, SrslcPar0, off, offs, snr, offsets, coffs, coffsets, Srslc0, SrslcPar0,
Mslc, Mamp, HGTSIM, Mslc, MslcPar, Mamp, MampPar, HGTSIM,
): ):
_safe_remove(path) _safe_remove(path)
+67 -7
View File
@@ -23,8 +23,10 @@ from pyint import _utils as ut
def get_LT1_date(raw_file): def get_LT1_date(raw_file):
file0 = os.path.basename(raw_file) file0 = os.path.basename(raw_file)
date = file0[41:48] match = re.search(r'(20\d{6})', file0)
return date if match:
return match.group(1)
return ''
def get_satellite(raw_file): def get_satellite(raw_file):
if 'LT1A_MONO_' in raw_file: if 'LT1A_MONO_' in raw_file:
@@ -70,6 +72,48 @@ def _run_checked(command, cwd=None):
return result return result
def _format_state_vector_line(line):
stripped = line.strip()
parts = stripped.split()
if not parts:
return ''
label = parts[0]
if label.startswith('state_vector_position_') and len(parts) >= 4:
return '%s %14.4f %14.4f %14.4f m m m' % (
label,
float(parts[1]),
float(parts[2]),
float(parts[3]),
)
if label.startswith('state_vector_velocity_') and len(parts) >= 4:
return '%s %13.5f %13.5f %13.5f m/s m/s m/s' % (
label,
float(parts[1]),
float(parts[2]),
float(parts[3]),
)
return stripped
def _replace_state_vectors_from_update(slc_par_path, update_par_path):
if not os.path.isfile(update_par_path):
return
with open(slc_par_path, 'r', encoding='utf-8', errors='ignore') as fp:
base_lines = fp.read().splitlines()
with open(update_par_path, 'r', encoding='utf-8', errors='ignore') as fp:
update_state_lines = [
_format_state_vector_line(line)
for line in fp.read().splitlines()
if 'state_vector' in line
]
if not update_state_lines:
return
merged = [line for line in base_lines if 'state_vector' not in line]
merged.extend(update_state_lines)
with open(slc_par_path, 'w', encoding='utf-8') as fp:
fp.write('\n'.join(merged) + '\n')
def _cleanup_paths(paths): def _cleanup_paths(paths):
for path in paths: for path in paths:
if not path: if not path:
@@ -184,15 +228,32 @@ def main(argv):
input_tiff, input_xml, cleanup_paths = _resolve_lt1_input_scene(zipfile_ref, work_dir) input_tiff, input_xml, cleanup_paths = _resolve_lt1_input_scene(zipfile_ref, work_dir)
slc_path = work_dir + '/' + date + '.slc' slc_path = work_dir + '/' + date + '.slc'
slc_par_path = work_dir + '/' + date + '.slc.par' slc_par_path = work_dir + '/' + date + '.slc.par'
update_path = work_dir + '/' + date + '.slc.update'
update_par_path = work_dir + '/' + date + '.slc.update.par'
_run_checked( _run_checked(
['par_LT1_SLC', input_tiff, input_xml, slc_par_path, slc_path], ['par_LT1_SLC', input_tiff, input_xml, slc_par_path, slc_path],
cwd=work_dir, cwd=work_dir,
) )
if not os.path.isfile(slc_path) or not os.path.isfile(slc_par_path): if not os.path.isfile(slc_path) or not os.path.isfile(slc_par_path):
raise RuntimeError('LT-1 import produced no SLC outputs for date: ' + date) raise RuntimeError('LT-1 import produced no SLC outputs for date: ' + date)
bridge_targets = [slc_par_path]
ysli_command = shutil.which('par_LT1_SLC_YSLi')
if ysli_command:
_run_checked(
[ysli_command, input_tiff, input_xml, update_path, update_par_path, '0'],
cwd=work_dir,
)
if not os.path.isfile(update_path) or not os.path.isfile(update_par_path):
raise RuntimeError('LT-1 import produced no update SLC outputs for date: ' + date)
_replace_state_vectors_from_update(slc_par_path, update_par_path)
bridge_targets.append(update_par_path)
else:
print('WARNING: par_LT1_SLC_YSLi is not available; using par_LT1_SLC outputs only.')
bridge_result = orbit_bridge.apply_precise_orbit( bridge_result = orbit_bridge.apply_precise_orbit(
date, date,
[slc_par_path], bridge_targets,
work_dir=work_dir, work_dir=work_dir,
operation_tag='lt1_import', operation_tag='lt1_import',
) )
@@ -215,10 +276,9 @@ def main(argv):
if os.path.isfile(SLC_Tab): if os.path.isfile(SLC_Tab):
os.remove(SLC_Tab) os.remove(SLC_Tab)
for kk in range(len(SLC_list)): with open(SLC_Tab, 'w') as fp:
call_str = 'echo ' + SLC_list[kk] + ' ' + SLC_par_list[kk] + ' >> ' + SLC_Tab for kk in range(len(SLC_list)):
if os.system(call_str) != 0: fp.write(SLC_list[kk] + ' ' + SLC_par_list[kk] + '\n')
raise RuntimeError('Failed to write SLC tab for date: ' + date)
with open(work_dir + '/down2slc.dat', 'w') as f: with open(work_dir + '/down2slc.dat', 'w') as f:
f.write('ok\n') f.write('ok\n')
print("Down to SLC for %s is done! " % date) print("Down to SLC for %s is done! " % date)
+1 -1
View File
@@ -136,7 +136,7 @@ def main(argv):
for k0 in date_list: for k0 in date_list:
print(k0) print(k0)
err_txt = scratchDir + '/' + projectName + '/down2slc_sen_all.err' err_txt = scratchDir + '/' + projectName + '/down2slc_LT1_all.err'
if os.path.isfile(err_txt): os.remove(err_txt) if os.path.isfile(err_txt): os.remove(err_txt)
data_para = [] data_para = []
+194 -40
View File
@@ -14,6 +14,8 @@ import time
import glob import glob
import argparse import argparse
import re import re
import shutil
import tarfile
from pyint import _orbit_bridge as orbit_bridge from pyint import _orbit_bridge as orbit_bridge
from pyint import _utils as ut from pyint import _utils as ut
@@ -21,8 +23,10 @@ from pyint import _utils as ut
def get_LT1_date(raw_file): def get_LT1_date(raw_file):
file0 = os.path.basename(raw_file) file0 = os.path.basename(raw_file)
date = file0[41:48] match = re.search(r'(20\d{6})', file0)
return date if match:
return match.group(1)
return ''
def get_satellite(raw_file): def get_satellite(raw_file):
if 'LT1A_MONO_' in raw_file: if 'LT1A_MONO_' in raw_file:
@@ -48,6 +52,168 @@ def write_input_list(list_path, paths):
f.write(path + '\n') f.write(path + '\n')
def _strip_lt1_extension(path):
name = os.path.basename(path)
if name.lower().endswith('.tar.gz'):
return name[:-7]
if name.lower().endswith('.tiff'):
return name[:-5]
return os.path.splitext(name)[0]
def _get_product_id(path):
parts = _strip_lt1_extension(path).split('_')
if parts:
return parts[-1]
return ''
def _resolve_lt1_input_scene(raw_path, work_dir, product_id):
cleanup_paths = []
raw_lower = raw_path.lower()
if raw_lower.endswith('.tiff'):
input_xml = re.sub(r'\.tiff$', '.meta.xml', raw_path, flags=re.IGNORECASE)
if not os.path.isfile(input_xml):
raise FileNotFoundError('LT-1 meta xml does not exist: ' + input_xml)
return raw_path, input_xml, cleanup_paths
if raw_lower.endswith('.tar.gz'):
temp_dir = os.path.join(work_dir, 'tmp_data_dir_' + str(product_id or 'scene'))
if os.path.isdir(temp_dir):
shutil.rmtree(temp_dir)
os.makedirs(temp_dir, exist_ok=True)
cleanup_paths.append(temp_dir)
with tarfile.open(raw_path, 'r:gz') as archive:
member_names = archive.getnames()
tiff_members = [name for name in member_names if name.lower().endswith('.tiff')]
xml_members = [name for name in member_names if name.lower().endswith('meta.xml')]
if not tiff_members or not xml_members:
raise RuntimeError('LT-1 archive is missing .tiff or meta.xml: ' + raw_path)
tiff_member = tiff_members[0]
xml_member = xml_members[0]
archive.extract(tiff_member, path=temp_dir)
archive.extract(xml_member, path=temp_dir)
return os.path.join(temp_dir, tiff_member), os.path.join(temp_dir, xml_member), cleanup_paths
raise RuntimeError('Unsupported LT-1 input, only .tiff or .tar.gz are supported: ' + raw_path)
def _cleanup_paths(paths):
for path in paths:
if not path:
continue
try:
if os.path.isdir(path):
shutil.rmtree(path)
elif os.path.isfile(path):
os.remove(path)
except OSError:
continue
def _format_state_vector_line(line):
stripped = line.strip()
parts = stripped.split()
if not parts:
return ''
label = parts[0]
if label.startswith('state_vector_position_') and len(parts) >= 4:
return '%s %14.4f %14.4f %14.4f m m m' % (
label,
float(parts[1]),
float(parts[2]),
float(parts[3]),
)
if label.startswith('state_vector_velocity_') and len(parts) >= 4:
return '%s %13.5f %13.5f %13.5f m/s m/s m/s' % (
label,
float(parts[1]),
float(parts[2]),
float(parts[3]),
)
return stripped
def _replace_state_vectors_from_update(slc_par_path, update_par_path):
if not os.path.isfile(update_par_path):
return
with open(slc_par_path, 'r', encoding='utf-8', errors='ignore') as fp:
base_lines = fp.read().splitlines()
with open(update_par_path, 'r', encoding='utf-8', errors='ignore') as fp:
update_state_lines = [
_format_state_vector_line(line)
for line in fp.read().splitlines()
if 'state_vector' in line
]
if not update_state_lines:
return
merged = [line for line in base_lines if 'state_vector' not in line]
merged.extend(update_state_lines)
with open(slc_par_path, 'w', encoding='utf-8') as fp:
fp.write('\n'.join(merged) + '\n')
def _run_checked(command, cwd=None):
result = subprocess.run(
command,
cwd=cwd,
text=True,
capture_output=True,
check=False,
)
if result.returncode != 0:
detail = (result.stderr or result.stdout or "").strip()
raise RuntimeError(
'Command failed (%s): %s%s' % (
result.returncode,
' '.join(command),
('\n' + detail) if detail else '',
)
)
return result
def _import_lt1_scene(raw_path, date, work_dir, product_id):
cleanup_paths = []
try:
input_tiff, input_xml, cleanup_paths = _resolve_lt1_input_scene(raw_path, work_dir, product_id)
product_suffix = str(product_id or _get_product_id(raw_path) or 'scene')
prefix = date + '_' + product_suffix
slc_path = work_dir + '/' + prefix + '.slc'
slc_par_path = work_dir + '/' + prefix + '.slc.par'
update_path = work_dir + '/' + prefix + '.slc.update'
update_par_path = work_dir + '/' + prefix + '.slc.update.par'
_run_checked(
['par_LT1_SLC', input_tiff, input_xml, slc_par_path, slc_path],
cwd=work_dir,
)
required = [slc_path, slc_par_path]
ysli_command = shutil.which('par_LT1_SLC_YSLi')
if ysli_command:
_run_checked(
[ysli_command, input_tiff, input_xml, update_path, update_par_path, '0'],
cwd=work_dir,
)
required.extend([update_path, update_par_path])
_replace_state_vectors_from_update(slc_par_path, update_par_path)
else:
update_path = ''
update_par_path = ''
print('WARNING: par_LT1_SLC_YSLi is not available; using par_LT1_SLC outputs only.')
missing = [path for path in required if not os.path.isfile(path)]
if missing:
raise RuntimeError('LT-1 import is missing outputs: ' + ', '.join(missing))
return {
'slc': slc_path,
'slc_par': slc_par_path,
'update': update_path,
'update_par': update_par_path,
}
finally:
_cleanup_paths(cleanup_paths)
def cmdLineParse(): def cmdLineParse():
parser = argparse.ArgumentParser(description='Generate SLC from LT1 raw data with orbit correction using GAMMA.',\ parser = argparse.ArgumentParser(description='Generate SLC from LT1 raw data with orbit correction using GAMMA.',\
formatter_class=argparse.RawTextHelpFormatter,\ formatter_class=argparse.RawTextHelpFormatter,\
@@ -113,35 +279,18 @@ def main(argv):
file_num=len(raw_files) file_num=len(raw_files)
imported_items = []
for kk in range(file_num): for kk in range(file_num):
zipfile_ref=str(raw_files[kk]) zipfile_ref=str(raw_files[kk])
outfile_name=zipfile_ref.split('/')[-1] outfile_name=zipfile_ref.split('/')[-1]
print(outfile_name) print(outfile_name)
before_slc = set(glob.glob(work_dir + '/*.slc')) product_id = _get_product_id(zipfile_ref) or str(kk + 1)
before_slc_par = set(glob.glob(work_dir + '/*.slc.par')) imported = _import_lt1_scene(zipfile_ref, date, work_dir, product_id)
before_update = set(glob.glob(work_dir + '/*.slc.update')) imported_items.append(imported)
before_update_par = set(glob.glob(work_dir + '/*.slc.update.par')) bridge_targets = [imported['slc_par']]
call_str = "echo " + zipfile_ref + " >date" if imported.get('update_par'):
if os.system(call_str) != 0: bridge_targets.append(imported['update_par'])
raise RuntimeError('Failed to materialize LT-1 input list for date: ' + date)
call_str = 'LT1_import_SLC_from_zipfiles1 date 0 '
rc = os.system(call_str)
if rc != 0:
raise RuntimeError('LT1_import_SLC_from_zipfiles1 failed for date %s with rc=%s' % (date, rc))
after_slc = set(glob.glob(work_dir + '/*.slc'))
after_slc_par = set(glob.glob(work_dir + '/*.slc.par'))
after_update = set(glob.glob(work_dir + '/*.slc.update'))
after_update_par = set(glob.glob(work_dir + '/*.slc.update.par'))
new_slc = sorted(after_slc - before_slc)
new_slc_par = sorted(after_slc_par - before_slc_par)
new_update = sorted(after_update - before_update)
new_update_par = sorted(after_update_par - before_update_par)
if not new_slc or not new_slc_par:
raise RuntimeError('LT-1 import produced no SLC outputs for date: ' + date)
if len(new_update) != len(new_update_par):
raise RuntimeError('LT-1 import produced mismatched update SLC outputs for date: ' + date)
bridge_targets = sorted((after_slc_par - before_slc_par) | (after_update_par - before_update_par))
if bridge_targets: if bridge_targets:
bridge_result = orbit_bridge.apply_precise_orbit( bridge_result = orbit_bridge.apply_precise_orbit(
date, date,
@@ -157,10 +306,10 @@ def main(argv):
SLC_Tab = work_dir + '/' + date+'_SLC_Tab' SLC_Tab = work_dir + '/' + date+'_SLC_Tab'
SLC_Tab_update = work_dir + '/' + date+'_update_SLC_Tab' SLC_Tab_update = work_dir + '/' + date+'_update_SLC_Tab'
SLC_update_list = sorted(glob.glob(work_dir + '/*.slc.update')) SLC_list = [item['slc'] for item in imported_items]
SLC_update_par_list = sorted(glob.glob(work_dir + '/*.slc.update.par')) SLC_par_list = [item['slc_par'] for item in imported_items]
SLC_list = sorted(glob.glob(work_dir + '/*.slc')) SLC_update_list = [item['update'] for item in imported_items if item.get('update')]
SLC_par_list = sorted(glob.glob(work_dir + '/*.slc.par')) SLC_update_par_list = [item['update_par'] for item in imported_items if item.get('update_par')]
if len(SLC_list) == 0 or len(SLC_par_list) == 0: if len(SLC_list) == 0 or len(SLC_par_list) == 0:
raise RuntimeError('No LT-1 SLC outputs were generated for date: ' + date) raise RuntimeError('No LT-1 SLC outputs were generated for date: ' + date)
if len(SLC_list) != len(SLC_par_list): if len(SLC_list) != len(SLC_par_list):
@@ -171,16 +320,21 @@ def main(argv):
if os.path.isfile(SLC_Tab): if os.path.isfile(SLC_Tab):
os.remove(SLC_Tab) os.remove(SLC_Tab)
for kk in range(len(SLC_list)): with open(SLC_Tab, 'w') as fp:
call_str = 'echo ' + SLC_list[kk] + ' ' + SLC_par_list[kk] + ' >> ' + SLC_Tab for kk in range(len(SLC_list)):
if os.system(call_str) != 0: fp.write(SLC_list[kk] + ' ' + SLC_par_list[kk] + '\n')
raise RuntimeError('Failed to write SLC tab for date: ' + date) cat_tab = SLC_Tab
call_str = 'echo ' + SLC_update_list[kk] + ' ' + SLC_update_par_list[kk] + ' >> ' + SLC_Tab_update if len(SLC_update_list) == len(SLC_list):
if os.system(call_str) != 0: with open(SLC_Tab_update, 'w') as fp:
raise RuntimeError('Failed to write update SLC tab for date: ' + date) for kk in range(len(SLC_update_list)):
call_str = 'SLC_cat_list.py ' + SLC_Tab_update + ' ' + date + '.slc ' + date + '.slc.par ' fp.write(SLC_update_list[kk] + ' ' + SLC_update_par_list[kk] + '\n')
if os.system(call_str) != 0: cat_tab = SLC_Tab_update
raise RuntimeError('SLC_cat_list.py failed for date: ' + date) else:
print('WARNING: update SLC outputs are unavailable; concatenating par_LT1_SLC outputs.')
_run_checked(
['SLC_cat_list.py', cat_tab, date + '.slc', date + '.slc.par'],
cwd=work_dir,
)
if not os.path.isfile(work_dir + '/' + date + '.slc.par'): if not os.path.isfile(work_dir + '/' + date + '.slc.par'):
raise RuntimeError('Final LT-1 concatenated SLC parameter file is missing for date: ' + date) raise RuntimeError('Final LT-1 concatenated SLC parameter file is missing for date: ' + date)
final_bridge_result = orbit_bridge.apply_precise_orbit( final_bridge_result = orbit_bridge.apply_precise_orbit(
+23 -2
View File
@@ -9,9 +9,29 @@ import numpy as np
import os import os
import sys import sys
import argparse import argparse
import re
from pyint import _utils as ut from pyint import _utils as ut
def _resolve_existing_master_date(slc_dir, requested_date):
if not os.path.isdir(slc_dir):
return requested_date
existing_dates = sorted(
item for item in os.listdir(slc_dir)
if re.match(r'^\d{8}$', item) and os.path.isdir(os.path.join(slc_dir, item))
)
if not existing_dates:
return requested_date
if requested_date in existing_dates:
return requested_date
if not requested_date or not re.match(r'^\d{8}$', str(requested_date)):
resolved = existing_dates[0]
else:
resolved = min(existing_dates, key=lambda item: abs(int(item) - int(requested_date)))
print('masterDate %s not found; using existing SLC date: %s' % (requested_date, resolved))
return resolved
def cmdLineParse(): def cmdLineParse():
parser = argparse.ArgumentParser(description='Generate radar-coordinates based DEM.',\ parser = argparse.ArgumentParser(description='Generate radar-coordinates based DEM.',\
formatter_class=argparse.RawTextHelpFormatter,\ formatter_class=argparse.RawTextHelpFormatter,\
@@ -46,12 +66,13 @@ def main(argv):
templateFile = templateDir + "/" + projectName + ".template" templateFile = templateDir + "/" + projectName + ".template"
templateDict=ut.update_template(templateFile) templateDict=ut.update_template(templateFile)
Mdate = templateDict['masterDate'] Mdate = templateDict['masterDate']
DEMDir = os.getenv('DEMDIR') DEMDir = os.getenv('DEMDIR')
processDir = scratchDir + '/' + projectName + "/ifgrams" processDir = scratchDir + '/' + projectName + "/ifgrams"
slcDir = scratchDir + '/' + projectName + "/SLC" slcDir = scratchDir + '/' + projectName + "/SLC"
Mdate = _resolve_existing_master_date(slcDir, Mdate)
rlks = templateDict['range_looks'] rlks = templateDict['range_looks']
azlks = templateDict['azimuth_looks'] azlks = templateDict['azimuth_looks']