refactor: 建立动态面板注册表,消除硬编码,实现步骤界面的数据驱动渲染与依赖路由
This commit is contained in:
253
src/gui/core/panel_registry.py
Normal file
253
src/gui/core/panel_registry.py
Normal file
@ -0,0 +1,253 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
面板注册中心
|
||||
|
||||
集中定义所有步骤面板的结构化配置,包括:
|
||||
- 步骤 ID / 类引用 / 标题 / 图标 / 阶段 / 导航显示名
|
||||
- 步骤间依赖关系(输入字段 → 上游步骤/输出类型/面板属性)
|
||||
- 构造参数(如 Step13ReportPanel 需要 main_window)
|
||||
|
||||
WaterQualityGUI 通过遍历 PANEL_REGISTRY 动态生成导航树、Tab 页、
|
||||
依赖传递和配置读写,彻底消除硬编码。
|
||||
"""
|
||||
|
||||
from src.gui.panels.step1_panel import Step1Panel
|
||||
from src.gui.panels.step2_panel import Step2Panel
|
||||
from src.gui.panels.step3_panel import Step3Panel
|
||||
from src.gui.panels.step4_sampling_panel import Step4SamplingPanel
|
||||
from src.gui.panels.step5_clean_panel import Step5CleanPanel
|
||||
from src.gui.panels.step6_feature_panel import Step6FeaturePanel
|
||||
from src.gui.panels.step7_index_panel import Step7IndexPanel
|
||||
from src.gui.panels.step8_ml_train_panel import Step8MlTrainPanel
|
||||
from src.gui.panels.step9_ml_predict_panel import Step9MlPredictPanel
|
||||
from src.gui.panels.step10_watercolor_panel import Step10WatercolorPanel
|
||||
from src.gui.panels.step11_map_panel import Step11MapPanel
|
||||
from src.gui.panels.step12_viz_panel import Step12VizPanel
|
||||
from src.gui.panels.step13_report_panel import Step13ReportPanel
|
||||
|
||||
|
||||
PANEL_REGISTRY = [
|
||||
# ═══════════════════════════════════════════════════════════════
|
||||
# 阶段一:影像预处理
|
||||
# ═══════════════════════════════════════════════════════════════
|
||||
{
|
||||
'step_id': 'step1',
|
||||
'class_ref': Step1Panel,
|
||||
'title': '水域掩膜',
|
||||
'icon': '1.png',
|
||||
'stage': '阶段一:影像预处理',
|
||||
'display_name': '1. 水域掩膜生成',
|
||||
'dependencies': None,
|
||||
'constructor_kwargs': None,
|
||||
},
|
||||
{
|
||||
'step_id': 'step2',
|
||||
'class_ref': Step2Panel,
|
||||
'title': '耀斑检测',
|
||||
'icon': '2.png',
|
||||
'stage': '阶段一:影像预处理',
|
||||
'display_name': '2. 耀斑区域识别',
|
||||
'dependencies': {
|
||||
'img_path': ('step1', 'reference_img', 'img_file'),
|
||||
'water_mask_path': ('step1', 'water_mask', 'water_mask_file'),
|
||||
},
|
||||
'constructor_kwargs': None,
|
||||
},
|
||||
{
|
||||
'step_id': 'step3',
|
||||
'class_ref': Step3Panel,
|
||||
'title': '耀斑去除',
|
||||
'icon': '3.png',
|
||||
'stage': '阶段一:影像预处理',
|
||||
'display_name': '3. 耀斑去除与修复',
|
||||
'dependencies': {
|
||||
'img_path': ('step1', 'reference_img', 'img_file'),
|
||||
'water_mask': ('step1', 'water_mask', 'water_mask_file'),
|
||||
},
|
||||
'constructor_kwargs': None,
|
||||
},
|
||||
|
||||
# ═══════════════════════════════════════════════════════════════
|
||||
# 阶段二:样本数据准备
|
||||
# ═══════════════════════════════════════════════════════════════
|
||||
{
|
||||
'step_id': 'step4_sampling',
|
||||
'class_ref': Step4SamplingPanel,
|
||||
'title': '采样点布设',
|
||||
'icon': '4.png',
|
||||
'stage': '阶段二:样本数据准备',
|
||||
'display_name': '4. 采样点布设',
|
||||
'dependencies': {
|
||||
'deglint_img_path': ('step3', 'deglint_image', 'deglint_img_file'),
|
||||
'water_mask_path': ('step1', 'water_mask', 'water_mask_file'),
|
||||
},
|
||||
'constructor_kwargs': None,
|
||||
},
|
||||
{
|
||||
'step_id': 'step5_clean',
|
||||
'class_ref': Step5CleanPanel,
|
||||
'title': '数据清洗',
|
||||
'icon': '5.png',
|
||||
'stage': '阶段二:样本数据准备',
|
||||
'display_name': '5. 数据清洗',
|
||||
# 业务要求保持输入源独立,不自动抓取 step4_sampling 的输出
|
||||
'dependencies': None,
|
||||
'constructor_kwargs': None,
|
||||
},
|
||||
{
|
||||
'step_id': 'step6_feature',
|
||||
'class_ref': Step6FeaturePanel,
|
||||
'title': '光谱特征',
|
||||
'icon': '6.png',
|
||||
'stage': '阶段二:样本数据准备',
|
||||
'display_name': '6. 光谱特征提取',
|
||||
'dependencies': {
|
||||
'deglint_img_path': ('step3', 'deglint_image', 'deglint_img_file'),
|
||||
'csv_path': ('step5_clean', 'processed_data', 'csv_file'),
|
||||
'boundary_mask_path': ('step1', 'water_mask', 'water_mask_file'),
|
||||
'glint_mask_path': ('step2', 'glint_mask', 'glint_mask_file'),
|
||||
},
|
||||
'constructor_kwargs': None,
|
||||
},
|
||||
{
|
||||
'step_id': 'step7_index',
|
||||
'class_ref': Step7IndexPanel,
|
||||
'title': '水质光谱指数计算',
|
||||
'icon': '7.png',
|
||||
'stage': '阶段二:样本数据准备',
|
||||
'display_name': '7. 水质指数计算',
|
||||
'dependencies': {
|
||||
'training_csv_path': ('step6_feature', 'training_spectra', 'training_data_widget'),
|
||||
},
|
||||
'constructor_kwargs': None,
|
||||
},
|
||||
|
||||
# ═══════════════════════════════════════════════════════════════
|
||||
# 阶段三:模型构建与训练
|
||||
# ═══════════════════════════════════════════════════════════════
|
||||
{
|
||||
'step_id': 'step8_ml_train',
|
||||
'class_ref': Step8MlTrainPanel,
|
||||
'title': '机器学习建模',
|
||||
'icon': '8.png',
|
||||
'stage': '阶段三:模型构建与训练',
|
||||
'display_name': '8. 机器学习建模',
|
||||
'dependencies': {
|
||||
'training_csv_file': ('step7_index', 'training_spectra_indices', 'training_csv_file'),
|
||||
},
|
||||
'constructor_kwargs': None,
|
||||
},
|
||||
|
||||
# ═══════════════════════════════════════════════════════════════
|
||||
# 阶段四:预测与成果输出
|
||||
# ═══════════════════════════════════════════════════════════════
|
||||
{
|
||||
'step_id': 'step9_ml_predict',
|
||||
'class_ref': Step9MlPredictPanel,
|
||||
'title': '机器学习预测',
|
||||
'icon': '10.png',
|
||||
'stage': '阶段四:预测与成果输出',
|
||||
'display_name': '9. 机器学习预测',
|
||||
'dependencies': {
|
||||
'models_dir': ('step8_ml_train', 'Supervised_Model_Training', 'models_dir_widget'),
|
||||
},
|
||||
'constructor_kwargs': None,
|
||||
},
|
||||
{
|
||||
'step_id': 'step10_watercolor',
|
||||
'class_ref': Step10WatercolorPanel,
|
||||
'title': '水色指数反演',
|
||||
'icon': '10.png',
|
||||
'stage': '阶段四:预测与成果输出',
|
||||
'display_name': '10. 水色指数反演',
|
||||
'dependencies': {
|
||||
'bsq_file': ('step3', 'deglint_image', 'bsq_file'),
|
||||
},
|
||||
'constructor_kwargs': None,
|
||||
},
|
||||
{
|
||||
'step_id': 'step11_map',
|
||||
'class_ref': Step11MapPanel,
|
||||
'title': '专题图生成',
|
||||
'icon': '10.png',
|
||||
'stage': '阶段四:预测与成果输出',
|
||||
'display_name': '11. 专题图生成',
|
||||
'dependencies': {
|
||||
'prediction_csv_dir_edit': ('step9_ml_predict', '9_ML_Prediction', 'prediction_csv_dir_edit'),
|
||||
'geotiff_dir_edit': ('step10_watercolor', 'WaterIndex_Images', 'geotiff_dir_edit'),
|
||||
},
|
||||
'constructor_kwargs': None,
|
||||
},
|
||||
{
|
||||
'step_id': 'step12_viz',
|
||||
'class_ref': Step12VizPanel,
|
||||
'title': '可视化',
|
||||
'icon': '9.png',
|
||||
'stage': '阶段四:预测与成果输出',
|
||||
'display_name': '12. 可视化展示',
|
||||
'dependencies': None,
|
||||
'constructor_kwargs': None,
|
||||
},
|
||||
{
|
||||
'step_id': 'step13_report',
|
||||
'class_ref': Step13ReportPanel,
|
||||
'title': '报告生成',
|
||||
'icon': '10.png',
|
||||
'stage': '阶段四:预测与成果输出',
|
||||
'display_name': '13. 分析报告生成',
|
||||
'dependencies': None,
|
||||
'constructor_kwargs': {'main_window'}, # 需要注入 main_window=self
|
||||
},
|
||||
]
|
||||
|
||||
|
||||
def build_step_dependencies():
|
||||
"""从 PANEL_REGISTRY 构建 step_dependencies 字典。
|
||||
|
||||
Returns:
|
||||
dict: {step_id: {input_field: (dep_step, output_type, panel_attr)}}
|
||||
"""
|
||||
deps = {}
|
||||
for entry in PANEL_REGISTRY:
|
||||
if entry['dependencies']:
|
||||
deps[entry['step_id']] = entry['dependencies']
|
||||
return deps
|
||||
|
||||
|
||||
def build_stage_groups():
|
||||
"""从 PANEL_REGISTRY 构建阶段分组字典。
|
||||
|
||||
Returns:
|
||||
dict: {stage_name: [(step_id, display_name), ...]}
|
||||
"""
|
||||
groups = {}
|
||||
for entry in PANEL_REGISTRY:
|
||||
stage = entry['stage']
|
||||
if stage not in groups:
|
||||
groups[stage] = []
|
||||
groups[stage].append((entry['step_id'], entry['display_name']))
|
||||
return groups
|
||||
|
||||
|
||||
def get_tab_index(step_id):
|
||||
"""根据 step_id 获取其在 PANEL_REGISTRY 中的索引(即 Tab 索引)。"""
|
||||
for i, entry in enumerate(PANEL_REGISTRY):
|
||||
if entry['step_id'] == step_id:
|
||||
return i
|
||||
return -1
|
||||
|
||||
|
||||
def get_step_id_by_tab_index(tab_index):
|
||||
"""根据 Tab 索引获取 step_id。"""
|
||||
if 0 <= tab_index < len(PANEL_REGISTRY):
|
||||
return PANEL_REGISTRY[tab_index]['step_id']
|
||||
return None
|
||||
|
||||
|
||||
def get_entry(step_id):
|
||||
"""根据 step_id 获取注册表条目。"""
|
||||
for entry in PANEL_REGISTRY:
|
||||
if entry['step_id'] == step_id:
|
||||
return entry
|
||||
return None
|
||||
Reference in New Issue
Block a user