Integrate SBAS workflows and redesign task center

This commit is contained in:
2026-06-13 13:10:12 +08:00
parent b931e8db53
commit 58a87706ef
275 changed files with 18750 additions and 42524 deletions
@@ -0,0 +1,225 @@
# Gamma SBAS 正确实现路线 2026-06-07
## 结论
当前系统的 Gamma SBAS 实现是错误模式,不是“不严格模式”。它把专家文档中的逐命令流程抽象成了另一条 Gamma/PyINT 混合链路,导致生成结果无法按专家命令行过程复核,也不能作为正确 SBAS 成果交付。
本次重构目标:默认 LT1 Gamma SBAS 只能执行专家文档 `LT1_GAMMA_SBAS_逐命令处理流程.docx` 对应的命令链。系统的职责是封装专家命令行流程,而不是替换成看起来相似的工具链。
## 错误来源
| 专家文档要求 | 当前错误实现 | 重构要求 |
| --- | --- | --- |
| `par_LT1_SLC` 后执行 `ORB_filt_spline.py` | 当前使用 `LT1_precision_orbit.py` 桥接 | 改为专家文档记录的 `ORB_filt_spline.py`,保留轨道输入审计 |
| `create_offset/init_offset_orbit/init_offset/offset_pwr/offset_fit/SLC_interp` | 当前使用 `SLC_coreg.py --init_offset` | 删除默认流程中的 `SLC_coreg.py`,逐场景展开专家命令 |
| `dem_import/fill_gaps/gc_map2/pixel_area/create_diff_par/offset_pwrm/offset_fitm/gc_map_fine/geocode/geocode_back` | 当前复用 PyINT DEM cache 并使用 `gc_map1` | DEM 从源 GeoTIFF 导入,必须覆盖完整 stack bbox,不允许只覆盖中心点 |
| `base_calc/base_plot/mk_diff_2d` | 当前使用 `phase_sim_orb/SLC_diff_intf` | 改为 `mk_diff_2d` |
| `mk_adf_2d/ave_image/rascc_mask/mk_unw_2d` | 当前使用 `adf/cc_wave/mcf` | 改为专家文档的 `mk_adf_2d` 和两次 `mk_unw_2d` |
| `quad_fit/quad_sub/atm_mod_2d/fill_gaps/atm_sim_2d/sub_phase` | 当前部分接近但输入来自错误解缠链 | 保留命令类型,输入统一改为专家链路产物 |
| 三轮 `mb` 加复数转换/`unw_model` | 当前一轮 `mb` 后直接 `ts_rate` | 改为专家文档三轮反演;本机 Gamma 环境未提供 `unw_to_cpx`,实际使用 `real_to_cpx - <unw> <cpx> <width> 1` 执行同一位置的实数到复数转换 |
| `replace_values/mask_data/dispmap/ts_rate/geocode_back/data2geotiff/disp_prt_2d` | 当前 Python 转 LOS 后发布多套派生产品 | 改为专家文档输出链,派生产品只能在专家产物之后追加,不能替代主产品 |
## 正确流程
### 01 Workspace
创建专家文档目录结构:
- `RAW`
- `SLC`
- `dem`
- `rslc_prep`
- `mli_dir`
- `diff_dir`
- `diff1_dir`
- `sbas`
- `publish`
- `logs`
- `scripts`
- `state`
验收条件:目录存在,场景清单和源文件路径写入 manifest。
### 02 Import LT1 SLC
每景执行:
```bash
par_LT1_SLC <scene>.tiff <scene>.meta.xml <date>.slc.par <date>.slc 0
cp <date>.slc.par <date>.slc.par.orig
ORB_filt_spline.py <date>.slc.par.orig <date>.slc.par --ignore_start 3 --ignore_end 17 --degree 5
SLC_corners <date>.slc.par
disSLC <date>.slc <width> ...
dismph_fft <date>.slc <width> ...
```
验收条件:每景 `.slc/.slc.par/.slc.par.orig` 存在,`SLC_tab` 行数等于场景数。
### 03 Reference MLI
参考景执行:
```bash
multi_look <ref>.slc <ref>.slc.par <ref>_<rlks>_<azlks>.mli <ref>_<rlks>_<azlks>.mli.par <rlks> <azlks>
grep range_samples <ref>.mli.par
grep azimuth_lines <ref>.mli.par
ras_dB <ref>.mli <width> ...
SLC_corners <ref>.mli.par
```
验收条件:参考 MLI、参数文件、宽高审计和 BMP 浏览图存在。
### 04 DEM Lookup
执行专家 DEM 链:
```bash
dem_import <dem>.tif SRTM.dem SRTM.dem.par ...
fill_gaps SRTM.dem <dem_width> SRTM_dem_fill
gc_map2 <ref>.mli.par SRTM.dem.par SRTM_dem_fill <ref>_seg.dem_par <ref>_seg.dem <ref>.lt ...
pixel_area <ref>.mli.par <ref>_seg.dem_par <ref>_seg.dem <ref>.lt ...
create_diff_par <ref>.mli.par - <ref>.diff_par 1 0
offset_pwrm <ref>.gamma0 <ref>.mli <ref>.diff_par ...
offset_fitm <ref>.offs <ref>.snr <ref>.diff_par ...
gc_map_fine <ref>.lt <dem_width> <ref>.diff_par <ref>.lt_fine 1
geocode <ref>.lt_fine <ref>_seg.dem <dem_width> <ref>.hgt <mli_width> <mli_lines>
geocode_back <ref>.mli <mli_width> <ref>.lt_fine <ref>.geo <dem_width> <dem_lines> 5 0
```
验收条件:`<ref>.lt_fine``<ref>.hgt``<ref>_seg.dem_par` 存在;DEM 覆盖必须包含完整 stack bbox。
### 05 Coreg Prep
执行:
```bash
cp SLC/dates rslc_prep/dates
cp <ref>.slc <ref>.rslc
cp <ref>.slc.par <ref>.rslc.par
```
验收条件:参考 RSLC 和 `rslc_tab` 初始化完成。
### 06 Coregister Scenes
非参考景逐景执行:
```bash
create_offset <ref>.rslc.par <date>.slc.par <ref>_<date>.off 1
init_offset_orbit <ref>.rslc.par <date>.slc.par <ref>_<date>.off
init_offset <ref>.rslc <date>.slc <ref>.rslc.par <date>.slc.par <ref>_<date>.off <rlks> <azlks>
offset_pwr <ref>.rslc <date>.slc <ref>.rslc.par <date>.slc.par <ref>_<date>.off ...
offset_fit <ref>_<date>.offs <ref>_<date>.snr <ref>_<date>.off ...
SLC_interp <date>.slc <ref>.rslc.par <date>.slc.par <ref>_<date>.off <date>.rslc <date>.rslc.par
```
验收条件:每景 `.rslc/.rslc.par/.off` 存在,`rslc_tab` 行数等于场景数。
### 07 RMLI Average
执行:
```bash
mk_mli_all rslc_tab . <rlks> <azlks> 1 1.0 0.4 mli.ave
grep range_samples mli.ave.par
grep azimuth_lines mli.ave.par
ras_dB mli.ave <width> ...
```
验收条件:`mli.ave/mli.ave.par/mli.ave.bmp` 存在。
### 08 Diff Network
执行:
```bash
base_calc rslc_tab <ref>.rslc.par bprep_file itab 1 1 <bmin> <bmax> <tmin> <tmax> -
base_plot rslc_tab <ref>.rslc.par itab bprep_file 1
mk_diff_2d rslc_tab itab 0 <ref>.hgt - mli.ave mli_dir . <rlks> <azlks> 3 1 1 0 -u
```
验收条件:`itab``bprep_file`、每对 `.diff/.diff.bmp` 存在。
### 09 Filter Unwrap
执行:
```bash
mk_adf_2d rslc_tab itab mli.ave . 5 0.6 32 8 -u
ave_image cc.list <width> mean.cc
rascc_mask mean.cc - <width> 1 1 - 1 1 <threshold>
mk_unw_2d rslc_tab itab mli.ave . <threshold> 0 1 1 1 1 <r_seed> <a_seed> 1 -u
mk_unw_2d rslc_tab itab mli.ave . - - 1 1 1 1 <r_seed> <a_seed> 1 mean.cc_mask.bmp -u
```
验收条件:每对 `.adf.diff/.adf.cc/.adf.unw` 存在,`mean.cc_mask.bmp` 存在。
### 10 Detrend ATM
每对执行:
```bash
create_diff_par <pair>.off <pair>.off <pair>.diff_par 0 0
quad_fit <pair>.adf.unw <pair>.diff_par 5 5 - - 3 <pair>.unw_linear
quad_sub <pair>.adf.unw <pair>.diff_par <pair>.unw_sub_linear 0 0
atm_mod_2d <pair>.unw_sub_linear <ref>.hgt <pair>.adf.cc <pair>.diff_par - 0 <pair>.a0 <pair>.a1 ...
fill_gaps <pair>.a0 <model_width> <pair>.a0_fill ...
fill_gaps <pair>.a1 <model_width> <pair>.a1_fill ...
atm_sim_2d <pair>.diff_par <ref>.hgt <pair>.a0_fill <pair>.a1_fill <pair>.atm_model
sub_phase <pair>.unw_sub_linear <pair>.atm_model <pair>.diff_par <pair>.unw.atmsub 0
```
验收条件:`unw_atmsub_tab` 行数等于 `itab` 行数。
### 11 SBAS Inversion
执行:
```bash
mb unw_atmsub_tab RMLI_tab itab - itab_ts ras/diff1 1 diff1.sigma_ts 1 - <r_ref> <a_ref> 15 15 0.0 mli.ave.par
real_to_cpx - <pair>.unw.atmsub <pair>.unw.atmsub.cpx <width> 1
unw_model <pair>.unw.atmsub.cpx <pair>.unw.atmsub_sim <pair>.unw.atmsub_1 <width> <r_ref> <a_ref>
mb unw.atmsub_1_tab RMLI_tab itab - itab_ts ras/diff2 1 diff2.sigma_ts 0 - <r_ref> <a_ref> 15 15 0.0 mli.ave.par
mb final_unw_tab RMLI_tab itab - itab_ts ras/diff 0 diff.sigma_ts 0 - <r_ref> <a_ref> 15 15 0.5 mli.ave.par
```
验收条件:`ras/diff*.tab``diff.sigma_ts``itab_ts` 存在。
### 12 Outputs Points
执行:
```bash
replace_values diff.sigma_ts 0.5 0.0 diff.sigma_ts.masked <width> 1 2 0
mask_data ras/diff_<date> <width> ras/diff_<date>.masked diff.sigma_ts.masked.bmp 0
dispmap ras/<date>.disp.phase - mli.ave.par - ras/<date>.disp 0 0
ts_rate disp.TS_tab RMLI_tab itab_ts - los_def_rate los_def_const los_def_sigma 0
geocode_back los_def_rate <width> <ref>.lt_fine geo_los_def_rate <dem_width> <dem_lines> 5 0
data2geotiff <ref>_seg.dem_par geo_los_def_rate 2 geo_los_def_rate.tif
disp_prt_2d disp_geo.TS_tab RMLI_tab itab_ts - 3 disp_point.txt - geo_los_def_rate geo_diff.sigma_ts items.txt disp_tab.txt 3 1 0
```
验收条件:`geo_los_def_rate.tif` 和点时序输出来自专家输出链。
## 工程改造路线
1. 更新 stage plan:默认 `lt1_gamma_sbas` 的工具清单改为专家命令,删除 `SLC_coreg.py/gc_map1/SLC_diff_intf/mcf/单轮 mb` 作为默认阶段描述。
2. 更新专家步骤状态:`implementation_status` 不再使用 `implemented_bridge`,只有 `implemented``planned``blocked`
3. 重写 `_materialize_workflow_scripts`:生成 12 个专家脚本,禁止复制旧桥接脚本作为专家步骤。
4. 增加命令审计:从每个脚本提取命令,和专家步骤允许命令集比对;发现旧错误命令或缺少核心命令时,任务不能进入完成状态。
5. 修正 DEM 选择:DEM 必须覆盖完整 stack bbox;只覆盖中心点不能通过。
6. 重构各阶段执行:`prepare/execute_coregistration``prepare/execute_rdc_dem``prepare/execute_interferograms``prepare/execute_ipta_timeseries``prepare/execute_publish_products` 逐步改为调用对应专家脚本和专家输出路径。
7. 修正完成判定:`WORKFLOW_COMPLETED` 必须同时满足专家脚本全部完成、命令审计通过、关键输出来自专家链路。
8. 标记历史产物:旧错误链路产物不能被 catalog 当作有效 SBAS 成果。
## 本轮编码边界
本轮先完成默认模式的结构性改造:
- 文档化正确流程和验收条件。
- 修改 stage plan 和 manifest 口径。
- 生成专家 12 步脚本,不再复制旧桥接脚本。
- 增加命令审计,阻断旧错误命令链。
- 修正 DEM 覆盖判定。
后续继续把每个 `execute_*` 阶段从旧阶段脚本迁移到 12 步专家脚本。迁移过程中只允许使用专家文档命令;任何替代命令必须显式标记为未启用,不能进入生产完成状态。
@@ -0,0 +1,84 @@
# Gamma SBAS expert workflow audit 2026-06-08
## Scope
Audited run:
- `run_id`: `sbas_a5d51de3808a`
- workflow manifest: `backend/runtime/sbas_insar_production/runs/sbas_a5d51de3808a/manifest.json`
- command manifest: `backend/runtime/sbas_insar_production/runs/sbas_a5d51de3808a/gamma_command_manifest.json`
- scripts: `backend/runtime/sbas_insar_production/runs/sbas_a5d51de3808a/scripts/*.sh`
- result catalog product: `gamma_sbas_sbas_a5d51de3808a`
The audit checks whether the production path follows `LT1_GAMMA_SBAS_逐命令处理流程.docx` as represented by `docs/GAMMA_SBAS_EXPERT_CORRECT_IMPLEMENTATION_ROUTE_20260607.md`.
## Result
The Gamma processing chain is now aligned with the expert-document workflow at the command-chain level. The run completed all 12 expert workflow steps and the result catalog registers only the expert-chain products as the primary SBAS result.
This is not the old mixed Gamma/PyINT path. The old invalid run and old invalid catalog record were removed.
## Step Mapping
| Step | Expert workflow requirement | Current run evidence | Status |
| --- | --- | --- | --- |
| 01 Workspace | Expert directories: `RAW`, `SLC`, `dem`, `rslc_prep`, `mli_dir`, `diff_dir`, `diff1_dir`, `sbas`, `publish`, `logs`, `scripts`, `state` | All directories exist under the run root | Pass |
| 02 Import LT1 SLC | `par_LT1_SLC`, copy original par, `ORB_filt_spline.py`, `SLC_corners`, browse checks | Script uses `par_LT1_SLC` and `ORB_filt_spline.py`; SLC products exist | Pass |
| 03 Reference MLI | `multi_look`, width/line checks, `ras_dB`, `SLC_corners` | Command audit passed with `multi_look`, `ras_dB`, `SLC_corners`; `mli.ave` products exist | Pass |
| 04 DEM Lookup | `dem_import`, `fill_gaps`, `gc_map2`, `pixel_area`, `create_diff_par`, `offset_pwrm`, `offset_fitm`, `gc_map_fine`, `geocode`, `geocode_back` | Command audit passed; `20241007.lt_fine`, `20241007.hgt`, `20241007_seg.dem_par` exist | Pass |
| 05 Coreg Prep | Copy reference SLC to RSLC prep and initialize `rslc_tab` | `rslc_prep/rslc_tab` exists | Pass |
| 06 Coregister Scenes | `create_offset`, `init_offset_orbit`, `init_offset`, `offset_pwr`, `offset_fit`, `SLC_interp` | Command audit passed with all required commands | Pass |
| 07 RMLI Average | `mk_mli_all`, width/line checks, `ras_dB` | Command audit passed; `mli.ave`, `mli.ave.par` exist | Pass |
| 08 Diff Network | `base_calc`, `base_plot`, `mk_diff_2d` | Command audit passed; `itab`, `bprep_file` exist | Pass |
| 09 Filter Unwrap | `mk_adf_2d`, `ave_image`, `rascc_mask`, two `mk_unw_2d` passes | Command audit passed with required commands | Pass |
| 10 Detrend ATM | `create_diff_par`, `quad_fit`, `quad_sub`, `atm_mod_2d`, `fill_gaps`, `atm_sim_2d`, `sub_phase` | Command audit passed; `unw_atmsub_tab` exists | Pass |
| 11 SBAS Inversion | Three `mb` passes with complex conversion and `unw_model` correction | Script runs three `mb` calls, `real_to_cpx -`, `unw_model`; `diff.sigma_ts`, `itab_ts`, `ras/diff.tab` exist | Pass with documented compatibility note |
| 12 Outputs Points | `replace_values`, `mask_data`, `dispmap`, `ts_rate`, `geocode_back`, `data2geotiff`, `disp_prt_2d` | Command audit passed; `geo_los_def_rate.tif`, `geo_los_def_rate_rgb.tif`, `items.txt`, `disp_point.txt` exist | Pass |
## Compatibility Note
The expert route originally referenced `unw_to_cpx`. The installed Gamma environment used for this run does not provide `unw_to_cpx`, and the implementation uses:
```bash
real_to_cpx - <pair>.unw.atmsub <pair>.unw.atmsub.cpx <width> 1
```
This is used only at the same workflow point to create the complex input consumed by `unw_model`. The command manifest, production code, and audit route have been updated to state this explicitly.
## Primary Products
The valid expert-chain products are:
- `publish/geotiff/geo_los_def_rate.tif`
- `publish/geotiff/geo_los_def_rate_rgb.tif`
- `publish/points/items.txt`
- `publish/points/disp_point.txt`
System-generated visualization derivatives are:
- `publish/geotiff/geo_los_def_rate_rgb_preview.png`
- `publish/geotiff/geo_los_def_rate_hls_colorbar.png`
- `publish/monitor_points/expert_point_001_timeseries.png`
- `publish/monitor_points/expert_point_001_timeseries.csv`
- `publish/monitor_points/expert_point_001_metadata.json`
These derivatives are not substitutes for the expert Gamma products. They are catalog and UI display assets derived after the expert outputs exist.
## Catalog Status
After cleanup and rebuild:
- SBAS catalog run count: 1
- registered product: `gamma_sbas_sbas_a5d51de3808a`
- product status: `READY`
- health status: `OK`
- issue count: 0
## Residual Risk
The command chain now follows the expert workflow. Remaining validation should be scientific review of parameter choices and result interpretation, especially:
- reference window size and selected reference point
- baseline network selection and itab approval policy
- deformation sign convention for business reporting
- whether the expert accepts `real_to_cpx -` as the local Gamma equivalent of the documented complex conversion step
@@ -0,0 +1,99 @@
# Gamma SBAS runtime observations - 2026-06-11
## 1. Interactive display window blocks unattended runs
Observed during run:
```text
run_id: sbas_c65c7486f76e
workflow: SBAS_GAMMA_WORKFLOW
stage: 02_import_lt1_slc.sh
date observed: 2026-06-11
```
User reported a Gamma/WSL display-style window during execution. The window only had a `Close` button. After the user clicked `Close`, the workflow continued.
Runtime checks later showed the same run was still in `02_import_lt1_slc.sh`, processing LT-1 scenes with `par_LT1_SLC`. The first two scenes completed:
```text
20230624 -> completed SLC import
20230726 -> completed SLC import
20230819 -> running at 2026-06-11 11:18 Asia/Shanghai
```
There was a large delay between the end of `20230726` and the start of `20230819`. This is consistent with a blocking interactive display process. The likely trigger is the browse/preview commands in the import step:
```bash
disSLC ...
dismph_fft ...
```
These commands are useful for expert visual inspection, but they are not acceptable as blocking UI windows in a managed background production workflow.
The same window was reported again later in the same run while the import step was still active. This confirms the issue is repeatable and should be treated as a workflow design defect, not a one-off operator/environment event.
For the active run, do not modify the generated shell script in place unless the operator explicitly chooses to skip the remaining interactive preview commands. A targeted intervention is possible only when the active child process is a display command such as `disSLC` or `dismph_fft`; terminating `par_LT1_SLC` or the parent bash process would risk corrupting or interrupting the import product.
## 2. Current operational decision
The operator changed the decision after the window repeated: stop this run, clear the run records, and audit/fix the production workflow before re-running.
Completed cleanup:
```text
run_id: sbas_c65c7486f76e
processes: stopped
run directory: deleted
system_tasks deleted: 1
system_jobs deleted: 1
catalog products deleted: 0
```
## 3. Required follow-up after this run
The fix must preserve expert-command equivalence for calculation commands while removing interactive blocking behavior.
Important distinction:
- `disSLC` and `dismph_fft` are expert command-line manual QC/display commands.
- They are not required numerical SBAS calculation steps.
- In a managed backend production workflow they must not open a UI window.
- The system should expose reviewable assets through generated rasters/previews and frontend visualization instead.
Implementation requirements:
1. Keep expert preview/browse products where they are generated by non-interactive raster/export commands.
2. Do not execute expert manual display commands in default backend production.
3. Never require an operator to click `Close` for a backend job to continue.
4. Add a workflow-level guard that detects display commands likely to open an interactive window.
5. Update run status reporting so the frontend shows the actual executing step instead of leaving `02_import_lt1_slc` as `PENDING` while the WSL process is running.
Candidate code area:
```text
backend/app/services/sbas_insar_production_service.py
_write_import_lt1_slc_script / 02_import_lt1_slc.sh generation
```
Related generated commands observed in the current script:
```bash
disSLC "${slc}" "${width}" 1 0 - - 1 1 "${SLC_DIR}/${date}.slc.bmp" || true
dismph_fft "${slc}" "${width}" 1 0 - - 1 1 "${SLC_DIR}/${date}.slc_fft.bmp" || true
```
Implementation decision:
- Remove `disSLC` and `dismph_fft` from generated unattended production scripts.
- Keep them in expert-document metadata as `manual_qc_tools`.
- Add script-write and command-audit guards so future generated scripts fail before execution if blocking display tools are present.
- Keep `ras*` commands that write explicit output BMP/GeoTIFF preview files; those are batch product-generation commands, not interactive display windows.
## 4. Acceptance criteria
After the fix:
- A full Gamma SBAS run can complete unattended from the web UI.
- No Gamma display window should require manual close.
- Preview BMP/PNG artifacts are still generated for inspection when feasible.
- The step status file and frontend task status reflect the active step during long-running shell scripts.
@@ -0,0 +1,68 @@
# Gamma SBAS 0 速率无效值与结果展示设计
## 当前口径
专家 Gamma SBAS 核心速率产品:
- `publish/geotiff/geo_los_def_rate.tif`
- 原始单位按专家命令解释为 `m/yr`
- 前端展示统一换算为 `mm/yr`
当前处理口径按用户确认执行:`0` 速率按无效值处理。
原因是当前 GeoTIFF 的覆盖区外和部分背景区域都可能被写为 0;在没有专家显式稳定区 mask 或质量 mask 前,把 0 解释为稳定值会把背景大量纳入统计,导致 P05/P50/P95 等摘要失真。因此本阶段先按无效值处理 0,后续若专家确认稳定区 mask,再调整。
## 有效性规则
1. 有效像元必须位于专家 RGB 覆盖区内。
2. 有效像元必须是有限值:不是 `NaN``Inf``-Inf`
3. 有效像元必须满足 `geo_los_def_rate != 0`
4. `0` 不参与统计、不参与纯速率图渲染,显示为透明背景。
5. GeoTIFF 元数据 `nodata=0.0` 与当前口径一致,但后端仍显式记录该规则,避免前端误解。
## 后端实现
### `_build_expert_gamma_primary_geotiff_stats`
- 使用 `masked=False` 读取速率,避免 Rasterio 隐式规则不可见。
- 使用 `geo_los_def_rate_rgb.tif` 非黑像元推断专家覆盖区。
- 有效条件:`coverage & finite & (value != 0.0)`
- 输出字段:
- `zero_is_valid: false`
- `validity_rule: "expert_rgb_coverage_finite_nonzero_values"`
- `coverage_mask_source`
- `zero_count`
- `nonzero_count`
- `metadata_nodata_applied: true`
### `_build_gamma_hls_rate_preview`
- 使用同一覆盖区规则;
- `0` 速率透明;
- 非零速率按 Gamma `hls.cm` 和专家固定范围 `[-0.08, 0.08] m/yr` 着色。
## 前端展示
1. `LOS 速率纯色图` 文案说明:
-`geo_los_def_rate.tif` 派生;
- 不叠加强度图或底图;
- 0 速率按无效值透明处理。
2. 统计摘要显示:
- `0 速率:按无效值处理`
- `有效规则:专家覆盖区内有限非零值`
## 后续增强
1. 若专家提供显式有效 mask 或稳定区定义,可将本规则切换为“mask 内 0 稳定、mask 外 0 无效”。
2. 多点时序、速率直方图、剖面线和质量图应基于同一有效性规则生成。
3. 所有派生图必须标注规则来源,避免与专家原始计算产物混淆。
## 验证标准
1. 后端语法检查通过。
2. 纯速率图非透明比例应接近非零有效像元比例。
3. API 产品详情:
- `zero_is_valid=false`
- `validity_rule="expert_rgb_coverage_finite_nonzero_values"`
- `valid_count == nonzero_count`
4. 前端构建通过。
@@ -0,0 +1,696 @@
# 全局任务状态与界面锁重构设计
最后更新:2026-06-12
## 1. 背景
当前前端存在一个“全局界面锁”机制:只要系统检测到仍有活跃任务,并且该任务不在前端非阻塞白名单内,就会把整个系统切到全局锁定状态,并弹出 `ActiveTasksOverlay` 全屏遮罩。
这个设计在早期可以避免用户在 ENVI / SARscape / IDL 长任务执行期间重复点击、切换入口或提交冲突任务。但随着系统扩展到 D-InSAR、多引擎生产、SBAS-InSAR、数据接入、资产扫描、洪涝分析、AI 诊断等多个相对独立的任务域,全局锁已经过粗:
- SBAS Gamma / LandSAR SBAS 已经证明长任务可以不锁全局界面,只在模块内展示状态。
- 后端 `task_service.create_task()` 已经按 `task_type` 做同类型 `PENDING/RUNNING` 互斥。
- 很多任务只是扫描、解包、目录重建或产物刷新,不应阻断其他业务操作。
- 全屏遮罩会遮住当前功能页,用户看不到任务详情,也无法继续浏览结果或管理其他独立任务。
因此,本设计将“全局界面锁”降级为“全局任务状态中心”,并要求每个功能模块设计自己的任务状态面板和局部操作约束。
## 2. 当前实现审计
### 2.1 前端锁入口
核心文件:
- `frontend/src/hooks/useGlobalTaskControl.js`
- `frontend/src/hooks/useDinsarOperations.js`
- `frontend/src/components/ActiveTasksOverlay.jsx`
- `frontend/src/components/app/AppOverlays.jsx`
- `frontend/src/ProductionWorkspace.jsx`
当前逻辑:
1. `useGlobalTaskControl` 订阅 `/tasks/active` 或 SSE `/tasks/active/stream`
2. 前端维护 `pendingTaskIds``nonBlockingTaskIds`
3. 活跃任务中只要存在不属于 `NON_BLOCKING_TASK_TYPES` 的任务,就设置 `isGlobalLocked=true`
4. `AppOverlays` 根据 `isGlobalLocked` 渲染 `ActiveTasksOverlay`
5. `App.ensureCanOperate()` 会因为 `isGlobalLocked` 拒绝写操作。
### 2.2 当前非阻塞任务
当前白名单包括:
- `UNPACK_ARCHIVES`
- `UNPACK_SENTINEL1`
- `GF3_UNPACK`
- `GF3_SARSCAPE_PRODUCE`
- `GF3_SARSCAPE_SYNC`
- `GF3_SARSCAPE_CLEAN`
- `SCAN_ASSET_INVENTORY`
- `COPY_DATA`
- `SBAS_GAMMA_WORKFLOW`
- `SBAS_LANDSAR_WORKFLOW`
- `SBAS_COREGISTRATION`
- `SBAS_RDC_DEM`
- `SBAS_INTERFEROGRAMS`
- `SBAS_IPTA_TIMESERIES`
- `REBUILD_SBAS_INSAR_CATALOG`
这些任务已经以“不锁全局界面”的方式运行。
### 2.3 当前仍会锁全局界面的任务
主要原因通常不是任务本身必须锁,而是提交时没有传 `taskType``nonBlocking: true`
已审计到的典型入口:
- D-InSAR 生产任务
- `ProductionWorkspace.handleDinsarRunQueued()`
- `DinsarProductionPanel.handleSubmit()`
- D-InSAR 结果扫描
- `ProductionWorkspace.handleDinsarProductQueued()`
- `DinsarProductsPanel.handleScan()`
- IDL Import / IDL DInSAR
- `IDLAutomationPanel`
- AI 训练、全量预测、AI 诊断
- `useDinsarOperations.handleTrainAi()`
- `useDinsarOperations.handlePredictAll()`
- `useDinsarOperations.handleAnalyzeResult()`
- 灾害点同步
- `HazardPointPanel`
- 水体 / 洪涝检测任务
- `WaterMonitorPanel`
- 部分数据监控任务
- `GF3_BATCH_PROCESS`
- `SCAN_DATA`
- 手动 LT-1 / 精轨 / GF3 扫描
- 预览缓存重建
- `App.rebuildRadarPreviewCache()` 通过 `handleTaskStart(null, ...)` 触发临时全局锁
### 2.4 后端已有保护
后端 `backend/app/services/task_service.py``create_task()` 中已做同类型任务互斥:
- 查询相同 `task_type` 且状态为 `PENDING` / `RUNNING` 的任务。
- 如果存在,直接返回任务冲突错误。
这说明前端全局锁不是唯一安全机制。真正的任务并发保护应继续下沉到后端,并从 `task_type` 扩展到更精确的资源锁。
## 3. 设计目标
1. 取消“任意阻塞任务遮住整个系统”的交互模式。
2. 全局层只负责展示所有活跃任务、最近任务、失败任务和快捷入口。
3. 每个功能模块拥有自己的任务状态面板,只展示和本功能相关的任务。
4. 默认任务不锁全局界面。
5. 需要互斥的场景由后端资源锁保证,而不是靠前端遮罩保证。
6. 前端只做局部禁用:禁用同一个功能里会造成重复提交或破坏状态的按钮。
7. 保留管理员取消任务能力,但从“强制解锁”改为“取消/中止任务”。
## 4. 非目标
本设计不要求一次性重写所有任务系统。
不在本阶段处理:
- 重做后端任务表结构。
- 重写 job worker。
- 改变现有任务 API 的基本返回格式。
- 一次性把所有历史任务类型改名。
- 删除所有旧 overlay 代码。
本设计优先保证渐进迁移。
## 5. 新架构概览
```text
后端任务系统
├─ SystemTaskORM / TaskLogORM
├─ SystemJobORM
├─ task_type 同类型互斥
└─ 后续扩展:resource_lock_key / resource_scope
前端任务状态层
├─ 全局任务状态中心
│ ├─ 展示所有活跃任务
│ ├─ 展示最近失败 / 完成任务
│ ├─ 支持跳转到所属功能
│ └─ 不遮住全系统
├─ 功能级任务面板
│ ├─ D-InSAR 生产任务面板
│ ├─ SBAS-InSAR 生产任务面板
│ ├─ 数据接入任务面板
│ ├─ 资产库存任务面板
│ ├─ 洪涝分析任务面板
│ └─ AI / 灾害点任务面板
└─ 局部操作约束
├─ 同类任务运行中,禁用同类提交按钮
├─ 目录重建中,禁用同一目录重建按钮
└─ 其他功能仍可浏览和操作
```
## 6. 全局任务状态中心
### 6.1 职责
全局任务状态中心只做观察和导航,不做全局阻断。
职责:
- 汇总 `/tasks/active`
- 汇总最近任务 `/tasks/recent`
- 显示任务类型、状态、进度、开始时间、最近消息。
- 支持按功能域筛选:
- 数据接入
- D-InSAR
- SBAS-InSAR
- 洪涝
- AI
- 运维
- 支持点击任务跳转到所属功能页。
- 支持查看任务日志。
- 支持管理员取消任务。
### 6.2 交互形态
建议替换现有 `ActiveTasksOverlay`
- 不再使用全屏遮罩。
- 使用顶部状态入口或右下角任务抽屉。
- 有活跃任务时显示小型状态指示。
- 点击后打开任务中心抽屉或弹层。
- 弹层不阻止用户关闭和继续使用系统。
### 6.3 状态文案
旧文案:
```text
为了保证数据一致性,耗时任务执行期间 UI 已锁定。
```
应替换为:
```text
后台任务正在执行。你可以继续使用其他功能;同类任务的重复提交会由系统自动限制。
```
## 7. 功能级任务面板
每个功能页应自行展示本功能任务状态。这样用户在当前业务上下文里能直接看到“我刚提交的任务跑到哪一步”,而不是被全局遮罩挡住。
### 7.1 通用组件建议
新增通用组件:
- `TaskStatusPanel`
- `TaskLogPanel`
- `TaskProgressRow`
- `TaskStatusBadge`
- `useTaskMonitor`
建议参数:
```ts
type TaskStatusPanelProps = {
title: string;
taskTypes?: string[];
taskTypePrefixes?: string[];
taskIds?: string[];
showRecent?: boolean;
compact?: boolean;
onTaskClick?: (task) => void;
};
```
`useTaskMonitor` 负责:
-`taskTypes` / `taskTypePrefixes` 查询活跃任务。
- 轮询或复用全局 SSE 数据。
- 拉取指定任务日志。
- 返回 `activeTasks``recentTasks``latestTask``isBusy`
### 7.2 D-InSAR 生产
任务类型:
- `IDL_RUN_DINSAR`
- `ISCE2_RUN`
- `PYINT_RUN`
- `LANDSAR_RUN`
面板位置:
- `DinsarProductionPanel` 右侧或提交区下方。
局部约束:
- 如果同一 engine 的任务正在运行,禁用同 engine 再提交。
- 其他 engine 是否允许并行应由后端资源锁决定。
- 用户仍可查看历史 run、日志、结果列表。
### 7.3 D-InSAR 产物
任务类型:
- `SCAN_DINSAR`
- `DINSAR_RESULT_SCAN`
- `DINSAR_RESULT_PACKAGE`
- 以当前后端实际 task_type 为准。
面板位置:
- `DinsarProductsPanel` 扫描按钮旁或结果列表顶部。
局部约束:
- 同一 catalog 重建任务运行中,禁用重复重建按钮。
- 不影响 SBAS 生产、D-InSAR 生产、结果浏览。
### 7.4 SBAS-InSAR 生产
任务类型:
- `SBAS_GAMMA_WORKFLOW`
- `SBAS_LANDSAR_WORKFLOW`
- `SBAS_COREGISTRATION`
- `SBAS_RDC_DEM`
- `SBAS_INTERFEROGRAMS`
- `SBAS_IPTA_TIMESERIES`
当前状态:
- 已基本符合新设计。
- 已在模块内展示 Runtime Status。
- 已显式设置 `nonBlocking: true`
后续调整:
- 将 Runtime Status 抽成 `TaskStatusPanel` 风格组件。
- 支持按 `run_id` 过滤关联任务。
- 全局任务中心只显示摘要和跳转入口。
### 7.5 SBAS-InSAR 结果
任务类型:
- `REBUILD_SBAS_INSAR_CATALOG`
局部约束:
- 重建中只禁用“重建目录”按钮。
- 结果列表仍可浏览。
当前已接近目标。
### 7.6 数据接入与资产扫描
任务类型:
- `UNPACK_ARCHIVES`
- `UNPACK_SENTINEL1`
- `GF3_UNPACK`
- `GF3_BATCH_PROCESS`
- `GF3_SARSCAPE_PRODUCE`
- `GF3_SARSCAPE_SYNC`
- `GF3_SARSCAPE_CLEAN`
- `SCAN_DATA`
- `SCAN_ASSET_INVENTORY`
建议:
- 数据接入页按卫星/流程展示独立状态卡。
- `SCAN_DATA` 不应锁全局界面。
- `GF3_BATCH_PROCESS` 是否需要局部锁取决于是否写共享目录;默认只锁 GF3 预处理按钮。
### 7.7 洪涝 / 水体分析
任务类型:
- `WATER_GEOCODE_*`
- `WATER_DETECT_*`
- `WATER_FLOOD_*`
- `FLOOD_SCENE_PREPROCESS_*`
- `FLOOD_WATER_EXTRACTION_*`
- `FLOOD_DETECTION_*`
- `GF3_PROCESS_*`
建议:
- 洪涝工作台显示场景级任务状态。
- 使用 task type prefix 匹配。
- 不再触发全局锁。
- 单个场景处理时,只禁用该场景相关按钮。
### 7.8 AI 与灾害点
任务类型:
- `AI_TRAIN`
- `AI_PREDICT`
- `AI_ANALYZE`
- `AI_WARMUP`
- `SCAN_HAZARD`
建议:
- AI 质量页显示 AI 训练/预测任务状态。
- AI 诊断页显示诊断任务状态。
- `AI_TRAIN` 运行中禁用再次训练;不阻止浏览结果。
- `AI_ANALYZE` 运行中只禁用同一结果的重复诊断。
- `SCAN_HAZARD` 只影响灾害点同步按钮。
## 8. 任务分类模型
建议引入统一任务元数据配置,前端和后端可逐步共享。
```ts
type TaskUiPolicy = {
taskType: string;
featureScope: string;
label: string;
globalVisible: boolean;
globalBlocking: boolean;
localBlocking: boolean;
resourceScope?: string;
routeTarget?: string;
};
```
默认策略:
- `globalVisible=true`
- `globalBlocking=false`
- `localBlocking=true`
也就是说,任务默认显示在全局任务中心,但不锁整个系统。
只有极少数任务可设置:
```ts
globalBlocking=true
```
但这应作为过渡兼容,不作为长期设计。
## 9. 后端资源锁设计
后端当前只有 `task_type` 级互斥。这不足以表达以下场景:
- 同一个 run 不能同时执行两个会修改同一状态文件的步骤。
- 同一个 catalog 不能并发重建。
- 同一个输出目录不能被两个生产任务同时写入。
- 同一个 ENVI / SARscape 单实例资源不能并行调用。
建议新增资源锁概念。
### 9.1 资源锁 key
示例:
```text
sbas-run:{run_id}
sbas-catalog:{catalog_root}
dinsar-engine:{engine_code}
dinsar-root:{root_dir}
envi-runtime:{host_or_profile}
gf3-sarscape-root:{root_dir}
water-scene:{scene_id}
ai-model:{model_id}
```
### 9.2 后端行为
创建任务时检查:
-`task_type` 是否已有活跃任务。
-`resource_lock_key` 是否已有活跃任务。
如果冲突:
- 返回 `409 Conflict`
- 返回冲突任务 ID、任务类型、状态、消息。
前端收到后:
- 不弹全局锁。
- 在当前功能面板提示“已有同资源任务运行中”。
- 提供跳转到任务日志。
### 9.3 迁移方式
第一阶段不必改数据库结构,可把资源锁写入 `SystemTaskORM.params`
```json
{
"resource_lock_key": "sbas-run:sbas_e21648e52bd4",
"feature_scope": "sbas_insar"
}
```
后续再考虑独立列或资源锁表。
## 10. 前端状态管理重构
### 10.1 保留内容
保留:
- `/tasks/active` SSE / fallback polling。
- `activeTasks` 全局缓存。
- 任务完成后刷新相关数据的能力。
### 10.2 移除或降级内容
降级:
- `isGlobalLocked`
- `pendingTaskIds`
- `nonBlockingTaskIds`
- `NON_BLOCKING_TASK_TYPES`
- `ActiveTasksOverlay`
迁移后:
- `isGlobalLocked` 不再驱动全屏遮罩。
- `pendingTaskIds` 不再用于判断系统锁定。
- `nonBlockingTaskIds` 不再需要。
- `NON_BLOCKING_TASK_TYPES` 变成 `TASK_UI_POLICIES`
- `ActiveTasksOverlay` 替换为 `GlobalTaskCenter`
### 10.3 新 hook
建议新增:
```text
frontend/src/hooks/useTaskCenter.js
frontend/src/hooks/useTaskMonitor.js
frontend/src/config/taskUiPolicies.js
```
`useTaskCenter`
- 订阅 active tasks。
- 维护全局任务状态。
- 提供任务完成事件分发。
`useTaskMonitor`
- 从全局任务状态中过滤当前功能相关任务。
- 提供 `isBusy``latestTask``activeTasks``recentTasks`
## 11. 任务完成后的刷新策略
当前全局锁解除时会调用 `initializeAppData({ refreshRadarSearch: true })`,这也过粗。
应改成按任务类型刷新:
| 任务类型 | 刷新目标 |
|---|---|
| `UNPACK_ARCHIVES` | LT-1 数据检索选项、当前检索页 |
| `UNPACK_SENTINEL1` | Sentinel-1 资产状态 |
| `SCAN_ASSET_INVENTORY` | 资产库存状态 |
| `SBAS_*` | 对应 SBAS run detail 或产品 catalog |
| `REBUILD_SBAS_INSAR_CATALOG` | SBAS 产品列表 |
| `SCAN_DINSAR` | D-InSAR 产品列表 |
| `AI_TRAIN` / `AI_PREDICT` | AI 状态与结果质量 |
| `SCAN_HAZARD` | 灾害点列表 |
| `WATER_*` / `FLOOD_*` | 洪涝工作台当前场景/事件 |
实现上可维护:
```ts
TASK_COMPLETION_REFRESH_POLICIES
```
每个功能页也可以订阅自己的任务完成事件。
## 12. 迁移计划
### 阶段 1:文档与审计
状态:本设计文档。
输出:
- 当前锁机制审计。
- 新交互原则。
- 迁移边界。
### 阶段 2:抽象任务 UI policy
新增:
- `frontend/src/config/taskUiPolicies.js`
内容:
- task type -> label
- task type -> feature scope
- task type -> route target
- task type -> local/global blocking policy
替换:
- `useGlobalTaskControl.NON_BLOCKING_TASK_TYPES`
- `useDinsarOperations.NON_BLOCKING_TASK_TYPES`
- `ActiveTasksOverlay.getTaskTypeLabel`
验收:
- 所有任务类型 label 来自同一配置。
- 新任务默认不锁全局。
### 阶段 3:全局遮罩改为任务中心
新增:
- `GlobalTaskCenter`
- `TaskCenterButton` 或顶部状态入口
替换:
- `ActiveTasksOverlay`
验收:
- 有活跃任务时不再遮住全系统。
- 用户可继续切换页面和浏览结果。
- 管理员仍可取消任务。
### 阶段 4:功能级任务面板
优先级:
1. D-InSAR 生产
2. D-InSAR 产物
3. 数据接入
4. 洪涝分析
5. AI / 灾害点
6. SBAS 组件收敛到通用面板
验收:
- 每个功能页能看到本功能任务状态。
- 同类任务运行中,只禁用同类提交按钮。
### 阶段 5:后端资源锁
新增:
- 任务 params 中写入 `feature_scope``resource_lock_key`
- `task_service.create_task()` 支持资源锁冲突检查。
验收:
- 同 run、同目录、同 catalog 的冲突任务由后端返回 `409`
- 前端不靠全局遮罩防冲突。
### 阶段 6:删除旧全局锁状态
删除或废弃:
- `isGlobalLocked`
- `pendingTaskIds`
- `nonBlockingTaskIds`
- `handleTaskStart(null, ...)` 触发全局锁的路径
验收:
- 代码中不存在“无 taskId 触发全局锁”的逻辑。
- 全局任务中心只展示状态,不控制系统可用性。
## 13. 风险与处理
### 13.1 后端资源冲突未覆盖
风险:
- 去掉前端全局锁后,某些共享目录或单实例程序可能被并发调用。
处理:
- 迁移初期保留少量 `globalBlocking=true` 兼容策略。
- 优先给 ENVI / SARscape / 同目录生产补资源锁。
- 对不确定任务先做局部锁,不做全局遮罩。
### 13.2 用户忽略后台任务
风险:
- 没有全屏遮罩后,用户可能不知道任务仍在跑。
处理:
- 顶部或右下角常驻任务指示。
- 功能页内明确显示任务状态。
- 失败任务有醒目提示。
### 13.3 任务完成刷新过少
风险:
- 以前全局刷新掩盖了局部刷新缺失。
处理:
- 建立 `TASK_COMPLETION_REFRESH_POLICIES`
- 逐功能补刷新策略。
- 保留手动刷新入口。
## 14. 验收标准
完成重构后应满足:
1. 任意 SBAS 任务运行时,系统其他功能可正常浏览和操作。
2. D-InSAR 任务运行时,不再弹全屏锁;D-InSAR 面板显示任务进度。
3. 同一个 D-InSAR engine 或同一输出目录的冲突提交由后端拒绝。
4. 数据接入扫描/解包任务运行时,不影响生产管理和结果浏览。
5. 洪涝场景级任务运行时,只影响对应场景按钮。
6. AI 训练/预测运行时,不阻断地图、结果浏览和 SBAS/DInSAR 生产。
7. 所有活跃任务都能在全局任务中心找到。
8. 每个功能页能看到与本功能相关的任务。
9. 管理员取消任务能力仍可用,但语义是“取消任务”,不是“强制解锁界面”。
10. 代码中不再通过 `handleTaskStart(null, ...)` 触发全局锁。
## 15. 推荐首批改动清单
建议第一批代码改动只做前端交互,不动后端任务模型:
1. 新建 `taskUiPolicies.js`,统一任务 label、scope、blocking 策略。
2. 将 D-InSAR 生产、D-InSAR 产物、IDL、AI、灾害点、水体任务全部标为 `globalBlocking=false`
3. `ActiveTasksOverlay` 改为可关闭的 `GlobalTaskCenter`
4. `ensureCanOperate()` 不再读取 `isGlobalLocked`,只检查用户权限。
5. `rebuildRadarPreviewCache()` 删除 `handleTaskStart(null, ...)`,改用局部 loading。
6. D-InSAR 生产面板增加任务状态卡。
7. D-InSAR 产物面板增加目录扫描任务状态卡。
第二批再做后端资源锁。
## 16. 结论
全局界面锁应退出核心设计。任务系统的正确边界应是:
- 全局:看见所有任务。
- 功能页:管理本功能任务。
- 后端:保证资源互斥和并发安全。
前端全屏锁只应作为临时兼容手段,不应继续扩展。
+3
View File
@@ -18,6 +18,9 @@
- [FRONTEND_NAVIGATION_ARCHITECTURE.md](FRONTEND_NAVIGATION_ARCHITECTURE.md)
当前左侧导航和生产管理工作台视图模型。
- [GLOBAL_TASK_STATUS_LOCK_REDESIGN_20260612.md](GLOBAL_TASK_STATUS_LOCK_REDESIGN_20260612.md)
全局界面锁降级为任务状态中心、功能级任务面板和后端资源锁的重构设计。
## 生产与结果
- [PRODUCTION_RESULTS_MULTI_ENGINE_DESIGN_20260423.md](PRODUCTION_RESULTS_MULTI_ENGINE_DESIGN_20260423.md)
+56
View File
@@ -0,0 +1,56 @@
# LandSAR SBAS-InSAR Archive Record - 2026-06-06
## Decision
The current LandSAR license does not include SBAS-InSAR capability. LandSAR SBAS production is archived and should not be used as a production path unless the runtime/license is replaced with one that supports SBAS-InSAR.
Future SBAS production work should focus on Gamma SBAS.
## Archived Runs
### Run 1
- Task ID: `2f772b33-e463-415d-a0e5-3153b092ed74`
- Job ID: `1e89b910-437d-4d0c-9957-a908bcbf0651`
- Task type: `SBAS_LANDSAR_WORKFLOW`
- Run ID: `landsar_sbas_20260605T175848009769Z_sbas_be0008c47ac5`
- Status: `FAILED`
- Started at: `2026-06-06 01:58:33`
- Ended at: `2026-06-06 02:42:14`
- Failure summary: LandSAR SBAS workflow failed after LT-1 import; `InSAR_Console.exe` returned `Cannot read this ID` for configured SBAS proID `280039`.
### Run 2
- Task ID: `51adf126-3d4b-4404-94af-1c12c2103f11`
- Job ID: `03eee99a-3bbc-4d81-9fdc-bf6199751834`
- Task type: `SBAS_LANDSAR_WORKFLOW`
- Run ID: `landsar_sbas_20260606T083925060668Z_sbas_be0008c47ac5`
- Status: `FAILED`
- Started at: `2026-06-06 16:38:20`
- Ended at: `2026-06-06 17:03:29`
- Failure summary: LandSAR SBAS runtime unsupported. LT-1 import completed for 7 scenes, but `InSAR_Console.exe` did not accept process `SBAS Stream` / proID `280039`.
## Data Stack
- Stack ID: `sbas_be0008c47ac5`
- Scene count: `7`
- Dates: `20240516`, `20240711`, `20240905`, `20250417`, `20250612`, `20250807`, `20251002`
- DEM: `D:\DEM\HeiLongJiang10M_DEM.tif`
## Cleanup Scope
The following records and generated artifacts were removed after this archive note was created:
- `system_tasks` records for the two task IDs above.
- `system_jobs` records for the two job IDs above.
- `task_logs` rows for the two task IDs above.
- Run result directories under `D:\production_results\timeseries\sbas_landsar\runs`.
- LandSAR working directories under `D:\LandSAR_Work\sbas`.
No matching rows were found in `result_products`, `result_catalog_states`, or `ps_timeseries_runs`.
## Follow-Up
- Keep LandSAR SBAS disabled or clearly marked unsupported in production operations.
- Continue SBAS production through Gamma SBAS only.
- Revisit LandSAR SBAS only after a supported license/runtime is available and proID/process compatibility is verified before full production execution.
@@ -0,0 +1,283 @@
# LandSAR SBAS-InSAR 接入设计
记录时间:2026-06-04
## 1. 结论
LandSAR 支持 SBAS-InSAR。其 SBAS 是一体化流程,算法编号为 `280039`,参数文件入口是:
```text
SBASProcess
ID 280039
```
这条链路和当前系统里的 Gamma SBAS 不同。Gamma SBAS 是分阶段工作流,包含栈发现、baseline audit、共参考配准、RDC DEM、干涉图、IPTA 反演和发布阶段;LandSAR SBAS 更接近 LandSAR D-InSAR 的模式:准备好 `Task_*/Input_Data` 后,通过 `InSAR_Console.exe + 280039.txt` 一次执行。
因此接入建议是:在 SBAS-InSAR 页面新增 `LandSAR SBAS` 处理器分支,而不是把 LandSAR 硬塞进现有 Gamma 分阶段按钮。
## 2. LandSAR SBAS 输入输出
### 输入目录
LandSAR SBAS 扫描 `Task_*` 目录,每个任务目录要求:
```text
Task_xxx
|-- Input_Data
| |-- LT1*_SLC.xml
| |-- LT1*_SLC.tif
| `-- ...
`-- Output_Data
```
核心条件:
- `Input_Data` 下至少 3 景已导入的 LT-1 SLC。
- 每景需要 `LT1*_SLC.xml``LT1*_SLC.tif/.tiff` 配对。
- DEM 需要外部指定。
- 精轨最好已经写入 XML 或已通过 LandSAR 精轨导入流程处理。
当前 LandSAR 项目文档说明,TimeSeriesBuilder 输出的 `Task_TS_*/Input_Data` 可直接被 PS/SBAS 页面扫描。
### 输出目录
LandSAR SBAS 输出在每个任务的 `Output_Data`
```text
Output_Data
|-- *.los.tif
|-- *.raster.tif
|-- vector/
|-- 280039.log
`-- 280039_console.log
```
成功判定可参考 LandSAR GUI
- 日志包含 `SBAS``success`
- 或日志包含 `console success`
- 控制台返回码为 0
- 同时存在核心输出,如 `*.los.tif``*.raster.tif`
## 3. 与现有系统的差异
### 现有 Gamma SBAS
当前 `/api/sbas-insar-production` 是 Gamma / IPTA SBAS 主线:
- 从资产池发现 LT-1 或 Sentinel-1 候选栈。
- 创建 `run_manifest.json`
- 分阶段执行 Gamma 脚本。
- catalog 期望的核心产品是:
- `publish/geotiff/los_rate_toward_m_per_year.tif`
- `publish/geotiff/los_sigma_m_per_year.tif`
- 相关预览图、质量图和监测点曲线。
### LandSAR SBAS
LandSAR SBAS 的输入不是系统当前的资产栈 manifest,而是 LandSAR 风格的 `Task_*/Input_Data`
LandSAR SBAS 的输出语义也和 Gamma 不完全一致。`*.los.tif` 在文档里描述为 LOS 时序形变场,不应在没有验证前直接标成 Gamma 那种 `los_rate_toward_m_per_year` 速率产品。
因此 LandSAR SBAS 需要独立 processor 标识:
```text
processor_code = landsar_sbas
profile_code = lt1_landsar_sbas
engine_code = landsar
proid = 280039
```
## 4. 推荐接入路线
### 阶段 1MVP,只接现成 Task/Input_Data
目标:先让系统能扫描、提交、监控和归档 LandSAR SBAS,不负责从原始 LT-1 自动构建时序 Input_Data。
新增配置:
```text
LANDSAR_SBAS_ENABLED=true
LANDSAR_SBAS_WORK_ROOT=D:\LandSAR_Work\sbas
LANDSAR_SBAS_DEM_PATH=D:\DEM\HeiLongJiang10M_DEM.tif
LANDSAR_SBAS_TIMEOUT_SECONDS=172800
LANDSAR_SBAS_MIN_SCENES=3
LANDSAR_SBAS_SOURCE_ROOTS=D:\Task_Pool\SBAS
```
后端新增:
```text
backend/app/services/landsar_sbas_service.py
```
职责:
- 检查 LandSAR runtime、授权服务、`InSAR_Console.exe`、SBAS 相关 DLL。
- 扫描 root 下的 `Task_*` 或单个 `Task_*`
- 校验 `Input_Data` 内 SLC XML/TIF 数量。
- 生成 `280039.txt` 参数文件。
- 调用:
```text
D:\LandSAR\InSAR_Console.exe D:\LandSAR_Work\sbas\<run_id>\native\<task>\Output_Data\280039.txt
```
- 把日志和核心 GeoTIFF 复制到系统标准结果目录。
- 写入 `run_manifest.json``workflow_summary.json``product_summary.json`
建议标准结果目录:
```text
D:\production_results\timeseries\sbas\<run_id>
|-- run_manifest.json
|-- workflow_summary.json
|-- product_summary.json
|-- native_logs
| |-- 280039.txt
| |-- 280039.log
| `-- 280039_console.log
`-- publish
`-- landsar
|-- los_timeseries.tif
|-- post_raster.tif
`-- vector/
```
任务队列新增:
```text
JOB_TYPE_SBAS_LANDSAR_WORKFLOW = "SBAS_LANDSAR_WORKFLOW"
```
前端新增:
-`SBAS-InSAR 生产` 页面增加处理器选择:
- `Gamma / IPTA SBAS`
- `LandSAR SBAS`
- 选择 `LandSAR SBAS` 后显示:
- Task 根目录
- DEM 路径
- 最少景数
- 干涉对策略:`single` / `prim`
- 垂直基线阈值
- 时间基线阈值
- 方位向/距离向多视
- 输出 LOS 时序
- 输出编码后栅格
- 隐藏 Gamma 的 baseline/coreg/RDC DEM/IPTA 分阶段按钮。
### 阶段 2:接入 catalog 和结果页
当前 `sbas_insar_catalog_service.py` 主要按 Gamma 产品定义扫描。LandSAR 接入后有两种选择:
1. 复用 `sbas_insar` catalog,但让资产定义按 `processor_code` 分支。
2. 新建 `landsar_sbas` catalog。
建议选择 1。理由是前端结果页还是 SBAS-InSAR 结果,只是处理器不同。
需要调整:
- `_READY_STATUSES` 增加 LandSAR 完成状态。
- `_CORE_ASSETS` 改成按 processor 分支。
- LandSAR 主资产角色:
```text
primary_geotiff -> publish/landsar/los_timeseries.tif
secondary_geotiff -> publish/landsar/post_raster.tif
run_manifest -> run_manifest.json
workflow_summary -> workflow_summary.json
native_console_log -> native_logs/280039_console.log
```
注意:不要把 LandSAR `*.los.tif` 直接命名为 `los_rate_toward_m_per_year.tif`,除非算法工程师确认该文件确实是年速率图。
### 阶段 3:从资产池自动构建 LandSAR 时序 Input_Data
阶段 1 只接现成 `Task_*/Input_Data`。如果需要从系统资产池直接生产 LandSAR SBAS,需要新增前处理:
1. 从 LT-1 资产池选择同轨同极化多景。
2. 调用 LandSAR LT-1 数据导入 `100016`,构建多景 `Input_Data`
3. 调用 LandSAR 精轨导入 `100206`,或确认精轨已进入 XML。
4. 输出 `Task_TS_*/Input_Data`
5. 再调用 SBAS `280039`
这一阶段风险比 MVP 高,建议在 LandSAR SBAS 一体化流程跑通后再做。
## 5. 参数建议
MVP 默认参数应与 LandSAR GUI 保持一致:
```text
dem_data_type=1 # 文件。注意 SBAS 模板中 0 是目录,1 是文件
dem_format=4 # COPERNICUS,需结合实际 DEM 测试
intf_method=0 # single
perp_baseline=200
time_baseline=300
doppler_baseline=100
az_looks=3
rg_looks=3
da_threshold=0.25
intensity_threshold=0.0
calibration_threshold=0.4
fine_reg_window=128
resample_factor=2
network_type=0 # Delaunay
max_arc_distance=1000
solve_method=0 # Periodogram
max_temporal_coh=0.7
ref_point_index=0
spatial_filter_dist=1000
unwrap_ref_index=0
time_filter_threshold=0.3
do_los_output=1
gen_vector_map=0
gen_pre_raster=0
gen_post_raster=1
```
需要特别注意 DEM 参数。DInSAR 用 `HeiLongJiang10M_DEM.tif` 已跑通,但 SBAS 模板里的 DEM 类型字段和 DInSAR 不同:
- SBAS`dem_data_type=0` 表示目录,`1` 表示文件。
- 当前 DEM 是 GeoTIFF 文件,所以应传 `1`
## 6. 风险点
1. 输入结构风险
现有 Gamma SBAS 的候选栈不是 LandSAR 的 `Task_*/Input_Data`。MVP 必须明确只支持 LandSAR 已导入后的时序任务目录。
2. 输出语义风险
LandSAR `*.los.tif` 是否为单幅速率图、累计形变图,还是多波段时序图,需要用一次真实输出确认。没有确认前不能按 Gamma 年速率产品入库。
3. DLL 风险
SBAS/PS 可能需要 DInSAR 之外的 DLL,例如:
- `SAR_InSAR_MTInSARModel.dll`
- `SAR_InSAR_PSInSAR_CSU.dll`
- `SAR_InSAR_MBCP_MTInSARModel.dll`
LandSAR SBAS availability check 应单独检查这些 DLL。
4. 运行时间风险
SBAS 是多景时序处理,默认 timeout 应明显大于 DInSAR,建议先设为 48 小时。
5. catalog 风险
当前 SBAS catalog 以 Gamma 结果为主。LandSAR 接入时要做 processor-specific asset mapping,否则会出现“运行成功但结果页查不到”。
## 7. 建议下一步
先实现阶段 1
1. 新增 `landsar_sbas_service.py`,只支持扫描现成 `Task_*/Input_Data`
2. 新增 `SBAS_LANDSAR_WORKFLOW` 后台任务。
3. 前端 SBAS 页面增加 `LandSAR SBAS` 分支。
4. 先不改资产池自动构建,不接 Sentinel-1,不开放 GACOS。
5. 用一个 3 景以上的 `Task_TS_*` 做首轮真实测试。
6. 根据真实输出再接 catalog 和结果页。
这个路线保留 Gamma SBAS 现状,同时利用已经验证的 LandSAR runtime 和授权链路,风险最低。
@@ -0,0 +1,843 @@
# LandSAR D-InSAR 与 SBAS-InSAR 服务接入采购需求说明书
编制日期:2026-06-04
适用项目:InSAR 管理系统 v2
重点数据:陆探一号(LT-1 / LuTan-1SAR 数据
文档用途:供应商技术沟通、采购询价、招标需求编制
## 1. 项目背景
现有 InSAR 管理系统已经具备雷达影像资产管理、任务队列、生产任务监控、结果目录管理、D-InSAR 结果入库、SBAS-InSAR 结果 catalog、地图预览和结果查询等工程能力。系统侧按“处理器 processor + 工作流 workflow + 结果包 manifest”的方式组织外部算法服务,要求外部服务能够以稳定接口接收任务、返回结构化状态并输出可入库的标准结果。
本次拟采购 LandSAR 服务版中的陆探一号 D-InSAR 与 SBAS-InSAR 两个处理服务模块。服务应以本地部署方式运行在生产服务器上,通过 HTTP API、消息队列 API 或二者结合的方式接收处理任务。业务系统负责选择数据、创建任务、轮询或订阅任务状态、读取结果清单并完成 catalog 入库;LandSAR 服务负责实际算法生产、运行日志、状态输出和结果文件组织。
## 2. 建设目标
采购目标是获得一套可本地部署、可长期稳定运行、可由现有系统调用的 LandSAR 服务版 API 模块,重点支撑陆探一号 D-InSAR 与 SBAS-InSAR 自动化生产。
核心建设目标如下:
1. 支持陆探一号 D-InSAR 差分干涉生产,产出可入库、可预览、可下载的标准 GeoTIFF 结果。
2. 支持陆探一号 SBAS-InSAR 时序形变生产,产出语义明确、可归档、可预览、可下载的栅格或点矢量结果。
3. 支持 D-InSAR 与 SBAS-InSAR 所需的数据导入、轨道处理、DEM 处理、地理编码和结果发布能力。
4. 提供完整的任务提交、排队、状态查询、日志查询、结果查询、任务取消和错误码机制。
5. 与现有系统任务队列、数据目录、D-InSAR 结果 catalog、SBAS-InSAR 结果 catalog 和前端生产页面集成。
6. 避免业务系统直接维护算法进程、底层授权细节和非结构化运行状态。
## 3. 系统现状
### 3.1 现有业务系统
现有系统主要技术栈:
- 后端:FastAPI / Python。
- 前端:React / Vite。
- 任务队列:系统内置任务队列和任务日志表。
- 数据库:系统已有结果 catalog 和任务状态表。
- 文件组织:生产结果主要进入 `D:\production_results`,临时工作目录可配置。
### 3.2 现有系统接入边界
现有系统侧可提供以下集成条件:
- 可配置的源数据目录、工作目录、结果目录和 DEM 路径。
- 可按任务生成 `run_id``task_id``job_id` 并维护任务日志。
- D-InSAR 结果目录支持按 pair/run 组织。
- SBAS-InSAR 结果目录支持按 processor/run 组织。
- 结果 catalog 可按 `processor_code``engine_code``profile_code` 区分不同处理器。
- 前端生产页面可根据处理器能力显示不同参数和任务状态。
### 3.3 当前痛点
1. D-InSAR 和 SBAS-InSAR 长流程任务需要稳定的异步服务接口。
2. 任务状态、阶段进度、日志和错误原因需要结构化输出。
3. 错误码需要统一,便于系统侧自动诊断和前端展示。
4. 多任务并发、排队、互斥和取消能力需要明确。
5. SBAS-InSAR 输出语义、质量指标和结果文件组织需要供应商明确说明。
6. D-InSAR 与 SBAS-InSAR 需要共用统一的 API、任务状态和结果 manifest 规范,降低系统侧维护成本。
## 4. 采购范围
本次采购范围分为必选能力和可选能力。
### 4.1 必选能力
1. LandSAR 本地 API 服务部署授权。
2. 陆探一号 D-InSAR API。
3. 陆探一号 SBAS-InSAR API。
4. D-InSAR 与 SBAS-InSAR 所需的数据导入、轨道处理、DEM 支持和地理编码能力。
5. 任务队列、任务状态、日志、结果查询、任务取消和错误码接口。
6. API 调用文档、参数说明、返回值说明和示例代码。
7. 服务部署脚本、启动脚本、停止脚本、健康检查接口。
8. 授权服务部署说明和异常处理说明。
9. D-InSAR 与 SBAS-InSAR 各至少一组陆探一号样例数据的端到端验收支持。
### 4.2 可选能力
1. 陆探一号独立预处理 API。
2. 陆探一号 PS-InSAR API。
3. 多任务并发执行能力。
4. GPU 加速能力。
5. 断点续跑能力。
6. 结果自动发布为标准 GeoTIFF、COG 或瓦片服务。
7. 与第三方消息队列对接能力,例如 RabbitMQ、Redis Stream、Kafka 或 ZeroMQ。
## 5. 总体架构要求
### 5.1 部署方式
LandSAR API 服务应部署在本地生产服务器,推荐形态:
```text
InSAR 管理系统
-> HTTP API / MQ
-> LandSAR API Service
-> LandSAR Engine
-> 本地文件系统结果目录
```
服务应支持 Windows Server 环境部署,安装目录、工作目录、授权方式和监听端口均应可配置。
### 5.2 服务访问方式
服务应至少提供一种稳定接口方式:
- HTTP REST API,本地端口访问,如 `http://127.0.0.1:<port>`
- 或消息队列接口,任务提交后异步回传状态
推荐同时支持:
- HTTP API 用于任务提交、状态查询、日志查询、结果查询、健康检查。
- 消息队列用于长任务异步调度和状态通知。
### 5.3 任务执行模式
所有生产任务均应采用异步任务模式:
1. 系统提交任务。
2. LandSAR API 返回 `job_id`
3. 系统定期查询状态或接收消息通知。
4. 任务完成后系统读取结果清单并入库。
不建议采用一次 HTTP 请求长期阻塞等待处理完成的模式。
## 6. 数据范围要求
### 6.1 支持数据类型
本次重点支持陆探一号:
- LT-1A
- LT-1B
- SLC 产品
- HH 极化优先,后续可扩展 HV/VV/VH
- 同轨、同模式、同区域数据配对和时序处理
### 6.2 输入数据形态
服务应明确支持以下至少一种输入形态。
优先要求:
```text
原始 LT-1 产品目录或压缩包
```
同时兼容:
```text
已导入的 LT1*_SLC.xml + LT1*_SLC.tif
```
对于 D-InSAR,服务应支持输入主影像和辅影像路径。
对于 SBAS/PS,服务应支持输入多景时序数据目录。
### 6.3 辅助数据
服务应支持以下辅助数据配置:
- DEM 文件或 DEM 目录。
- 精密轨道文件目录。
- 输出目录。
- 临时工作目录。
- 可选 GCP 文件。
- 可选 GACOS 大气改正文件,若服务支持。
## 7. 功能需求
## 7.1 陆探一号支撑性预处理能力
### 7.1.1 功能目标
支撑性预处理能力用于满足 D-InSAR 和 SBAS-InSAR 生产前的数据导入、轨道处理、多视、地理编码和快视输出需要。若供应商提供独立预处理 API,应可作为后续扩展能力接入系统;若预处理仅作为 D-InSAR/SBAS-InSAR 内部阶段,也应在任务日志、阶段状态和结果 manifest 中体现。
### 7.1.2 必须支持的处理能力
1. 数据导入。
2. 精密轨道导入或轨道参数更新。
3. 多视处理。
4. 辐射定标或强度图生成。
5. 地形校正、正射校正或地理编码。
6. 输出标准 GeoTIFF。
7. 输出快视图。
8. 输出完整处理日志。
### 7.1.3 输入参数要求
如提供独立预处理 API,预处理任务应至少支持以下参数:
```json
{
"job_type": "lt1_preprocess",
"input_path": "D:/data/LT1/scene",
"dem_path": "D:/DEM/HeiLongJiang10M_DEM.tif",
"orbit_path": "D:/orbit_pools/landsar",
"output_dir": "D:/production_results/landsar_preprocess/<job_id>",
"work_dir": "D:/LandSAR_Work/api/<job_id>",
"polarization": "HH",
"az_looks": 3,
"rg_looks": 3,
"geocode": true,
"orthorectify": true,
"output_format": "GeoTIFF"
}
```
### 7.1.4 输出结果要求
如提供独立预处理 API,预处理任务应输出:
```text
output_dir
|-- manifest.json
|-- logs/
|-- quicklook/
|-- geotiff/
| |-- intensity_geo.tif
| |-- amplitude_geo.tif
| `-- ...
`-- metadata/
```
GeoTIFF 必须满足:
- GDAL 可读。
- 有 CRS。
- 有 GeoTransform。
- NoData 值明确。
- 数据类型明确。
- 可被 QGIS 打开。
- 可被现有系统用于地图预览和后续洪涝分析。
## 7.2 陆探一号 D-InSAR API
### 7.2.1 功能目标
D-InSAR API 用于对两景陆探一号 SLC 数据执行差分干涉处理,输出 LOS 形变、相干性、解缠相位和快视产品。
### 7.2.2 必须支持的处理能力
1. 主辅影像导入。
2. 精密轨道处理。
3. 配准。
4. 重采样。
5. 干涉图生成。
6. 去平地和地形相位。
7. Goldstein 或等效滤波。
8. 相干性计算。
9. 相位解缠。
10. LOS 向形变计算。
11. 地理编码。
12. 结果 GeoTIFF 输出。
13. 处理日志和参数文件输出。
### 7.2.3 可选处理能力
1. LOS 转垂直向形变。
2. GCP 优化。
3. 大气相位改正。
4. 自定义解缠阈值。
5. 自定义滤波参数。
大气相位改正如依赖 GACOS,应明确 GACOS 文件来源、格式和命名规则。不得在无 GACOS 文件时静默启用。
### 7.2.4 输入参数要求
D-InSAR API 应至少支持以下参数:
```json
{
"job_type": "lt1_dinsar",
"master": {
"xml": "D:/Task_Pool/DInSAR/Task_xxx/Input_Data/master.xml",
"slc": "D:/Task_Pool/DInSAR/Task_xxx/Input_Data/master.tif"
},
"slave": {
"xml": "D:/Task_Pool/DInSAR/Task_xxx/Input_Data/slave.xml",
"slc": "D:/Task_Pool/DInSAR/Task_xxx/Input_Data/slave.tif"
},
"dem_path": "D:/DEM/HeiLongJiang10M_DEM.tif",
"output_dir": "D:/production_results/dinsar/<pair_key>/<run_id>",
"work_dir": "D:/LandSAR_Work/api/<job_id>",
"az_looks": 3,
"rg_looks": 3,
"coh_mask_threshold": 0.3,
"unwrap_coh_threshold": 0.3,
"filter_alpha": 0.6,
"geocode": true,
"vertical_displacement": false,
"atmospheric_correction": false
}
```
### 7.2.5 输出结果要求
D-InSAR 结果应至少包含:
```text
output_dir
|-- manifest.json
|-- logs/
|-- geotiff/
| |-- los_displacement.tif
| |-- coherence.tif
| |-- unwrapped_phase.tif
| |-- wrapped_phase.tif
| `-- vertical_displacement.tif
|-- quicklook/
`-- metadata/
```
其中 `vertical_displacement.tif` 如未启用垂直向形变,可不生成。
核心 GeoTIFF 要求:
- 可被 GDAL/QGIS 读取。
- 坐标系和仿射变换完整。
- 单位明确,例如米、毫米或弧度。
- NoData 值明确。
- 方向约定明确,例如朝向雷达为正或远离雷达为正。
- 输出文件命名稳定,不随 GUI 语言环境变化。
## 7.3 陆探一号 SBAS-InSAR API
### 7.3.1 能力定位
SBAS-InSAR 是本次采购的必选服务模块。供应商应明确该模块是否已产品化支持 LT-1,并提供真实样例数据、处理报告、输出文件说明和接口调用示例。
### 7.3.2 基本要求
SBAS-InSAR API 应至少具备:
1. 多景 LT-1 SLC 输入。
2. 干涉对自动选择。
3. 垂直基线阈值设置。
4. 时间基线阈值设置。
5. 多视参数设置。
6. 相干点或有效像元筛选。
7. 时序形变反演。
8. LOS 时序或速率产品输出。
9. 编码后栅格产品输出。
10. 完整日志和质量指标输出。
### 7.3.3 输入参数要求
SBAS-InSAR API 应至少支持以下参数:
```json
{
"job_type": "lt1_sbas_insar",
"input_stack": {
"mode": "task_input_data",
"path": "D:/Task_Pool/SBAS/Task_xxx/Input_Data"
},
"dem_path": "D:/DEM/HeiLongJiang10M_DEM.tif",
"orbit_path": "D:/orbit_pools/landsar",
"output_dir": "D:/production_results/timeseries/sbas_landsar/<run_id>",
"work_dir": "D:/LandSAR_Work/api/<job_id>",
"az_looks": 3,
"rg_looks": 3,
"intf_method": "single",
"perp_baseline": 200,
"time_baseline": 300,
"doppler_baseline": 100,
"network_type": "delaunay",
"solve_method": "periodogram",
"los_output": true,
"post_raster": true,
"vector_output": false
}
```
服务应明确支持以下至少一种多景输入形态:
- 原始 LT-1 多景产品目录或压缩包列表。
- 已导入的 `LT1*_SLC.xml + LT1*_SLC.tif` 多景目录。
- LandSAR 服务约定的 `Task_*/Input_Data` 多景任务目录。
### 7.3.4 输出结果要求
SBAS-InSAR 结果应至少包含:
```text
output_dir
|-- manifest.json
|-- logs/
|-- geotiff/
| |-- los_timeseries.tif
| |-- los_rate.tif
| |-- quality.tif
| `-- post_raster.tif
|-- vectors/
|-- quicklook/
`-- metadata/
```
其中 `los_rate.tif``quality.tif``vectors/` 可按供应商算法实际输出调整,但 manifest 必须准确标明每个资产的角色、单位、维度和业务含义。
### 7.3.5 输出说明要求
供应商必须说明 SBAS 输出文件语义:
- 输出是累计形变、平均速率还是多波段时序。
- 单位是米、毫米、弧度还是其他。
- 正负号方向约定。
- 多波段时序的日期映射关系。
- 质量图或相干性图的含义。
- 参考点或参考区域信息。
- 干涉网络信息,包括时间基线、垂直基线和选对策略。
在未明确输出语义前,业务系统只按 LandSAR 原始产品归档,不直接标记为业务级年速率产品。供应商如要求系统展示年速率产品,必须明确输出确为年速率图,并提供单位、正负号方向和质量控制说明。
## 7.4 陆探一号 PS-InSAR API
### 7.4.1 能力定位
PS-InSAR 作为可选扩展能力。若供应商 API 服务支持,应明确接口成熟度和样例验证情况。
### 7.4.2 基本要求
如支持 PS-InSAR,应至少具备:
1. 多景 LT-1 SLC 输入。
2. PS 点选择。
3. 网络构建。
4. 参数估计。
5. 大气/轨道残差处理。
6. 时序形变反演。
7. 点矢量结果输出。
8. 栅格化或可视化输出。
9. 点位时间序列导出。
### 7.4.3 输出要求
PS-InSAR 输出应至少包含:
- PS 点 GeoJSON / Shapefile / CSV。
- 点位形变速率。
- 点位时序形变。
- 质量指标。
- 参考点信息。
- 坐标系统说明。
## 8. API 通用接口要求
### 8.1 健康检查接口
服务应提供:
```http
GET /health
GET /version
GET /capabilities
```
返回内容至少包括:
- 服务状态。
- LandSAR 引擎版本。
- 授权状态。
- 支持模块列表。
- 支持数据类型。
- 当前队列长度。
- 当前运行任务数量。
### 8.2 任务提交接口
服务应提供统一任务提交接口:
```http
POST /jobs
```
返回:
```json
{
"job_id": "string",
"status": "queued",
"message": "job accepted"
}
```
### 8.3 任务状态接口
```http
GET /jobs/{job_id}
```
返回:
```json
{
"job_id": "string",
"job_type": "lt1_dinsar",
"status": "running",
"progress": 45,
"stage": "geocoding",
"message": "processing geocoding",
"created_at": "2026-06-04T10:00:00Z",
"started_at": "2026-06-04T10:01:00Z",
"updated_at": "2026-06-04T10:30:00Z"
}
```
### 8.4 日志接口
```http
GET /jobs/{job_id}/logs
```
要求:
- 支持获取完整日志。
- 支持按 offset 或时间增量获取日志。
- 日志级别包含 INFO、WARNING、ERROR。
- 日志中应包含 LandSAR 原始错误信息。
### 8.5 结果接口
```http
GET /jobs/{job_id}/result
```
返回:
```json
{
"job_id": "string",
"status": "completed",
"output_dir": "D:/production_results/...",
"assets": [
{
"role": "primary_geotiff",
"path": "D:/production_results/.../los_displacement.tif",
"format": "GeoTIFF",
"unit": "m",
"description": "LOS displacement"
}
],
"logs": [],
"metadata": {}
}
```
### 8.6 任务取消接口
```http
POST /jobs/{job_id}/cancel
```
要求:
- 支持取消排队任务。
- 支持尽可能安全地中止运行中任务。
- 被取消任务应有明确状态 `cancelled`
- 不得留下无法再次运行的锁文件或僵尸进程。
## 9. 状态码和错误码要求
服务必须提供稳定错误码,至少包括:
| 错误码 | 含义 |
| --- | --- |
| LICENSE_UNAVAILABLE | 授权不可用 |
| ENGINE_NOT_READY | LandSAR 引擎不可用 |
| INVALID_INPUT | 输入参数错误 |
| INPUT_NOT_FOUND | 输入文件不存在 |
| DEM_NOT_FOUND | DEM 不存在 |
| ORBIT_NOT_FOUND | 精轨文件不存在 |
| UNSUPPORTED_SENSOR | 不支持的数据类型 |
| PROCESS_FAILED | 处理失败 |
| OUTPUT_MISSING | 处理完成但结果缺失 |
| TIMEOUT | 任务超时 |
| CANCELLED | 用户取消 |
错误响应应包含:
```json
{
"error_code": "DEM_NOT_FOUND",
"message": "DEM file not found",
"detail": "D:/DEM/xxx.tif",
"recoverable": true
}
```
## 10. 与现有系统集成要求
### 10.1 任务队列集成
现有系统会将 LandSAR API 服务视为外部处理器。业务系统负责创建本地任务记录,LandSAR API 负责实际生产。
集成流程:
```text
用户提交生产任务
-> 系统创建任务记录
-> 系统调用 LandSAR API
-> LandSAR API 返回 job_id
-> 系统轮询或订阅 job 状态
-> job 完成
-> 系统读取 result assets
-> 系统入库 catalog
-> 前端展示结果
```
### 10.2 文件目录集成
建议目录:
```text
D:\LandSAR_Work\api
D:\production_results\landsar_preprocess
D:\production_results\dinsar
D:\production_results\timeseries\sbas
D:\production_results\timeseries\psinsar
```
LandSAR API 应允许调用方指定:
- `work_dir`
- `output_dir`
- `log_dir`
- `temp_dir`
### 10.3 结果入库集成
LandSAR API 结果清单应便于系统入库。推荐每个任务输出:
```text
manifest.json
```
manifest 至少包含:
- job_id
- job_type
- processor_code
- input_files
- output_files
- parameters
- start_time
- end_time
- status
- CRS
- bbox
- unit
- NoData
- software_version
- license_mode
## 11. 性能和稳定性要求
### 11.1 并发要求
供应商应明确:
- 是否支持多任务并行。
- 最大并发任务数。
- 不同模块是否互斥。
- D-InSAR 与预处理是否可同时执行。
- API 服务是否支持排队。
如不支持并发,服务也必须支持内部排队或返回明确的忙碌状态。
### 11.2 超时要求
建议默认超时:
- 预处理:6 小时。
- D-InSAR12 小时。
- SBAS-InSAR48 小时。
- PS-InSAR72 小时。
超时后应返回明确状态,并保留日志。
### 11.3 稳定性要求
服务应支持:
- 长时间运行。
- 进程异常退出后自动恢复。
- 服务重启后查询历史任务。
- 任务失败后保留工作目录和日志。
- 任务成功后可按配置清理中间文件。
## 12. 安全和授权要求
1. API 服务应支持本机访问限制,默认只监听 `127.0.0.1`
2. 如监听局域网地址,应支持 Token 或 API Key。
3. 授权异常应有明确错误码。
4. 授权服务应支持开机自启动或由 API 服务托管启动。
5. 授权有效期、授权模块列表应可查询。
## 13. 文档和交付物要求
供应商应提供:
1. API 接口文档。
2. OpenAPI / Swagger 文档。
3. 参数说明表。
4. 错误码说明表。
5. 部署说明。
6. 授权说明。
7. 示例调用代码,至少包括 Python 示例。
8. 示例数据处理报告。
9. 结果文件格式说明。
10. 运维手册。
## 14. 验收要求
### 14.1 支撑性预处理验收
如供应商提供独立预处理 API,使用至少 1 景 LT-1 数据完成预处理,验收项:
- API 可提交任务。
- 任务状态可查询。
- 日志可查询。
- 输出 GeoTIFF 可被 GDAL/QGIS 打开。
- 输出包含 CRS 和 GeoTransform。
- 系统可读取结果并生成预览。
### 14.2 D-InSAR 验收
使用至少 1 组 LT-1 主辅影像完成 D-InSAR,验收项:
- API 可提交任务。
- 可输出 LOS 形变 GeoTIFF。
- 可输出相干性 GeoTIFF。
- 可输出解缠相位或差分相位产品。
- 可输出处理日志。
- 结果可进入现有系统 D-InSAR 结果管理。
- 任务失败时错误码明确。
### 14.3 SBAS-InSAR 验收
使用不少于 3 景 LT-1 数据完成 SBAS-InSAR 样例处理。若供应商建议更高的最小景数,应按供应商推荐值提供样例数据和验收结果。
验收项:
- API 可提交异步 SBAS-InSAR 任务。
- 任务状态、阶段进度和日志可查询。
- 可设置时间基线、垂直基线、多视参数和干涉网络策略。
- 可输出 LOS 时序、速率、累计形变或供应商算法定义的主产品。
- 输出结果语义明确,包括单位、正负号方向、日期映射、参考点和质量指标。
- 输出 GeoTIFF 或点矢量结果可被 GDAL/QGIS 读取。
- 结果可进入现有系统 SBAS-InSAR 结果 catalog。
- 任务失败、结果缺失、输入不足、DEM 缺失和授权异常时错误码明确。
### 14.4 PS-InSAR 可选验收
如采购包含 PS-InSAR
- 使用供应商建议的最小 LT-1 数据景数完成 PS 样例处理。
- 输出结果语义明确。
- 输出点/栅格产品可被 GIS 软件打开。
- 系统能归档结果和日志。
## 15. 供应商需确认问题
请供应商在报价或技术响应中明确回答以下问题:
1. API 服务是 HTTP、消息队列,还是二者都支持?
2. API 服务是否可本地离线部署?
3. 默认监听端口是多少,是否可配置?
4. 是否提供 OpenAPI / Swagger 文档?
5. 是否支持 LT-1 原始产品直接输入?
6. 是否支持已导入的 `LT1*_SLC.xml + LT1*_SLC.tif` 输入?
7. 预处理是否包含正射校正或地理编码?
8. D-InSAR 输出的 LOS 形变单位和正负号约定是什么?
9. 是否支持垂直向形变?
10. 是否支持 GACOS 或其他大气改正?
11. SBAS-InSAR 是否已产品化支持 LT-1?最小建议景数是多少?
12. PS-InSAR 是否已产品化支持 LT-1
13. 支持的最大并发任务数是多少?
14. 是否支持任务取消?
15. 是否支持断点续跑?
16. 是否支持服务重启后恢复任务状态?
17. 授权服务如何部署,是否支持无加密狗本地授权服务?
18. 授权模块是否区分预处理、D-InSAR、SBAS、PS
19. 是否提供示例数据和验收报告?
20. 是否提供二次开发技术支持?
## 16. 采购实施建议
建议采用“两个必选服务模块、分阶段实施验收”的方式推进:
### 第一阶段:D-InSAR 服务接入
必须交付:
- LandSAR API 服务。
- LT-1 D-InSAR API。
- 任务状态、日志、结果和错误码接口。
- D-InSAR 示例数据验收。
### 第二阶段:SBAS-InSAR
必须交付:
- LT-1 SBAS-InSAR API。
- 多景时序输入。
- 时序结果输出。
- 结果语义说明和系统入库适配。
- SBAS-InSAR 示例数据验收。
### 第三阶段:PS-InSAR
可选扩展:
- LT-1 PS-InSAR API。
- PS 点结果输出。
- 点位时序曲线输出。
- 监测点分析接口。
## 17. 本系统侧预计改造内容
采购 LandSAR API 服务后,现有系统侧需要进行以下改造:
1. 新增 LandSAR API 客户端模块。
2. 新增 API 服务健康检查。
3. 新增 D-InSAR 服务版处理器分支。
4. 新增 SBAS-InSAR 服务版处理器分支。
5. 新增 LandSAR API job_id 与系统 task_id/run_id 的绑定关系。
6. 新增 LandSAR 结果 manifest 解析。
7. 新增错误码映射。
8. 新增前端参数页和任务监控展示。
9. 新增中间文件清理策略。
10.`processor_code` 适配 D-InSAR 与 SBAS-InSAR 结果 catalog。
## 18. 当前建议结论
本次采购应要求供应商交付“可本地部署、可 API 调用、可异步任务化”的 LandSAR 服务版 D-InSAR 与 SBAS-InSAR 两个模块。D-InSAR 与 SBAS-InSAR 均应作为强制响应项和验收项,PS-InSAR 可作为可选扩展项。
原因是:
- 现有系统已经具备 D-InSAR 和 SBAS-InSAR 生产调度、结果 catalog 和前端展示入口。
- D-InSAR 是成对影像生产流程,结果需进入现有 D-InSAR 结果管理。
- SBAS-InSAR 是多景时序生产流程,结果需进入现有 SBAS-InSAR 结果 catalog。
- 两类服务应共享统一任务状态、日志、错误码、结果 manifest 和授权健康检查接口。
- PS-InSAR 输出形态和业务展示方式与 SBAS/D-InSAR 差异较大,可在 D-InSAR 与 SBAS-InSAR 服务稳定后扩展。
建议招标时将“D-InSAR API + SBAS-InSAR API + 服务部署授权 + 任务状态/日志/结果/错误码接口”列为必须响应项,将“独立预处理 API、PS-InSAR API、GPU 加速、断点续跑、第三方消息队列”列为可选响应项。
+2
View File
@@ -139,6 +139,8 @@ AOI 模式处理逻辑:
`center_bucket``receiving_station` 是内部诊断字段,不作为用户生产入口展示。
2026-06-09 修正:候选序列发现不再把 `center_bucket` 作为 strict 模式的硬分组字段。此前全库查找会按中心点小格拆成大量小序列,1500 景 LT-1 数据里最大候选只有 7 景;现在 strict 和 aoi 都先按同卫星/同模式/同相对轨道/同方向/同极化形成观测组,再按 footprint 公共重叠聚类。实际验证:全库 LT-1 候选从最大 7 景恢复到 32/29/28 景级别;牡丹江 AOI 候选也能返回 32/29/26 景级别。
## 6. 产物契约
一次完成的 SBAS Run 是一个结果产品包。核心资产包括:
@@ -0,0 +1,454 @@
# SBAS-InSAR Gamma 实现与专家文档对照审阅记录
审阅日期:2026-06-03
审阅对象:
- 专家文档:`D:\Code\Insar_management_system_v2\LT1_GAMMA_SBAS_逐命令处理流程.docx`
- 当前实现:`backend/app/services/sbas_insar_production_service.py`
- 当前入库:`backend/app/services/sbas_insar_catalog_service.py`
- 样本 Run`backend/runtime/sbas_insar_production/runs/sbas_7537cc71c998`
## 1. 审阅结论
当前 SBAS-InSAR Gamma 实现不能视为专家文档的逐命令复刻。
它更接近“参考专家文档后形成的 Gamma/PyINT 混合生产链路”。这条链路曾跑出完整产物,但从专家文档一致性、结果验收语义和空间范围表达看,存在需要优先修正的问题。专家反馈“结果和实现路径有问题”,从代码和样本产物看是有依据的。
核心判断:
1. 生产坐标系中的 RDC/SAR 栅格本身是矩形。
2. 系统展示和入库使用的是地理坐标 bbox/GeoTIFF,而不是 SAR 坐标矩形。
3. 当前把“发现阶段影像范围”“最终地理编码外包矩形”“最终有效像元范围”混在一起,容易造成范围和质量误判。
4. 样本 Run 的 DEM 没有覆盖完整 stack bbox,但仍被标记为 ready,这是结果边缘异常和黑边风险的直接原因。
## 2. 专家文档主流程
专家文档的 LT-1 Gamma SBAS 主链路可以概括为:
```text
par_LT1_SLC
ORB_filt_spline.py
multi_look
dem_import / fill_gaps
gc_map2 / pixel_area / create_diff_par / offset_pwrm / offset_fitm / gc_map_fine / geocode
create_offset / init_offset_orbit / init_offset / offset_pwr / offset_fit / SLC_interp
mk_mli_all
base_calc / base_plot / mk_diff_2d
mk_adf_2d / ave_image / rascc_mask / mk_unw_2d
quad_fit / quad_sub / atm_mod_2d / fill_gaps / atm_sim_2d / sub_phase
mb / unw_to_cpx / unw_model / mb / mb
replace_values / mask_data / dispmap / ts_rate
geocode_back / data2geotiff / disp_prt_2d
```
专家文档强调正式运行前必须用实际数据替换日期、极化、宽度、行数、DEM 宽度、种子点、阈值和小基线阈值,并用 `grep``SLC_corners`、显示检查命令进行核对。
## 3. 当前实现主流程
当前系统实现的主要阶段是:
```text
01_baseline_audit.sh
02_coreg_common_ref.sh
03_prepare_rdc_dem.sh
04_diff_unwrap_common_ref.sh
05_detrend_atm.sh
05_mb_ts_rate.sh
07_publish_products.sh
08_point_timeseries.sh
```
实现入口集中在:
- `backend/app/services/sbas_insar_production_service.py`
- `backend/app/services/job_handlers.py`
- `deploy/wsl/runners/gamma_sbas_product_tools.py`
当前文档化的 stage 名称与专家文档相近,但部分脚本内部命令不是专家文档原命令序列。
## 4. 主要问题
### 4.1 DEM 允许只覆盖中心点,不强制覆盖完整 stack
严重级别:高
当前 DEM 选择逻辑允许以下任一条件成立即保留 DEM:
```python
self._bbox_contains(coverage, stack_bbox, margin_degrees=0.05)
or self._bbox_contains_point(coverage, self._stack_center(stack_manifest), margin_degrees=0.05)
```
位置:
- `backend/app/services/sbas_insar_production_service.py::_resolve_rdc_dem_source`
样本 Run `sbas_7537cc71c998` 的证据:
```json
"covers_stack_bbox": false,
"covers_stack_center": true,
"stack_bbox": {
"min_lon": 128.7690438245,
"min_lat": 43.7486321624,
"max_lon": 129.6293024728,
"max_lat": 44.3582486206
}
```
同一 Run 的 DEM coverage
```json
"coverage": {
"min_lon": 127.99998768,
"max_lon": 130.99998756,
"min_lat": 44.00000064,
"max_lat": 46.000000560000004
}
```
也就是说,stack 南界到 `43.7486`DEM 南界只到约 `44.0000`。这会造成南侧边缘缺失、NoData、黑边或地理编码结果范围不足。
当前 summary 仍显示:
```json
"ready": true
```
这是验收逻辑漏洞。
建议:
- DEM 选择必须强制 `covers_stack_bbox=true`,并增加安全缓冲。
- 如果 DEM 不覆盖完整 stack,应直接阻断 RDC DEM 阶段,不允许标记 ready。
- `selection_note` 不应写“covering the SBAS stack extent”,除非确实覆盖完整 stack bbox。
### 4.2 干涉和解缠命令链与专家文档不一致
严重级别:高
专家文档:
```text
mk_diff_2d
mk_adf_2d
ave_image
rascc_mask
mk_unw_2d
```
当前实现:
```text
create_offset
phase_sim_orb
SLC_diff_intf
adf
cc_wave
rascc_mask
mcf
```
位置:
- `backend/app/services/sbas_insar_production_service.py::_write_interferogram_script`
这不是简单命令名称不同,而是处理策略不同。当前链路可能可以跑通,但不能直接说“与专家逐命令流程一致”。如果专家按文档检查结果,当前实现路径会对不上。
建议:
- 保留当前混合链路时,应将 profile 标记为 `lt1_gamma_sbas_hybrid``experimental`
- 新增严格专家链路 profile,例如 `lt1_gamma_sbas_expert_v1`,按专家文档生成 `mk_diff_2d/mk_adf_2d/mk_unw_2d` 脚本。
### 4.3 SBAS 反演缺少专家文档中的二次修正链路
严重级别:高
专家文档在第一次 `mb` 后包含:
```text
unw_to_cpx
unw_model
mb
mb
```
当前实现基本是:
```text
mb
ts_rate
```
位置:
- `backend/app/services/sbas_insar_production_service.py::_write_ipta_timeseries_script`
这会影响 2π 跳变修正、最终反演稳定性和专家验收一致性。
建议:
- 明确把第一次 `mb`、模型辅助解缠修正、第二次 `mb`、最终 `mb` 分成独立可审计步骤。
- 每次 `mb` 输出都应记录输入列表、`itab`、参考点、窗口、阈值和输出统计。
### 4.4 配准实现不是专家文档的显式逐命令配准
严重级别:中高
专家文档配准链:
```text
create_offset
init_offset_orbit
init_offset
offset_pwr
offset_fit
SLC_interp
```
当前实现调用:
```text
SLC_coreg.py --init_offset
```
位置:
- `backend/app/services/sbas_insar_production_service.py::_write_coregistration_script`
如果 `SLC_coreg.py` 内部等价,仍需要把内部日志和参数展开到系统审计里。否则专家无法按逐命令流程核对。
建议:
- 专家链路 profile 中显式生成 `create_offset/init_offset_orbit/init_offset/offset_pwr/offset_fit/SLC_interp`
- 混合链路可以保留 `SLC_coreg.py`,但必须与专家链路区分。
### 4.5 DEM 查找表链路与专家文档不一致
严重级别:中
专家文档:
```text
dem_import
fill_gaps
gc_map2
pixel_area
create_diff_par
offset_pwrm
offset_fitm
gc_map_fine
geocode
```
当前实现:
```text
复用已有 Gamma DEM cache
replace_values
gc_map1
geocode
create_diff_par
init_offsetm
offset_pwrm
offset_fitm
gc_map_fine
geocode
```
位置:
- `backend/app/services/sbas_insar_production_service.py::_write_rdc_dem_script`
当前方式可能是工程上可行的,但与专家文档命令链不一致;同时 DEM 覆盖检查还存在高风险漏洞。
建议:
- 专家链路 profile 中按文档执行 `dem_import/gc_map2/pixel_area`
- 混合链路继续使用 DEM cache 时,必须加强 DEM 覆盖、坐标、分辨率、NoData 验收。
### 4.6 入库和展示范围来自 stack 元数据,不是最终产品有效范围
严重级别:中
当前 geographic coverage 构造来自 stack scenes 的 metadata bbox
- `backend/app/services/sbas_insar_production_service.py::_build_stack_geographic_coverage`
入库时使用该 coverage 写入:
- `min_lon`
- `min_lat`
- `max_lon`
- `max_lat`
- `geom`
- `coverage_polygon`
位置:
- `backend/app/services/sbas_insar_catalog_service.py::_build_product`
这意味着系统中展示的是“发现阶段影像范围”,不是最终 GeoTIFF 的真实 footprint,更不是最终有效像元 footprint。
样本 Run 的最终 GeoTIFF `los_rate_toward_mm_per_year.tif` 信息:
```text
Size is 966, 435
Origin = (128.790404333349983,44.362917266649994)
Pixel Size = (0.000833333300000,-0.000833333300000)
Upper Left = (128.7904043, 44.3629173)
Lower Right = (129.5954043, 44.0004173)
NoData Value=0
```
而 stack bbox 是:
```json
{
"min_lon": 128.7690438245,
"min_lat": 43.7486321624,
"max_lon": 129.6293024728,
"max_lat": 44.3582486206
}
```
两者明显不同。
建议:
- 入库时从主 GeoTIFF 读取外包矩形、CRS、transform 和 NoData。
- 另行计算有效像元 footprint,或至少计算有效像元 bbox。
- 前端明确区分:
- stack metadata footprint
- RDC/SAR processing grid
- geocoded raster extent
- valid-pixel footprint
### 4.7 质量统计把 0 当成有效值
严重级别:中
当前 `_gamma_float32_stats` 使用 finite 像元作为 `valid_count`,只额外记录 `nonzero_count`。但 GeoTIFF 明确 `NoData Value=0`,因此黑边或无效像元会被 `valid_count` 掩盖。
位置:
- `backend/app/services/sbas_insar_production_service.py::_gamma_float32_stats`
样本质量统计:
```json
"pixel_count": 11480259,
"valid_count": 11480259,
"nonzero_count": 1956770
```
`nonzero_count` 只占约 17%,但 `valid_count` 却是 100%。这会误导验收。
建议:
- 对最终产品统计必须把 NoData 排除。
- 对 RDC 中间文件可以同时报告:
- finite_count
- nonzero_count
- nodata_count
- valid_pixel_ratio
- valid_bbox
- `ready` 不应只看文件尺寸和 finite 统计。
## 5. SAR 坐标矩形问题
专家反馈“SAR 坐标应该是矩形”,需要拆成两个层次理解。
### 5.1 处理坐标
RDC/SAR 处理网格应该是规则矩形。
样本 Run 中:
```json
"reference_geometry": {
"range_samples": 2693,
"azimuth_lines": 4263,
"expected_float32_bytes": 45921036
}
```
RDC 文件大小匹配 `2693 * 4263 * 4`,说明处理中间产品本身是矩形栅格。
### 5.2 展示和入库坐标
系统前端和 catalog 当前展示的是 EPSG:4326 的地理 bbox 或 scene bbox,不是 SAR 坐标矩形。
地理编码后的 GeoTIFF 是经纬度网格矩形,但有效像元可能因为 SAR 覆盖、DEM 覆盖、查找表外推、NoData 而不是满矩形。前端如果只画地理 bbox,会让用户误以为整块都有效。
### 5.3 结论
当前问题不是“RDC 文件不是矩形”,而是系统把以下内容混用了:
1. SAR/RDC 处理矩形。
2. 原始 scene metadata bbox。
3. stack 多景 bbox union/intersection。
4. 最终 GeoTIFF 地理外包矩形。
5. 最终有效像元 footprint。
建议把这些空间语义拆开保存和展示。
## 6. 建议整改路线
### 第一阶段:先修验收与范围表达
目标:不改变核心 Gamma 命令,先避免错误结果被标记为 ready。
1. DEM 必须完整覆盖 stack bbox,加缓冲;否则阻断。
2. `rdc_dem_summary.ready` 必须检查 DEM coverage。
3. `publish_product_summary` 读取主 GeoTIFF 的真实 extent、NoData、valid pixel ratio。
4. catalog 入库优先使用主 GeoTIFF extent 和 valid footprint,而不是 stack metadata bbox。
5. 前端展示拆分为“数据发现范围”和“产品有效范围”。
### 第二阶段:建立专家文档严格链路
目标:给专家可逐命令审计的生产路径。
新增 profile
```text
lt1_gamma_sbas_expert_v1
```
特性:
- 按专家文档 12 节生成脚本。
- 每节脚本命令、输入、输出、日志与专家文档一一对应。
- 保留当前混合链路,但命名为 hybrid/experimental,不再和专家链路混称。
### 第三阶段:结果质量验收
目标:形成可解释的质量结论。
建议增加:
- DEM 覆盖检查。
- RDC 栅格尺寸检查。
- GeoTIFF extent 检查。
- NoData/valid-pixel ratio 检查。
- 相干性统计。
- 每对干涉图解缠覆盖率。
- `mb` 输入层数、有效像元、参考点窗口记录。
- LOS 速度范围和 sigma 分布阈值告警。
## 7. 当前不建议的做法
1. 不建议继续把当前链路称为“专家文档逐命令链路”。
2. 不建议只看产物文件存在和文件大小判断成功。
3. 不建议用 stack metadata bbox 代表最终产品有效范围。
4. 不建议把 0 NoData 统计为有效像元。
5. 不建议在 DEM 未覆盖完整 stack 的情况下继续标记 ready。
## 8. 后续需要专家确认的问题
1. 是否要求严格使用专家文档中的 `mk_diff_2d/mk_adf_2d/mk_unw_2d`,还是允许保留 `SLC_diff_intf/adf/mcf` 混合链路。
2. DEM 来源是否必须每次从 GeoTIFF 通过 `dem_import` 重新导入,还是允许复用 Gamma DEM cache。
3. `mb` 的三次反演和 `unw_model` 修正是否必须进入正式链路。
4. 参考点 `R_REF/A_REF`、窗口、阈值是否由系统自动选择,还是必须由专家人工确认。
5. 最终业务展示默认应展示 SAR/RDC 矩形、GeoTIFF extent,还是有效像元 footprint。
@@ -0,0 +1,541 @@
# Sentinel-1 Gamma SBAS 无拼接接入设计
最后更新:2026-06-02
本文设计 `sbas-insar-production` 对 Sentinel-1 Gamma SBAS 的稳定接入方案。目标是复用现有 SBAS 生产管理框架,但不影响现有 LT-1 Gamma SBAS 链路;允许传感器专用逻辑冗余实现,以稳定性和可回退为第一优先级。
## 1. 术语说明
本文目标是 Sentinel-1 SAR 数据,不是 Sentinel-2。
Sentinel-2 是光学卫星,不具备 SAR 干涉相位,不能迁移到 Gamma SBAS-InSAR。如果后续业务说“哨兵2”,需要先确认是不是口误;系统实现应使用 `Sentinel-1``S1``s1_gamma_sbas` 这些明确命名,避免把 Sentinel-2 暗含进 InSAR 链路。
## 2. 设计结论
当前 Gamma SBAS 核心是 LT-1 专用实现,包含 LT-1 目录扫描、LT-1 元数据解析、LT-1 精轨脚本和 `par_LT1_SLC` 导入脚本。Sentinel-1 不应在这条链上硬改。
新增 Sentinel-1 支持时采用 profile 并列方案:
```text
lt1_gamma_sbas # 现有链路,保持行为不变
s1_gamma_sbas # 新增链路,独立发现、独立脚本、独立校验
```
复用内容:
- API 路由和生产 Run 生命周期。
- Stack discovery / audit / create run 的外层流程。
- Workflow/job 调度、日志、状态机。
- Gamma 环境注入和 WSL runtime 管理。
- 产品发布、catalog、预览、监测点、下载接口。
不复用或只抽象复用的内容:
- 不复用 LT-1 场景扫描。
- 不复用 LT-1 SLC 导入脚本。
- 不复用 LT-1 精轨处理脚本。
- 不复用 LT-1 专家文档中的传感器专有命令。
- 不在 LT-1 脚本模板中加入 Sentinel-1 分支。
## 3. 目标与非目标
### 3.1 目标
1. 新增 Sentinel-1 Gamma SBAS profile,入口可发现 Sentinel-1 候选 stack。
2. Sentinel-1 使用 ZIP/SAFE + EOF 资产,不走 LT-1 `tiff/meta.xml/txt orbit` 逻辑。
3. 不支持拼接。第一阶段只支持单轨、同向、同 relative orbit、同 acquisition mode、同 polarization、同 subswath、同 burst 或同一稳定 burst key 的 stack。
4. 对需要拼接才能覆盖 AOI 的数据,系统不自动拼接,改为拆成多个独立候选 stack 或直接标记为 `NOT_READY_REQUIRES_STITCHING`
5. LT-1 现有生产效果不变,默认入口仍可继续跑现有 LT-1 数据。
6. Sentinel-1 先做严格、保守、可解释的生产链,允许代码冗余,避免为了共用而引入隐性耦合。
### 3.2 非目标
1. 不支持 Sentinel-2 光学时序。
2. 不支持跨轨、跨 relative orbit、升降轨混合。
3. 不支持跨 swath 拼接。
4. 不支持跨 burst 拼接。
5. 不支持相邻 Sentinel-1 slice/frame 自动拼接。
6. 不把多个独立 Sentinel-1 SBAS 结果镶嵌成一张最终产品。
7. 不改现有 LT-1 专家文档脚本的含义和输出。
## 4. 当前 LT-1 链路中不能直接复用的点
当前实现里有多处 LT-1 硬编码:
```text
_iter_lt1_scene_dirs
_looks_like_lt1_scene_dir
_parse_lt1_scene
par_LT1_SLC
LT1_precision_orbit.py
Prepare LT1 SLCs
LT1_GAMMA_SBAS_逐命令处理流程.docx
layout_source = LT1_GAMMA_SBAS_expert_document
allowed_operations = lt1_gamma_sbas_workflow / lt1_gamma_sbas_step
```
这些不应扩展成大量 `if sensor == "S1"` 分支。否则 LT-1 的稳定链路会被 Sentinel-1 的 TOPS/burst 复杂性污染。
## 5. 总体架构
新增一个传感器 profile 适配层。现有 `SbasInsarProductionService` 保持外层协调角色,传感器专有逻辑下沉到 adapter。
建议模块:
```text
backend/app/services/sbas_profiles/
__init__.py
base.py
lt1_gamma_sbas_profile.py
s1_gamma_sbas_profile.py
backend/app/services/sbas_script_templates/
lt1_gamma_sbas_scripts.py
s1_gamma_sbas_scripts.py
```
核心接口建议:
```python
class GammaSbasProfile:
profile_code: str
sensor_family: str
def discover_scenes(source_roots, orbit_roots, filters) -> SceneDiscoveryResult: ...
def group_stack_candidates(scenes, aoi, options) -> list[StackCandidate]: ...
def audit_stack(stack_id, context) -> StackAudit: ...
def build_run_manifest(stack, options) -> dict: ...
def build_workflow_manifest(run_dir, run_manifest, options) -> dict: ...
def materialize_scripts(run_dir, workflow_manifest) -> list[ScriptArtifact]: ...
def validate_no_stitch_policy(stack) -> list[Issue]: ...
```
LT-1 profile 可以先只是封装现有函数,不改变行为。Sentinel-1 profile 独立实现。
## 6. API 和配置
### 6.1 API 参数
现有接口保持兼容,新增可选 `profile_code`
```json
{
"profile_code": "lt1_gamma_sbas",
"source_roots": [],
"orbit_roots": [],
"admin_region": "",
"discovery_mode": "strict",
"aoi_bbox": null
}
```
默认值为 `lt1_gamma_sbas`。这样老前端和老调用不受影响。
新增 Sentinel-1 时使用:
```json
{
"profile_code": "s1_gamma_sbas",
"source_roots": ["D:\\Sentinel1_Image_Pool_ZIP"],
"orbit_roots": ["D:\\Sentinel1_Orbit_Pool"],
"admin_region": "..."
}
```
### 6.2 配置项
新增配置建议:
```text
GAMMA_SBAS_PROFILES=lt1_gamma_sbas,s1_gamma_sbas
GAMMA_SBAS_DEFAULT_PROFILE=lt1_gamma_sbas
GAMMA_SBAS_S1_ENABLED=false
GAMMA_SBAS_S1_SOURCE_ROOTS=D:\Sentinel1_Image_Pool_ZIP
GAMMA_SBAS_S1_ORBIT_ROOTS=D:\Sentinel1_Orbit_Pool
GAMMA_SBAS_S1_NO_STITCH=true
GAMMA_SBAS_S1_MIN_SCENES=8
GAMMA_SBAS_S1_DEFAULT_SUBSWATH=IW2
GAMMA_SBAS_S1_DEFAULT_POLARIZATION=VV
```
`GAMMA_SBAS_S1_ENABLED` 初始应为 `false`。完成样本验证后再开放。
### 6.3 Runtime 白名单
`wsl_runtime_registry.py` 需要新增 operation
```text
s1_gamma_sbas_workflow
s1_gamma_sbas_step
```
不要复用 `lt1_gamma_sbas_workflow` 的 operation 名称。
## 7. Sentinel-1 数据发现与分组
### 7.1 数据来源
优先复用资产库存层:
- Sentinel-1 ZIP / SAFE 源产品资产。
- Sentinel-1 EOF 精密轨道资产。
- `logical_product_uid` 关联 ZIP 和 SAFE。
- EOF 使用 validity window 匹配 scene。
如果资产库存不可用,S1 profile 可提供只读目录扫描兜底,但目录扫描结果必须写入同样的 `SceneDescriptor` 结构。
### 7.2 SceneDescriptor
Sentinel-1 scene 描述结构至少包含:
```json
{
"sensor_family": "S1",
"satellite": "S1A",
"product_type": "SLC",
"acquisition_mode": "IW",
"polarization": "VV",
"orbit_direction": "ASCENDING",
"relative_orbit": "40",
"absolute_orbit": "...",
"start_time_utc": "...",
"stop_time_utc": "...",
"source_archive_path": "...zip",
"safe_dir": "...SAFE",
"manifest_path": "...manifest.safe",
"orbit_file_path": "...EOF",
"footprint": {},
"available_subswaths": ["IW1", "IW2", "IW3"],
"burst_index_summary": {}
}
```
### 7.3 Stack 分组规则
Sentinel-1 stack candidate 必须满足:
1.`sensor_family = S1`
2.`acquisition_mode = IW`
3.`orbit_direction`
4.`relative_orbit`
5. 同 polarization,第一阶段建议只支持 `VV`
6. 所有 scene 都有匹配 EOF。
7. 所有 scene 与 AOI 有交集。
8. 能解析出共同 subswath 和 burst key。
9. 不需要跨 swath/burst/相邻 slice 拼接。
不满足第 8、9 条时,不应尝试自动修复,直接输出:
```text
status = NOT_READY_REQUIRES_STITCHING
```
或者拆成多个候选:
```text
s1_rel040_asc_iw2_burst_013
s1_rel040_asc_iw2_burst_014
```
每个候选独立生产,不做最终合成。
## 8. 无拼接策略
本文中的“不支持拼接”定义如下:
1. 不把相邻 Sentinel-1 产品 slice 合成一个输入。
2. 不把多个 subswath 合成一个输入。
3. 不把多个 burst 的结果合成一个输出。
4. 不把多个独立 SBAS run 的 GeoTIFF 合成一个产品。
第一阶段最稳策略是 `single_subswath_single_burst`
```text
stack geometry = relative orbit + direction + IW subswath + burst key
```
如果 AOI 跨多个 burst,系统给出多个独立候选。用户可以分别生产和查看,但系统不拼接。
这样牺牲覆盖范围,但能显著降低 TOPS 拼接、边界相位、burst overlap 和几何一致性的风险。
## 9. Sentinel-1 Workflow 阶段
新增 Sentinel-1 专用 workflow 模板,不修改 LT-1 模板。
建议阶段:
```text
01_workspace_data
02_import_s1_slc
03_select_single_burst
04_reference_mli
05_baseline_audit
06_coregister_scenes
07_rdc_dem
08_diff_network
09_filter_unwrap
10_detrend_atm
11_sbas_inversion
12_publish_products
13_monitor_points
```
与 LT-1 的主要差异在前半段:
- LT-1`par_LT1_SLC` + LT-1 txt 精轨。
- S1ZIP/SAFE + EOF + TOPS/burst 选择。
后半段可复用 Gamma DIFF/IPTA 的思想,但脚本仍建议独立生成,避免 LT-1 和 S1 共用同一个 shell 模板。
## 10. 脚本隔离设计
LT-1 当前脚本路径保持不变:
```text
scripts/01_workspace_data.sh
scripts/02_import_lt1_slc.sh
...
```
Sentinel-1 使用独立命名:
```text
scripts/s1/01_workspace_data.sh
scripts/s1/02_import_s1_slc.sh
scripts/s1/03_select_single_burst.sh
scripts/s1/04_reference_mli.sh
...
```
`run_manifest.json` 中明确记录:
```json
{
"profile_code": "s1_gamma_sbas",
"sensor_family": "S1",
"stitching_policy": "disabled",
"stack_geometry_policy": "single_subswath_single_burst"
}
```
## 11. 产物与 Catalog
Sentinel-1 产物仍进入 SBAS catalog,但必须带 profile 和 sensor 标签:
```json
{
"catalog_name": "sbas_insar",
"product_family": "timeseries",
"processor_code": "gamma_ipta_sbas",
"profile_code": "s1_gamma_sbas",
"sensor_family": "S1"
}
```
核心资产仍保持现有约定:
```text
publish/geotiff/los_rate_toward_m_per_year.tif
publish/geotiff/los_rate_away_m_per_year.tif
publish/geotiff/los_sigma_m_per_year.tif
publish/geotiff/los_rate_toward_m_per_year.hls.geo_preview.png
publish/geotiff/los_sigma_m_per_year.cc.geo_preview.png
publish/vectors/los_rate_points.geojson.gz
publish/monitor_points/*
```
产品目录建议按 profile 分层,避免和 LT-1 混在一起:
```text
D:\production_results\timeseries\sbas
|-- lt1_gamma_sbas
| `-- <run_id>
`-- s1_gamma_sbas
`-- <run_id>
```
如果短期不改目录,也必须在 manifest/catalog 中保留 `profile_code`,前端筛选时不能只看 product family。
## 12. 前端设计
`SBAS-InSAR Production` 增加 profile 选择:
```text
数据类型:
[ LT-1 Gamma SBAS ] [ Sentinel-1 Gamma SBAS ]
```
默认仍是 LT-1。
Sentinel-1 页面提示:
```text
当前 Sentinel-1 Gamma SBAS 使用无拼接策略。
仅支持同轨同向、同 relative orbit、同 subswath、同 burst 的稳定候选序列。
跨 burst / 跨 subswath / 相邻 slice 自动拼接暂不支持。
```
候选列表增加字段:
- sensor family
- satellite
- acquisition mode
- relative orbit
- orbit direction
- polarization
- subswath
- burst key
- stitching policy
- missing EOF count
如果候选需要拼接,按钮置灰,原因显示为 `需要拼接,当前策略不支持`
## 13. 稳定性护栏
### 13.1 不影响 LT-1 的护栏
1. 默认 profile 不变。
2. LT-1 常量、模板、脚本文件名不改。
3. Sentinel-1 代码放到新 adapter 和新脚本模板中。
4. `GAMMA_SBAS_S1_ENABLED=false` 时前端不展示 S1。
5. LT-1 的单元测试和脚本快照测试必须先通过。
### 13.2 Sentinel-1 提交前校验
提交生产前必须全部通过:
```text
source ZIP/SAFE exists
EOF exists for every scene
same relative orbit
same orbit direction
same acquisition mode
same polarization
same subswath
same burst key
scene count >= minimum
no stitching required
DEM coverage exists
AOI intersects all selected scenes
```
任一失败,禁止提交 workflow job。
### 13.3 执行阶段校验
每阶段输出必须有 manifest 记录:
```text
stage_status.json
stage stdout/stderr log
expected outputs
missing outputs
quality flags
```
Sentinel-1 首批样本不自动发布到正式 catalog。建议先生成 run artifact,人工确认后再开启 publish。
## 14. 实施阶段
### Phase 0:文档和开关
- 新增本文档。
- 新增配置项设计。
- S1 默认关闭。
### Phase 1Profile 框架拆分
- 新增 `GammaSbasProfile` 基类。
- 当前 LT-1 逻辑包一层 `Lt1GammaSbasProfile`
- 保证 LT-1 行为不变。
- 增加 LT-1 脚本快照测试。
### Phase 2Sentinel-1 Discovery
- 实现 `S1GammaSbasProfile.discover_scenes`
- 优先读取 source/orbit asset inventory。
- 输出 S1 stack candidates。
- 对需要拼接的候选输出 `NOT_READY_REQUIRES_STITCHING`
### Phase 3Sentinel-1 Planning Run
- 能创建 `s1_gamma_sbas` planning run。
- 能生成 `run_manifest.json``stack_manifest.json``gamma_command_manifest.json`
- 只生成脚本,不执行 Gamma。
### Phase 4Sentinel-1 Script Dry Run
- 生成 `scripts/s1/*.sh`
- 在样本数据上执行到导入和 reference MLI。
- 验证 no-stitch 限制是否真实有效。
### Phase 5Sentinel-1 Workflow 执行
- 执行 coreg、RDC DEM、diff、unwrap、detrend、IPTA。
- 先不自动发布正式 catalog。
- 输出质量报告和人工验收包。
### Phase 6Catalog 发布和前端展示
- Sentinel-1 样本通过后开启 publish。
- 前端结果页支持 profile/sensor 筛选。
- 产品详情显示 `stitching_policy=disabled`
## 15. 验收标准
### 15.1 LT-1 回归
1. LT-1 discovery 结果不变。
2. LT-1 run manifest 关键字段不变。
3. LT-1 脚本输出与改造前一致。
4. LT-1 样本能继续跑通。
5. LT-1 catalog 结果不受 S1 profile 影响。
### 15.2 Sentinel-1 最小可用
1. 能发现 Sentinel-1 候选 stack。
2. 能绑定 EOF。
3. 能拒绝需要拼接的候选。
4. 能生成 S1 planning run 和脚本。
5. 能在一个单 subswath / 单 burst 样本上跑通 workflow。
6. 输出标准 SBAS 产品资产。
7. Catalog 中能按 `profile_code=s1_gamma_sbas` 查询。
## 16. 风险与取舍
### 16.1 覆盖范围变小
不拼接意味着 AOI 覆盖能力会变弱。跨 burst 或跨 subswath 的区域不会自动合成,只能拆成多个独立结果查看。
这是稳定性优先的取舍。
### 16.2 Sentinel-1 TOPS 复杂度高
Sentinel-1 TOPS 的 burst、Doppler、coregistration 对脚本稳定性要求高。第一阶段不应追求通用覆盖,应先让单一稳定样本跑通。
### 16.3 Gamma 命令版本差异
Sentinel-1 导入和 TOPS 处理命令需要以生产服务器安装的 Gamma 版本为准。脚本模板中所有 Sentinel-1 命令必须经过样本数据验证后再开放。
### 16.4 不共享脚本导致代码冗余
本设计接受冗余。相比强行抽象共用,冗余脚本更容易保证 LT-1 不被影响,也更容易单独回滚 Sentinel-1。
## 17. 回滚策略
如果 Sentinel-1 profile 出现问题:
1. 设置 `GAMMA_SBAS_S1_ENABLED=false`
2. 前端隐藏 Sentinel-1 profile。
3. Runtime 白名单保留不影响 LT-1。
4. 已生成的 S1 run 保留为实验记录,不进入正式 catalog。
5. LT-1 profile 不需要回滚。
## 18. 推荐下一步
1. 先实现 profile 拆分,但不改 LT-1 行为。
2. 准备一个 Sentinel-1 最小样本集:同 relative orbit、同方向、同 polarization、同 subswath、同 burst key,至少 8 景。
3. 只实现 discovery + planning run。
4. 人工核对 `gamma_command_manifest.json``scripts/s1/*.sh`
5. 再进入 Gamma 实际执行阶段。