- BandMathCalculator 支持 wavelength_offset 参数,公式波长统一加减偏移后匹配传感器波段 - WaterQualityIndexCalculator 全链传递偏移量 (band_math → calculate_one → calculate_many) - WaterIndexCsvProcessor / Step7Handler / DataPreparationStep 传播偏移参数 - Step7/Step10 面板新增 QDoubleSpinBox 波长偏移控件 (±200nm, 默认0) - 偏移控件去除单位后缀,避免编辑时需手动移动光标 - 新增 ARCHITECTURE.md 完整项目架构文档
453 lines
24 KiB
Markdown
453 lines
24 KiB
Markdown
# WQ_GUI 水质遥感分析系统 — 架构文档
|
||
|
||
> 生成日期:2026-06-30 | 分支:Mega2.2 | 步骤数:13
|
||
|
||
---
|
||
|
||
## 一、项目总览
|
||
|
||
```
|
||
src/
|
||
├── gui/
|
||
│ ├── water_quality_gui.py # V1 入口
|
||
│ ├── water_quality_gui_v2.py # V2 入口(当前主力)
|
||
│ ├── styles.py # 全局样式 ModernStylesheet
|
||
│ ├── core/
|
||
│ │ ├── panel_registry.py # 步骤注册表
|
||
│ │ ├── panel_factory.py # 惰性加载面板工厂
|
||
│ │ ├── pipeline_executor.py # 流水线调度
|
||
│ │ ├── event_bus.py # 全局事件总线
|
||
│ │ ├── worker_thread.py # 工作线程
|
||
│ │ ├── dependency_subscriber.py # 步骤间依赖自动注入
|
||
│ │ └── workspace_initializer.py # 工作区初始化
|
||
│ ├── panels/
|
||
│ │ ├── _step_path_resolver.py # 路径解析(文件系统扫描)
|
||
│ │ ├── step1_panel.py ~ step13_report_panel.py # 13个步骤面板
|
||
│ │ └── ...
|
||
│ └── components/
|
||
│ ├── custom_widgets.py # FileSelectWidget / DirSelectWidget
|
||
│ ├── data_models.py # PandasTableModel
|
||
│ └── chart_dialogs.py # InteractiveViewerDialog 等
|
||
├── core/ # 后端处理引擎
|
||
│ ├── handlers/ # 步骤处理器(14个)
|
||
│ ├── steps/ # 步骤算法实现
|
||
│ ├── algorithms/ # 核心算法
|
||
│ └── pipeline/ # 流水线调度器
|
||
├── postprocessing/ # 后处理(可视化、地图、报告)
|
||
└── new/ # 新架构(部分迁移中)
|
||
```
|
||
|
||
---
|
||
|
||
## 二、核心架构机制
|
||
|
||
### 2.1 事件总线 (EventBus)
|
||
|
||
全局单例 `global_event_bus`,解耦面板之间及面板与调度器的通信:
|
||
|
||
| 事件名 | 发布者 | 订阅者 | 用途 |
|
||
|---|---|---|---|
|
||
| `RequestRunSingleStep` | 各面板 `run_btn` | PipelineExecutor | 单步执行 |
|
||
| `OutputUpdated` | 面板输出变化时 | 依赖订阅者 | 自动传播输出路径 |
|
||
| `PipelineStarted/Finished/Stopped` | PipelineExecutor | 全局 | 流水线生命周期 |
|
||
| `StepCompleted` | WorkerThread | 日志/UI | 单步完成通知 |
|
||
| `LogMessage` | 各处 | LogManager | 日志写入 |
|
||
| `ProgressUpdate` | WorkerThread | 进度条 | 进度更新 |
|
||
| `NavigateToTab` | 各处 | QTabWidget | 标签切换 |
|
||
| `WorkspaceChanged` | WorkspaceManager | 全局面板 | 工作目录变更 |
|
||
|
||
### 2.2 面板工厂 (PanelFactory)
|
||
|
||
惰性加载机制:启动时仅创建占位 Tab,首次切换到某 Tab 时才实例化对应 Panel。
|
||
|
||
核心方法:
|
||
- `get_panel(step_id)` → 返回面板实例(已缓存则直接返回)
|
||
- `_ensure_loaded(tab_index)` → 实例化、包装 QScrollArea、替换占位 Tab
|
||
- `_replay_state_to_panel(panel)` → 新加载的面板回放上游已产生的输出状态
|
||
|
||
### 2.3 依赖注入系统
|
||
|
||
`PANEL_REGISTRY` 中每个步骤定义 `dependencies`:
|
||
|
||
```python
|
||
dependencies = {
|
||
'target_attr': ('upstream_step_id', 'output_type', 'source_attr')
|
||
}
|
||
```
|
||
|
||
`DependencySubscriber` 监听 `OutputUpdated` 事件,自动将上游输出路径填入下游面板的对应输入控件。
|
||
|
||
`_step_path_resolver.py` 则通过文件系统扫描 + 目录映射表实现回退路径发现。
|
||
|
||
### 2.4 执行流程
|
||
|
||
```
|
||
用户点击 "独立运行步骤"
|
||
→ Panel._on_run_single_clicked()
|
||
→ EventBus.publish('RequestRunSingleStep', {step_name, config})
|
||
→ PipelineExecutor._on_request_run_single_step()
|
||
→ WorkerThread(QThread) 启动
|
||
→ PipelineScheduler.run_step(step_key, config)
|
||
→ BaseStepHandler.execute(ctx, config)
|
||
→ 实际算法逻辑
|
||
```
|
||
|
||
---
|
||
|
||
## 三、13 个步骤详解
|
||
|
||
### 模块一:影像预处理(Steps 1-3)
|
||
|
||
---
|
||
|
||
#### Step 1 — 水域掩膜生成
|
||
|
||
| 项目 | 详情 |
|
||
|---|---|
|
||
| **面板文件** | `src/gui/panels/step1_panel.py` |
|
||
| **面板类** | `Step1Panel(QWidget)` |
|
||
| **后端处理器** | `src/core/handlers/step1_water_mask.py` — `Step1WaterMaskHandler` |
|
||
| **后端算法** | `src/core/steps/water_mask_step.py` — `WaterMaskStep` |
|
||
| **UI 输入** | `mask_file`(FileSelectWidget) / NDWI 阈值模式:`ndwi_threshold`(QLineEdit, 0.0-1.0), `img_file`(FileSelectWidget) |
|
||
| **UI 输出** | `output_file`(FileSelectWidget, mode=save), `run_btn` |
|
||
| **上游依赖** | 无 |
|
||
| **产出类型** | `reference_img`, `water_mask` |
|
||
| **关键方法** | `init_ui()` → `update_ui_state()` 切换掩膜/NDWI 策略;`get_config()` 返回 `{mask_path, use_ndwi, ndwi_threshold, img_path, output_path}` |
|
||
| **目录映射** | `→ 1_water_mask` |
|
||
|
||
#### Step 2 — 耀斑检测
|
||
|
||
| 项目 | 详情 |
|
||
|---|---|
|
||
| **面板文件** | `src/gui/panels/step2_panel.py` |
|
||
| **面板类** | `Step2Panel(QWidget)` |
|
||
| **后端处理器** | `src/core/handlers/step2_glint_detection.py` — `Step2GlintDetectionHandler` |
|
||
| **后端算法** | `src/core/steps/glint_detection_step.py` — `GlintDetectionStep` |
|
||
| **UI 输入** | `img_file`(FileSelectWidget), `water_mask_file`(FileSelectWidget) |
|
||
| **UI 参数** | `glint_wave`(QDoubleSpinBox, 300-1000nm), `method`(QComboBox: Otsu/Z-Score/百分位数/IQR/自适应/多波段综合), `max_area`(QSpinBox), `buffer_size`(QSpinBox) |
|
||
| **UI 输出** | `output_file`(FileSelectWidget, mode=save), `run_btn` |
|
||
| **上游依赖** | `img_file` ← step1.reference_img; `water_mask_file` ← step1.water_mask |
|
||
| **产出类型** | `glint_mask` |
|
||
| **目录映射** | `→ 2_Glint_Detection` |
|
||
|
||
#### Step 3 — 去耀斑
|
||
|
||
| 项目 | 详情 |
|
||
|---|---|
|
||
| **面板文件** | `src/gui/panels/step3_panel.py` |
|
||
| **面板类** | `Step3Panel(QWidget)` |
|
||
| **后端处理器** | `src/core/handlers/step3_glint_removal.py` — `Step3GlintRemovalHandler` |
|
||
| **后端算法** | `src/core/steps/glint_removal_step.py` — `GlintRemovalStep` |
|
||
| **UI 输入** | `img_file`(FileSelectWidget), `water_mask_file`(FileSelectWidget) |
|
||
| **UI 参数** | `method`(QComboBox: Goodman/Kutser/Hedley/SUGAR), 4 个 StackedWidget 参数页 + `interpolate_zeros`(QCheckBox), `interp_method`(QComboBox) |
|
||
| **UI 输出** | `output_file`(FileSelectWidget), `run_btn` |
|
||
| **上游依赖** | `img_file` ← step1.reference_img; `water_mask_file` ← step1.water_mask |
|
||
| **产出类型** | `deglint_image` |
|
||
| **特殊机制** | `img_file.textChanged` → 自动调用 `_update_band_ranges()` 检测波段范围;`method.currentIndexChanged` → 切换参数 StackedWidget 页面 |
|
||
| **目录映射** | `→ 3_deglint` |
|
||
|
||
---
|
||
|
||
### 模块二:特征工程与数据(Steps 4-7)
|
||
|
||
---
|
||
|
||
#### Step 4 — 采样点布局与交互式探索
|
||
|
||
| 项目 | 详情 |
|
||
|---|---|
|
||
| **面板文件** | `src/gui/panels/step4_sampling_panel.py` |
|
||
| **面板类** | `Step4SamplingPanel(QWidget)` |
|
||
| **后端处理器** | `src/core/handlers/step4_sampling.py` — `Step4SamplingHandler` |
|
||
| **UI 输入** | `deglint_img_file`(FileSelectWidget), `water_mask_file`(FileSelectWidget) |
|
||
| **UI 参数** | `interval`(QSpinBox, 10-500px), `sample_radius`(QSpinBox, 1-50px), `chunk_size`(QSpinBox, 100-10000px), `use_adaptive_sampling`(QCheckBox) |
|
||
| **UI 输出** | `output_file`(FileSelectWidget), `refresh_btn`, `run_btn` |
|
||
| **可视化** | Matplotlib 嵌入:`FigureCanvasQTAgg` + 隐藏 `NavigationToolbar2QT`,左右分栏(散点图 + 光谱曲线),自定义工具栏按钮 |
|
||
| **交互** | `_on_hover()` 鼠标变小手 + 悬停标注;`_on_click()` 点击高亮 + 光谱绘制 + 再次点击取消选中;三按钮互斥:👆 点选探针 / ✋ 拖拽漫游 / 🔍 框选放大 |
|
||
| **上游依赖** | `deglint_img_file` ← step3.deglint_image; `water_mask_file` ← step1.water_mask |
|
||
| **产出类型** | `sampling_points` |
|
||
| **特殊机制** | `_status_timer` (5000ms) 自动检测 CSV 并重渲染;`draw_idle()` 防 UI 卡死;rcParams 中文字体双重保障 |
|
||
| **目录映射** | `→ 4_sampling` |
|
||
|
||
#### Step 5 — 数据清洗
|
||
|
||
| 项目 | 详情 |
|
||
|---|---|
|
||
| **面板文件** | `src/gui/panels/step5_clean_panel.py` |
|
||
| **面板类** | `Step5CleanPanel(QWidget)` |
|
||
| **后端处理器** | `src/core/handlers/step5_process_csv.py` — `Step5ProcessCsvHandler` |
|
||
| **UI 输入** | `csv_file`(FileSelectWidget) |
|
||
| **UI 参数** | `preview_rows_spin`(QSpinBox), `preview_table`(QTableView + PandasTableModel), `preview_status_label`(QLabel) |
|
||
| **UI 输出** | `output_file`(FileSelectWidget, mode=save), `run_btn` |
|
||
| **上游依赖** | 无(独立输入源) |
|
||
| **产出类型** | `processed_data` |
|
||
| **目录映射** | `→ 5_Data_Cleaning` |
|
||
|
||
#### Step 6 — 光谱特征提取
|
||
|
||
| 项目 | 详情 |
|
||
|---|---|
|
||
| **面板文件** | `src/gui/panels/step6_feature_panel.py` |
|
||
| **面板类** | `Step6FeaturePanel(QWidget)` |
|
||
| **后端处理器** | `src/core/handlers/step6_extract_spectra.py` — `Step6ExtractSpectraHandler` |
|
||
| **UI 输入** | `deglint_img_file`(FileSelectWidget), `csv_file`(FileSelectWidget), `water_mask_file`(FileSelectWidget), `glint_mask_file`(FileSelectWidget) |
|
||
| **UI 参数** | `radius`(QSpinBox, 1-50px), `source_epsg`(QSpinBox, default 4326) |
|
||
| **UI 输出** | `output_file`(FileSelectWidget), `run_btn` |
|
||
| **上游依赖** | `deglint_img_file` ← step3; `csv_file` ← step5; `water_mask_file` ← step1; `glint_mask_file` ← step2 |
|
||
| **产出类型** | `output_file` |
|
||
| **目录映射** | `→ 6_Spectral_Feature_Extraction` |
|
||
|
||
#### Step 7 — 水质指数计算
|
||
|
||
| 项目 | 详情 |
|
||
|---|---|
|
||
| **面板文件** | `src/gui/panels/step7_inversion_panel.py` |
|
||
| **面板类** | `Step7InversionPanel(QWidget)` |
|
||
| **后端处理器** | `src/core/handlers/step7_calc_indices.py` — `Step7CalcIndicesHandler` |
|
||
| **UI 输入** | `formula_file`(FileSelectWidget, 只读), `training_data_widget`(FileSelectWidget) |
|
||
| **UI 参数** | `category_combo`(QComboBox 按类别筛选), `formula_list`(NoScrollPassListWidget, checkable), 选择按钮:全选/清空/比值/浓度/重载 |
|
||
| **UI 输出** | `output_file`(FileSelectWidget), `run_btn` |
|
||
| **上游依赖** | `training_data_widget` ← step6_feature.output_file |
|
||
| **产出类型** | `training_spectra_indices` |
|
||
| **特殊机制** | `_load_formulas_from_csv()` 从内置公式库加载;`_update_formula_count()` 统计选中数 |
|
||
| **目录映射** | `→ 7_Water_Quality_Indices` |
|
||
|
||
---
|
||
|
||
### 模块三:模型训练与反演(Steps 8-10)
|
||
|
||
---
|
||
|
||
#### Step 8 — 机器学习建模
|
||
|
||
| 项目 | 详情 |
|
||
|---|---|
|
||
| **面板文件** | `src/gui/panels/step8_ml_train_panel.py` |
|
||
| **面板类** | `Step8MlTrainPanel(QWidget)` |
|
||
| **后端处理器** | `src/core/handlers/step8_ml_train.py` — `Step8MlTrainHandler` |
|
||
| **后端算法** | `src/core/steps/modeling_step.py` — `ModelingStep` |
|
||
| **UI 输入** | `training_csv_file`(FileSelectWidget) |
|
||
| **UI 参数** | `feature_start`(QComboBox), `cv_folds`(QSpinBox 2-10), 预处理 11 项 CheckBox(None/MMS/SS/SNV/MA/SG/MSC/D1/D2/DT/CT), 模型 15 项 CheckBox(LR/Ridge/Lasso/ElasticNet/PLS/DT/RF/ExtraTrees/XGBoost/LightGBM/CatBoost/GBDT/AdaBoost/SVR/KNN/MLP), 数据划分 3 项 CheckBox(SPXY/KS/Random) |
|
||
| **UI 输出** | `output_path`(FileSelectWidget, 目录模式), `run_btn` |
|
||
| **上游依赖** | `training_csv_file` ← step7_index.training_spectra_indices |
|
||
| **产出类型** | `output_path` |
|
||
| **目录映射** | `→ 8_Supervised_Model_Training` |
|
||
|
||
#### Step 9 — 机器学习预测
|
||
|
||
| 项目 | 详情 |
|
||
|---|---|
|
||
| **面板文件** | `src/gui/panels/step9_ml_predict_panel.py` |
|
||
| **面板类** | `Step9MlPredictPanel(QWidget)` |
|
||
| **后端处理器** | `src/core/handlers/step9_ml_predict.py` — `Step9MlPredictHandler` |
|
||
| **后端算法** | `src/core/steps/prediction_step.py` — `PredictionStep` |
|
||
| **UI 输入** | `sampling_csv_file`(FileSelectWidget), `models_dir_file`(FileSelectWidget, 目录) |
|
||
| **UI 参数** | 模型来源:`use_trained_model`/`use_external_model`(QRadioButton), 外部模型 `model_list`(QListWidget, checkable), `metric`(QComboBox: R²/RMSE/MAE), `prediction_column`(QLineEdit) |
|
||
| **UI 输出** | `output_file`(FileSelectWidget, 目录), `run_btn` |
|
||
| **上游依赖** | `models_dir_file` ← step8_ml_train.output_path |
|
||
| **产出类型** | `output_file` |
|
||
| **目录映射** | `→ 9_ML_Prediction` |
|
||
|
||
#### Step 10 — 水色指数反演
|
||
|
||
| 项目 | 详情 |
|
||
|---|---|
|
||
| **面板文件** | `src/gui/panels/step10_watercolor_panel.py` |
|
||
| **面板类** | `Step10WatercolorPanel(QWidget)` |
|
||
| **后端处理器** | `src/core/handlers/step10_qaa_inversion.py` — `Step10QaaInversionHandler` |
|
||
| **后端算法** | `src/core/algorithms/waterindex_inversion.py` — `WaterIndexCsvProcessor` |
|
||
| **UI 输入** | `formula_file`(FileSelectWidget, 只读), `sampling_csv_file`(FileSelectWidget) |
|
||
| **UI 参数** | `category_combo`(QComboBox 按水质类别筛选), `formula_list`(NoScrollPassListWidget, checkable), 全选/清空/比值/浓度按钮 |
|
||
| **UI 输出** | `output_dir`(FileSelectWidget, 目录), `progress_bar`(QProgressBar), `progress_label`(QLabel), `run_btn` |
|
||
| **上游依赖** | `sampling_csv_file` ← step4_sampling.sampling_points |
|
||
| **产出类型** | `output_dir` |
|
||
| **特殊机制** | 内嵌 `WaterIndexWorker(QThread)` 后台处理 CSV |
|
||
| **目录映射** | `→ 10_WaterIndex_CSV` |
|
||
|
||
---
|
||
|
||
### 模块四:制图与成果汇编(Steps 11-13)
|
||
|
||
---
|
||
|
||
#### Step 11 — 专题图生成
|
||
|
||
| 项目 | 详情 |
|
||
|---|---|
|
||
| **面板文件** | `src/gui/panels/step11_map_panel.py` |
|
||
| **面板类** | `Step11MapPanel(QWidget)` |
|
||
| **后端处理器** | `src/core/handlers/step11_concentration.py` — `Step11ConcentrationHandler` |
|
||
| **后端算法** | CSV 模式: `src/core/steps/mapping_step.py` — `MappingStep.generate_distribution_map()`;GeoTIFF 模式: `src/postprocessing/map.py` — `ContentMapper.visualize_raster()` |
|
||
| **UI 输入** | `render_mode_combo`(QComboBox: CSV插值/GeoTIFF栅格), `batch_mode_combo`(QComboBox: 单个文件/文件夹批量), `prediction_csv_file`(FileSelectWidget), `geotiff_file`(FileSelectWidget), `boundary_file`(FileSelectWidget: *.shp) |
|
||
| **UI 参数** | `resolution`(QDoubleSpinBox, 1-1000), `input_crs`/`output_crs`(QLineEdit, EPSG:32651), `show_points`(QCheckBox), `use_diffusion`(QCheckBox) |
|
||
| **UI 输出** | `output_dir`(FileSelectWidget), `progress_bar`(QProgressBar), `run_button` |
|
||
| **上游依赖** | `prediction_csv_dir_edit` ← step9; `geotiff_dir_edit` ← step10; `boundary_file` ← step1.water_mask |
|
||
| **特殊机制** | 两个后台线程:`Step11MapBatchThread`(CSV) / `Step11GeoTIFFBatchThread`(GeoTIFF) |
|
||
| **目录映射** | `→ 14_visualization` |
|
||
|
||
#### Step 12 — 可视化
|
||
|
||
| 项目 | 详情 |
|
||
|---|---|
|
||
| **面板文件** | `src/gui/panels/step12_viz_panel.py` |
|
||
| **面板类** | `Step12VizPanel(QWidget)` |
|
||
| **后端算法** | `src/postprocessing/visualization_reports.py` — `WaterQualityVisualization`; `src/core/visualization/scatter_plot.py`; `src/postprocessing/point_map.py` — `SamplingPointMap` |
|
||
| **UI 输入** | `work_dir_edit`(QLineEdit), `img_dir_edit`(QLineEdit) |
|
||
| **UI 参数** | 6 个 QCheckBox: `gen_scatter`(模型评估散点图), `gen_spectrum`(光谱曲线), `gen_boxplots`(统计图), `gen_mask_glint`(掩膜缩略图), `gen_sampling_map`(采样点地图), `gen_distribution_map`(空间分布图) |
|
||
| **UI 输出** | `gen_all_btn`(QPushButton), `scan_btn`(QPushButton), `ImageCategoryTree`(QTreeWidget), `ImageViewerWidget`(带缩放/平移/保存), 筛选: `view_mode_cb` + `chart_filter_cb` |
|
||
| **上游依赖** | 无(文件系统自动扫描) |
|
||
| **产出类型** | 多种图表 PNG |
|
||
| **特殊机制** | `VisualizationWorkerThread(QThread)` 后台批量生成;`ImageCategoryTree` 三视图模式(按水质参数/图表类型/物理文件夹) |
|
||
|
||
#### Step 13 — 报告生成
|
||
|
||
| 项目 | 详情 |
|
||
|---|---|
|
||
| **面板文件** | `src/gui/panels/step13_report_panel.py` |
|
||
| **面板类** | `Step13ReportPanel(QWidget)` |
|
||
| **后端算法** | `src/postprocessing/report_word.py` — `WaterQualityReportGenerator` + `ReportGenerationConfig` |
|
||
| **UI 输入** | `work_dir_edit`(QLineEdit, 只读), `output_dir_edit`(QLineEdit + 浏览) |
|
||
| **UI 参数** | `report_title_edit`(QLineEdit), `enable_ai_cb`(QCheckBox), AI 设置按钮 → `AISettingsDialog` |
|
||
| **UI 输出** | `progress_label`(QLabel), `progress_bar`(QProgressBar), `generate_btn`(QPushButton) |
|
||
| **上游依赖** | 无(但需要 `main_window` 在构造时注入) |
|
||
| **产出类型** | Word 报告 (.docx) |
|
||
| **特殊机制** | `ReportWorkerThread(QThread)` 后台生成;AI 分析可选(需配置 API Key) |
|
||
| **目录映射** | `→ reports` |
|
||
|
||
---
|
||
|
||
## 四、步骤间数据流转图
|
||
|
||
```
|
||
Step1 水域掩膜 ─── img_file ───────────────┬──► Step2 耀斑检测 ── glint_mask ──► Step6
|
||
│ │
|
||
├── water_mask ──────────────────────┼──► Step3 去耀斑 ─── deglint ────► Step4
|
||
│ │ │ │
|
||
│ │ └───────────────────────────┤
|
||
│ │ │
|
||
│ ├──► Step4 采样 ←────────────────────┘
|
||
│ ├──► Step6 特征提取
|
||
│ ├──► Step11 专题图 ───► Step12
|
||
│ └──► Step12 可视化 Step13
|
||
│
|
||
└──► Step11 专题图(边界)
|
||
|
||
Step4 采样 ── sampling_csv ──► Step10 水色指数 ── output_dir ──► Step11(GeoTIFF)
|
||
|
||
Step5 清洗 ── csv ──► Step6 特征提取 ── output ──► Step7 指数计算
|
||
│
|
||
▼
|
||
Step8 机器学习建模
|
||
│
|
||
▼
|
||
Step9 机器学习预测
|
||
│
|
||
▼
|
||
Step11 专题图(CSV)
|
||
```
|
||
|
||
---
|
||
|
||
## 五、自定义组件
|
||
|
||
### 5.1 文件选择控件
|
||
|
||
**`FileSelectWidget`** (`src/gui/components/custom_widgets.py`)
|
||
|
||
| 模式 | 行为 |
|
||
|---|---|
|
||
| `mode="open"` | `QFileDialog.getOpenFileName()` — 选择已存在文件 |
|
||
| `mode="save"` | `QFileDialog.getSaveFileName()` — 选择保存路径 |
|
||
| `mode="dir"` | `QFileDialog.getExistingDirectory()` — 选择目录 |
|
||
|
||
关键方法:`get_path()`, `set_path(path)`, `set_read_only(bool)`, `line_edit.textChanged` 信号
|
||
|
||
### 5.2 路径解析器
|
||
|
||
**`_step_path_resolver.py`** — 所有 13 个 Panel 统一通过 `from src.gui.panels._step_path_resolver import ...` 导入
|
||
|
||
| 函数 | 用途 |
|
||
|---|---|
|
||
| `resolve_subdir(work_dir, subdir_key)` | 步骤名 → 实际子目录路径 |
|
||
| `scan_work_dir_for_input(work_dir, output_type)` | 文件系统扫描发现上游输出 |
|
||
| `resolve_step_widget(main_window, step_key, widget_attr)` | 通过 panel_factory 定位上游控件 |
|
||
| `get_step_output_path(main_window, step_key, work_dir, widget_attr, fallback_key)` | 获取上游输出路径(含回退) |
|
||
|
||
### 5.3 全局样式
|
||
|
||
**`ModernStylesheet`** (`src/gui/styles.py`) — 提供 `get_button_stylesheet('normal'|'primary')`
|
||
|
||
---
|
||
|
||
## 六、关键设计模式
|
||
|
||
| 模式 | 位置 | 说明 |
|
||
|---|---|---|
|
||
| **惰性加载** | PanelFactory | Tab 切换时才实例化 Panel,降低启动时间 |
|
||
| **事件总线** | EventBus | Panel ↔ PipelineExecutor 解耦通信 |
|
||
| **依赖注入** | DependencySubscriber + PANEL_REGISTRY | 上游输出自动填入下游输入 |
|
||
| **文件系统回退** | _step_path_resolver | 当依赖注入失败时,扫描实际文件系统 |
|
||
| **独立运行** | 每个 Panel 的 `run_btn` | 不依赖全流水线,可单独执行 |
|
||
| **后台线程** | WorkerThread / 各 Panel 内嵌 QThread | 长时间计算不阻塞 GUI |
|
||
| **交互模式** | Step4 三按钮互斥 | 点选探针 / 拖拽漫游 / 框选放大 |
|
||
|
||
---
|
||
|
||
## 七、文件清单
|
||
|
||
### 前端面板(13 个)
|
||
|
||
| 文件 | 类 | Step ID |
|
||
|---|---|---|
|
||
| `step1_panel.py` | `Step1Panel` | `step1` |
|
||
| `step2_panel.py` | `Step2Panel` | `step2` |
|
||
| `step3_panel.py` | `Step3Panel` | `step3` |
|
||
| `step4_sampling_panel.py` | `Step4SamplingPanel` | `step4_sampling` |
|
||
| `step5_clean_panel.py` | `Step5CleanPanel` | `step5_clean` |
|
||
| `step6_feature_panel.py` | `Step6FeaturePanel` | `step6_feature` |
|
||
| `step7_inversion_panel.py` | `Step7InversionPanel` | `step7_index` |
|
||
| `step8_ml_train_panel.py` | `Step8MlTrainPanel` | `step8_ml_train` |
|
||
| `step9_ml_predict_panel.py` | `Step9MlPredictPanel` | `step9_ml_predict` |
|
||
| `step10_watercolor_panel.py` | `Step10WatercolorPanel` | `step10_watercolor` |
|
||
| `step11_map_panel.py` | `Step11MapPanel` | `step11_map` |
|
||
| `step12_viz_panel.py` | `Step12VizPanel` | `step12_viz` |
|
||
| `step13_report_panel.py` | `Step13ReportPanel` | `step13_report` |
|
||
|
||
### 后端核心(14 个 Handler)
|
||
|
||
| 文件 | 类 | Step Key |
|
||
|---|---|---|
|
||
| `handlers/step1_water_mask.py` | `Step1WaterMaskHandler` | `step1` |
|
||
| `handlers/step2_glint_detection.py` | `Step2GlintDetectionHandler` | `step2` |
|
||
| `handlers/step3_glint_removal.py` | `Step3GlintRemovalHandler` | `step3` |
|
||
| `handlers/step4_sampling.py` | `Step4SamplingHandler` | `step4_sampling` |
|
||
| `handlers/step5_process_csv.py` | `Step5ProcessCsvHandler` | `step5_clean` |
|
||
| `handlers/step6_extract_spectra.py` | `Step6ExtractSpectraHandler` | `step6_feature` |
|
||
| `handlers/step7_calc_indices.py` | `Step7CalcIndicesHandler` | `step7_index` |
|
||
| `handlers/step8_ml_train.py` | `Step8MlTrainHandler` | `step8_ml_train` |
|
||
| `handlers/step9_ml_predict.py` | `Step9MlPredictHandler` | `step9_ml_predict` |
|
||
| `handlers/step10_qaa_inversion.py` | `Step10QaaInversionHandler` | `step10_qaa_inversion` |
|
||
| `handlers/step11_concentration.py` | `Step11ConcentrationHandler` | `step11_concentration` |
|
||
| `handlers/step12_kriging.py` | `Step12KrigingHandler` | `step12_kriging` |
|
||
| `handlers/step13_visualization.py` | `Step13VisualizationHandler` | `step13_visualization` |
|
||
| `handlers/step14_report.py` | `Step14ReportHandler` | `step14_report` |
|
||
|
||
> 注:Handler 注册有 14 个(step1-14),对应 Panel 有 13 个(step1-13)。Step12 的 Handler 处理克里金插值,Step13 的 Handler 处理可视化,Step14 的 Handler 处理报告。
|
||
|
||
---
|
||
|
||
## 八、审计修复记录(2026-06-30)
|
||
|
||
本轮已修复的全部问题:
|
||
|
||
| # | 严重度 | 文件 | 问题 | 修复 |
|
||
|---|---|---|---|---|
|
||
| 1 | 🔴 | `step11_map_panel.py:652` | `mapper` 在 import 之前引用 | 移动 import 至引用上方 |
|
||
| 2 | 🟡 | `step12_viz_panel.py:1719` | `get_panel('step1_mask')` key 不存在 | 改为 `'step1'` |
|
||
| 3 | 🟡 | `step3_panel.py:384` | `currentData()` 返回 None | 改为 `currentText()` |
|
||
| 4 | 🟡 | `step5_clean_panel.py:228/253` | PandasTableModel 从 v1 入口导入 | 改为 `src.gui.components.data_models` |
|
||
| 5 | 🟡 | `step3_panel.py:271` | InteractiveViewerDialog 同上 | 改为 `src.gui.components.chart_dialogs` |
|
||
| 6 | 🟢 | `step7_inversion_panel.py:9` | `import csv` 未使用 | 移除 |
|
||
| 7 | 🟢 | `step5_clean_panel.py:167` | 死方法 `_add_row_with_fixed_label` | 标注废弃 |
|
||
| 8 | 🟢 | 全部 12 个 Panel | `_step_path_resolver` 导入风格不一致 | 统一为 `from src.gui.panels._step_path_resolver import ...`,移除 `_HERE`/`sys.path` hack |
|