Files
WQ_GUI/ARCHITECTURE.md
duxin 9e433395f4 feat: 波长偏移修正 + 项目架构文档
- BandMathCalculator 支持 wavelength_offset 参数,公式波长统一加减偏移后匹配传感器波段
- WaterQualityIndexCalculator 全链传递偏移量 (band_math → calculate_one → calculate_many)
- WaterIndexCsvProcessor / Step7Handler / DataPreparationStep 传播偏移参数
- Step7/Step10 面板新增 QDoubleSpinBox 波长偏移控件 (±200nm, 默认0)
- 偏移控件去除单位后缀,避免编辑时需手动移动光标
- 新增 ARCHITECTURE.md 完整项目架构文档
2026-06-30 13:13:38 +08:00

24 KiB
Raw Blame History

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

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.pyStep1WaterMaskHandler
后端算法 src/core/steps/water_mask_step.pyWaterMaskStep
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.pyStep2GlintDetectionHandler
后端算法 src/core/steps/glint_detection_step.pyGlintDetectionStep
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.pyStep3GlintRemovalHandler
后端算法 src/core/steps/glint_removal_step.pyGlintRemovalStep
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.pyStep4SamplingHandler
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.pyStep5ProcessCsvHandler
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.pyStep6ExtractSpectraHandler
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.pyStep7CalcIndicesHandler
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.pyStep8MlTrainHandler
后端算法 src/core/steps/modeling_step.pyModelingStep
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.pyStep9MlPredictHandler
后端算法 src/core/steps/prediction_step.pyPredictionStep
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.pyStep10QaaInversionHandler
后端算法 src/core/algorithms/waterindex_inversion.pyWaterIndexCsvProcessor
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.pyStep11ConcentrationHandler
后端算法 CSV 模式: src/core/steps/mapping_step.pyMappingStep.generate_distribution_map()GeoTIFF 模式: src/postprocessing/map.pyContentMapper.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.pyWaterQualityVisualization; src/core/visualization/scatter_plot.py; src/postprocessing/point_map.pySamplingPointMap
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.pyWaterQualityReportGenerator + 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