Files
WQ_GUI/docs/SMOKE_TEST_ROUTE_B_MVP.md

351 lines
15 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Smoke Test — 路线 B MVPPipelineContext + AutoML + 软取消 + GUI 缝合)
> 适用范围:路线 B 重构 4 部分pipeline 包 / AutoML 训练器 / WorkerThread 软取消 / GUI 一键全自动)落盘后的端到端点火试飞清单。
> 目标:**用最小数据集1 个 BSQ + 1 个 CSV在 1020 分钟内验证全链路打通**。
---
## 0. 前置准备5 分钟)
### 0.1 装 Optuna
`environment.yml` 当前**未列** optuna属于本次重构新增依赖。若不装Step 6 会自动降级到老 GridSearchCV仍能跑通但会触发 fallback 日志)。
```bash
call venv\Scripts\activate.bat
pip install "optuna>=3.6,<4.0"
```
写入 `environment.yml` 的 patch提交时改
```yaml
# 路线 B AutoML 防爆引擎(可选;未装时 Step 6 走老 GridSearchCV 降级路径)
- optuna>=3.6
```
### 0.2 准备最小数据集
```text
work_dir_smoke/
├── raw/
│ ├── sample.b # 假彩色 BSQ任意小分辨率都行建议 50×50×6 波段)
│ ├── sample_mask.tif # (可选)水域掩膜;不提供则 Step 1 自动生成 NDWI
│ └── sample.csv # 含 36 个水质参数目标列Chl-a / TSS / SD / TN / TP / COD…+ 6 列波段反射率
└── (其他文件由流程自动生成)
```
**CSV 模板示例**`feature_start_column` 默认为第一列;目标列必须**在特征列之前**
```csv
Chl-a,TSS,SD,B1,B2,B3,B4,B5,B6
12.3,15.1,0.8,0.045,0.052,0.038,0.061,0.072,0.085
11.8,14.2,0.9,0.044,0.051,0.037,0.060,0.071,0.084
... (≥ 200 行AutoML 智能子采样 N>5000 时才生效)
```
### 0.3 启动 venv
```bash
cd /d "D:\111\office\ZHLduijie\1.WQ\WQ_GUI"
call venv\Scripts\activate.bat
set PYTHONPATH=src;%PYTHONPATH%
```
---
## 1. CLI 烟雾最快路径3 分钟)— **A 级:必跑**
跳过 GUI直接验证 `automl_trainer.py` 自身可独立运行 + Optuna 子采样 + 降级路径:
```bash
python -m src.core.prediction.automl_trainer ^
--csv work_dir_smoke/raw/sample.csv ^
--feature-start 6 ^
--n-trials 5 ^
--timeout 60.0 ^
--out work_dir_smoke/7_Supervised_Model_Training_AutoML
```
**通过标准**
- [ ] 进程退出码 0
- [ ] 控制台打印 `AutoML: 目标列 X 共尝试 N 个 trial最佳 CV R²=…`
- [ ] `<out>/<preprocess>/<target>_<preprocess>_<model>_AUTOML.joblib` 存在
- [ ] `<out>/automl_summary.json` 存在且 `success=true`
**若 Optuna 未装**,期待看到:
```
[AutoML] optuna 未安装,全目标列回退老 GridSearchCV
```
产物文件名带 `_AUTOML` 后缀的逻辑此时**不会触发**fallback 走老路径),属正常。
---
## 2. GUI 端到端 9 步核心场景1020 分钟)— **S 级:必跑**
### 2.1 启动 GUI
```bash
call venv\Scripts\activate.bat
set PYTHONPATH=src;%PYTHONPATH%
python -m src.gui.water_quality_gui
```
### 2.2 UI 配置
| 步骤 | 操作 | 期望 |
| ----- | -------------------------------------------------------------------- | ------------------------------------------------------------------------------------ |
| 1/9 | 点"选择工作目录" → 选 `work_dir_smoke/` | 左侧步骤列表高亮UI 不报错 |
| 2/9 | 在 Step 1 面板选 `sample.b`**掩膜留空**(验证 NDWI 自动生成路径) | 掩膜文本框保持空白 |
| 3/9 | 在 Step 4 面板选 `sample.csv` | CSV 路径显示正确 |
| 4/9 | **关键**其他步骤2/3/5/5.5/6/7/8/9保持默认不改任何参数 | AutoML 默认开启use_automl=True |
| 5/9 | 点 **▶ 运行完整流程**(不要用老 `run_full_pipeline` 槽) | 弹出**二次确认窗**,文案显示:<br>• 掩膜:`未指定(将自动生成 NDWI 水域掩膜)`<br>• 去耀斑:开启<br>• AutoML开启Optuna 子采样寻优) |
| 6/9 | 点"是(Y)" | "运行"按钮变灰,"停止"按钮亮起;进度条归零 |
### 2.3 观察日志(重点 4 大检查点)
#### ✅ 检查点 1ctx 路径传递
启动后**第一秒**应看到类似:
```
[Runner] ctx 已构造14 路径字段4 目录字段
[Runner] 步骤 1/14step1_generate_water_maskrequires=['raw_img_path', 'water_mask_path']
[Runner] 步骤 2/14step2_find_glint_arearequires=['raw_img_path', 'water_mask_path', 'output_dir']
...
[Runner] ctx 路径校准water_mask_path = ...\work_dir_smoke\2_Glint_Area_Mask\glint_mask.tif
```
**若没有 `[Runner]` 日志**,说明 v1 旧路径被走到了,**`inspect.signature` duck-type 没探测到 v2**,回去检查 `worker_thread.py:run()`
#### ✅ 检查点 2Step 1 NDWI 自动生成
```
[Step1] 未指定 mask_path自动基于 NDWI 生成水域掩膜
[Step1] NDWI 阈值=0.4,写入 1_Water_Mask/water_mask.tif
```
→ 验证 `<work_dir>/1_Water_Mask/water_mask.tif` 文件存在且非空。
#### ✅ 检查点 3AutoML 启用
```
[Step6] AutoML 启用 Optuna 子采样寻优timeout=300s, n_trials=20, max_samples=5000
[Step6] 目标列 'Chl-a' 共 3 个候选模型,最佳 R²=0.812model=RandomForest
[Step6] 目标列 'TSS' 共 3 个候选模型,最佳 R²=0.745model=XGBoost
[Step6] 训练完成,产物写入 7_Supervised_Model_Training_AutoML/
[Step6] automl_summary.json 写入完成
```
→ 验证产物:
- [ ] `7_Supervised_Model_Training_AutoML/<preprocess>/<target>_<preprocess>_<model>_AUTOML.joblib` ≥ 1 个
- [ ] `7_Supervised_Model_Training_AutoML/automl_summary.json``automl: true` 字段
- [ ] 老目录 `7_Supervised_Model_Training/` **不应该被创建**AutoML 路径独立)
#### ✅ 检查点 4AutoML 降级(仅未装 Optuna 时)
```
[AutoML] optuna 未安装,全目标列回退老 GridSearchCV
[Step6] 降级路径:调用 WaterQualityModelingBatch.train_models_batch132 组 GridSearchCV
```
→ 跑通即可(仍能产生模型文件),但**降级**属于非优选路径。
### 2.4 9 步全程观察清单
| 步 | 期望产物(路径相对 `work_dir` | 期望耗时50×50 测试数据) |
| ---- | -------------------------------------------------------------- | -------------------------- |
| 1 | `1_Water_Mask/water_mask.tif` | < 5 s |
| 2 | `2_Glint_Area_Mask/glint_mask.tif` | < 5 s |
| 3 | `3_Remove_Glint_Image/deglint_image.tif` | < 5 s |
| 4 | `4_Process_CSV/processed_data.csv` | < 2 s |
| 5 | `5_Training_Sample/training_spectra.csv` | < 5 s |
| 5.5 | `5_5_Calculate_Indices/indices.csv`如启用 | < 2 s |
| **6**| `7_Supervised_Model_Training_AutoML/`**新路径** | **< 5 minOptuna 5 trial** |
| 6.5 | `6_5_Non_Empirical_Modeling/`如启用 | 12 min |
| 6.75 | `6_75_Custom_Regression/`如启用 | 12 min |
| 7 | `7_Sampling_Points/sampling_points.csv` | < 3 s |
| 8 | `8_Prediction/predicted_values.csv` | < 5 s |
| 8.5 | `8_5_Prediction_Non_Empirical/predicted.csv`如启用 | < 5 s |
| 8.75 | `8_75_Prediction_Custom/predicted.csv`如启用 | < 5 s |
| 9 | `9_Kriging_Distribution_Map/distribution_map.tif` | 530 s Python |
### 2.5 流程结束
- [ ] 进度条到 100%
- [ ] "运行"按钮恢复可点
- [ ] "停止"按钮变灰
- [ ] 日志末行出现 `=== 流程执行完成 ===` `=== 流程被取消 ===`取决于是否点过停止
- [ ] 控制台 `on_pipeline_finished` 触发UI 状态被统一恢复
---
## 3. 软取消测试3 分钟)— **A 级:必跑**
验证 `threading.Event` 软取消链路不再用 `terminate()`)。
### 3.1 启动完整流程
2.2 启动流程
### 3.2 中途点"停止"
**时机** Step 6 AutoML trials 的中途看到 `[Step6] 目标列 'Chl-a' 共 N 个候选模型` 之后任意时刻"停止"。
**期望看到**
```
[STOP] 用户请求软取消
[Step6] 检测到 cancel_event本 trial 完成后退出
[Step6] AutoML 在 trial #X 中止,已完成 5/20 trial
[Runner] 软取消:跳过剩余 8 个 step
=== 流程被取消 ===
```
UI 状态
- [ ] "运行"按钮重新亮起
- [ ] "停止"按钮变灰
- [ ] 进度条保留在中断时的百分比****归零
- [ ] `on_pipeline_finished` 触发 `success=False, cancelled=True` 区分
- [ ] **Python 进程不退出**GUI 仍可继续点"运行"开新流程
**反例(不应该发生)**
- `QThread: Destroyed while thread is still running` 警告
- Python 解释器直接崩溃
- UI 永远卡死`run_all_btn` 一直是灰的
### 3.3 旧 `stop()` 路径回归
为防老代码忘了改临时把 `water_quality_gui.py:stop_pipeline` 改回 `self.worker.stop()`跑一次完整流程看是否出现
```
[DEPRECATED] WorkerThread.stop() 已弃用,请改用 soft_stop()。
```
**这是预期行为**弃用方法保留但打 warning流程仍能完成即视为通过
---
## 4. 失败 / 降级场景5 分钟)— **B 级:选跑**
### 4.1 未填掩膜 + NDWI 阈值设极端值
NDWI 阈值设到 `0.9`几乎无水域Step 1 应给出 warning 但不崩
```
[Step1] NDWI 阈值=0.9,水域覆盖率 < 1%,请检查影像
```
### 4.2 CSV 完全无目标列
准备一个**没有目标列的 CSV**全特征列点运行
```
[AutoML] 训练 CSV 不存在或无目标列:未识别出目标列
[Step6] AutoML 全部失败,所有目标列返回 success=False
```
UI 不会崩会在 `automl_summary.json` `error: "未识别出目标列"`
### 4.3 Step 1 路径不存在
Step 1 选了一个**不存在的 .bsq 文件**
```
[Runner] step1_generate_water_mask 异常FileNotFoundError
[STOP] 流程中止在 step 1
```
UI 弹错误窗 + 把左侧步骤列表 `setCurrentRow(0)` 自动定位到 Step 1`_focus_step` 起效)。
### 4.4 Optuna 版本冲突
装一个 `optuna==2.10`API 大改 GUI
```
[AutoML] optuna API 不兼容(>=3.6 要求):<error>
[AutoML] 全目标列回退老 GridSearchCV
```
降级路径生效即视为通过
---
## 5. 验证矩阵 Checklist
复制以下到 PR 描述 / 验收单
```markdown
## 路线 B MVP 验证矩阵
### 代码落盘
- [ ] src/core/pipeline/__init__.py17 行4 export
- [ ] src/core/pipeline/context.pyPipelineContext dataclass
- [ ] src/core/pipeline/runner.pyStepSpec + PIPELINE_STEPS + PipelineRunner
- [ ] src/core/prediction/__init__.py追加 train_with_automl export
- [ ] src/core/prediction/automl_trainer.pyAutoMLResult + train_with_automl + CLI
- [ ] src/core/steps/modeling_step.pyuse_automl 分支 + _train_models_automl
- [ ] src/core/water_quality_inversion_pipeline_GUI.pyrun_full_pipeline_v2 + LEGACY_ATTR_MAP + _sync_legacy_attrs_from_context
- [ ] src/gui/core/worker_thread.pycancel_event + soft_stop + run() duck-type
- [ ] src/gui/water_quality_gui.pyon_run_all_clicked + _collect_minimal_config + 按钮重连)
### CLI 自测
- [ ] A.1 `python -m src.core.prediction.automl_trainer --csv ...` 退出码 0
- [ ] A.2 产物 .joblib 含 `_AUTOML` 后缀
- [ ] A.3 automl_summary.json 含 success=true
### GUI 端到端
- [ ] B.1 启动无 ImportError
- [ ] B.2 二次确认窗文案含 mask 提示 + AutoML 状态
- [ ] B.3 日志含 [Runner] 前缀v2 路径生效)
- [ ] B.4 Step 1 NDWI 自动生成路径生效
- [ ] B.5 9 步产物路径全部存在
- [ ] B.6 流程结束后 UI 状态恢复(运行按钮亮、停止按钮灰)
### 软取消
- [ ] C.1 流程中途点停止cancel_event 触发
- [ ] C.2 流程被取消而非崩溃
- [ ] C.3 UI 状态由 on_pipeline_finished 统一恢复
- [ ] C.4 旧 stop() 调用打 [DEPRECATED] warning
### 降级
- [ ] D.1 Optuna 未装 → 全目标列回退老 GridSearchCV
- [ ] D.2 无目标列 CSV → 写 error 到 summary不崩 UI
- [ ] D.3 不存在文件 → _focus_step 定位到对应 step
```
---
## 6. 已知未做(不在本次范围)
- [ ] Kriging 多进程并行当前 backend="loop" Python
- [ ] Step 5 radius==0 内存优化整波段读入
- [ ] 进度条 sub-step 粒度当前只到 step
- [ ] Step 8 全图预测当前只对采样点预测
- [ ] 全项目搜替换老 `self.worker.stop()` 调用仅本会话改了 `water_quality_gui.py` stop_pipeline
- [ ] `requirements.txt` 同步 Optuna `environment.yml`
- [ ] 单元测试套件`tests/` 目录为空建议用 pytest 覆盖 train_with_automl / PipelineRunner
---
## 7. 出问题找哪里
| 现象 | 看哪里 |
| --------------------------------------------- | ------------------------------------------------------- |
| `[Runner]` 日志没出来 | `worker_thread.py:run()` `inspect.signature` 探测 |
| `[AutoML]` 完全没打 | `modeling_step.py:170` `if use_automl` 是否进了 |
| AutoML `optuna API 不兼容` | `automl_trainer.py:236` `try import` |
| 软取消无反应 | `worker_thread.py:run()` 末尾的 `cancel_event.is_set()` |
| 二次确认窗没出来 | `water_quality_gui.py:on_run_all_clicked` line ~2848 |
| 9 步产物路径错位 | `pipeline/runner.py:PIPELINE_STEPS` `output` 字段 |
| v1 路径被走到 | `_sync_legacy_attrs_from_context` 没调 v2 异常 |
---
> **作者注**:本清单对应**路线 B 一键全自动重构 4 部分全部落盘**的验收场景,编号与 todo 8 同步。
> 跑通 §1 + §2 + §3 三段即视为 MVP 验收通过§4 用于鲁棒性抽查。