From 3f217e95b06601b2f02b909349d56bec779609ff Mon Sep 17 00:00:00 2001 From: DXC Date: Thu, 18 Jun 2026 10:28:14 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8D=E4=B8=8B=E6=B8=B8?= =?UTF-8?q?=E9=9D=A2=E6=9D=BF=E8=87=AA=E5=8A=A8=E5=A1=AB=E5=85=85=E6=96=AD?= =?UTF-8?q?=E8=A3=82=E7=9A=84=E4=B8=89=E5=A4=84=E6=A0=B9=E5=9B=A0=20+=20?= =?UTF-8?q?=E6=B8=85=E7=90=86=E8=BF=87=E6=97=B6=20pipeline=E2=86=92panel?= =?UTF-8?q?=20=E6=98=A0=E5=B0=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/core/workspace_manager.py | 29 ++++---------- src/gui/core/panel_registry.py | 2 +- src/gui/core/pipeline_executor.py | 17 --------- src/gui/core/workspace_initializer.py | 55 ++++++++++++++++++--------- src/gui/water_quality_gui.py | 18 --------- 5 files changed, 46 insertions(+), 75 deletions(-) diff --git a/src/core/workspace_manager.py b/src/core/workspace_manager.py index ab5a8e5..0165f4d 100644 --- a/src/core/workspace_manager.py +++ b/src/core/workspace_manager.py @@ -25,9 +25,9 @@ class WorkspaceManager: def __init__(self): self.step_default_outputs = { - 'step1': {'water_mask': "1_water_mask/water_mask_from_ndwi.dat"}, + 'step1': {'water_mask': "1_water_mask/water_mask_out.dat"}, 'step2': {'glint_mask': "2_Glint_Detection/severe_glint_area.dat"}, - 'step3': {'deglint_image': "3_deglint/deglint_goodman.bsq"}, + 'step3': {'deglint_image': "3_deglint/deglint_image.bsq"}, 'step4_sampling': {'sampling_points': "4_sampling/sampling_spectra.csv"}, 'step5_clean': {'processed_data': "5_Data_Cleaning/processed_data.csv"}, 'step6_feature': {'training_spectra': "6_Spectral_Feature_Extraction/training_spectra.csv"}, @@ -38,12 +38,6 @@ class WorkspaceManager: 'step11_map': {'14_visualization': "14_visualization/"}, } self.step_outputs = {} - # pipeline step_id → panel step_id 映射(由 WaterQualityGUI 注入) - self._pipeline_to_panel = {} - - def set_step_id_mapping(self, mapping: dict): - """注入 pipeline step_id → panel step_id 映射,用于事件发布时统一 ID。""" - self._pipeline_to_panel = mapping def _publish_outputs(self, step_id: str, outputs: dict): """将发现的产出发布到 EventBus。 @@ -206,18 +200,11 @@ class WorkspaceManager: return discovered_outputs def update_step_outputs(self, step_name, work_path): - """更新指定步骤的输出路径记录并发布 EventBus 事件。 - - step_name 可能是 pipeline step_id(如 'step4'), - 会先通过 _pipeline_to_panel 映射为面板 step_id(如 'step5_clean')。 - """ - # 映射 pipeline step_id → panel step_id - panel_step_id = self._pipeline_to_panel.get(step_name, step_name) - - if panel_step_id not in self.step_default_outputs: + """更新指定步骤的输出路径记录并发布 EventBus 事件。""" + if step_name not in self.step_default_outputs: return - step_outputs = self.step_default_outputs[panel_step_id] + step_outputs = self.step_default_outputs[step_name] published = {} for output_type, relative_path in step_outputs.items(): @@ -227,17 +214,17 @@ class WorkspaceManager: if matching_files: latest_file = max(matching_files, key=lambda p: p.stat().st_mtime) path_str = str(latest_file) - self.step_outputs.setdefault(panel_step_id, {})[output_type] = path_str + self.step_outputs.setdefault(step_name, {})[output_type] = path_str published[output_type] = path_str else: output_path = work_path / relative_path if output_path.exists(): path_str = str(output_path) - self.step_outputs.setdefault(panel_step_id, {})[output_type] = path_str + self.step_outputs.setdefault(step_name, {})[output_type] = path_str published[output_type] = path_str if published: - self._publish_outputs(panel_step_id, published) + self._publish_outputs(step_name, published) @staticmethod def prune_config_for_prediction_mode(config: dict) -> dict: diff --git a/src/gui/core/panel_registry.py b/src/gui/core/panel_registry.py index c4343da..6e80dec 100644 --- a/src/gui/core/panel_registry.py +++ b/src/gui/core/panel_registry.py @@ -150,7 +150,7 @@ PANEL_REGISTRY = [ 'stage': '阶段四:预测与成果输出', 'display_name': '9. 机器学习预测', 'dependencies': { - 'models_dir': ('step8_ml_train', 'Supervised_Model_Training', 'models_dir_widget'), + 'models_dir': ('step8_ml_train', 'Supervised_Model_Training', 'models_dir_file'), }, 'constructor_kwargs': None, }, diff --git a/src/gui/core/pipeline_executor.py b/src/gui/core/pipeline_executor.py index 57200a7..26f3884 100644 --- a/src/gui/core/pipeline_executor.py +++ b/src/gui/core/pipeline_executor.py @@ -43,23 +43,6 @@ from src.gui.core.pipeline_mode_dialog import PipelineModeDialog from src.gui.dialogs import BandConfirmDialog from src.core.pipeline.runner import PipelineHalt -# pipeline step_id → panel step_id 映射 -PIPELINE_TO_PANEL_STEP = { - 'step1': 'step1', - 'step2': 'step2', - 'step3': 'step3', - 'step4': 'step5_clean', - 'step5': 'step6_feature', - 'step7': 'step7_index', - 'step8': 'step8_ml_train', - 'step9': 'step10_watercolor', - 'step10': 'step4_sampling', - 'step11_ml': 'step9_ml_predict', - 'step11': 'step11_map', - 'step14': 'step11_map', -} - - class PipelineExecutor(QObject): """Pipeline 执行器 —— 纯逻辑层,零 UI 直接操作。""" diff --git a/src/gui/core/workspace_initializer.py b/src/gui/core/workspace_initializer.py index 7e19d6b..0092db5 100644 --- a/src/gui/core/workspace_initializer.py +++ b/src/gui/core/workspace_initializer.py @@ -34,23 +34,6 @@ from PyQt5.QtWidgets import QMessageBox, QFileDialog from src.gui.core.event_bus import global_event_bus from src.core.workspace_manager import WorkspaceManager -# pipeline step_id → panel step_id 映射 -PIPELINE_TO_PANEL_STEP = { - 'step1': 'step1', - 'step2': 'step2', - 'step3': 'step3', - 'step4': 'step5_clean', - 'step5': 'step6_feature', - 'step7': 'step7_index', - 'step8': 'step8_ml_train', - 'step9': 'step10_watercolor', - 'step10': 'step4_sampling', - 'step11_ml': 'step9_ml_predict', - 'step11': 'step11_map', - 'step14': 'step11_map', -} - - class WorkspaceInitializer(QObject): """工作空间初始化器 —— 纯逻辑层,零 UI 直接操作。""" @@ -66,7 +49,10 @@ class WorkspaceInitializer(QObject): # 工作空间管理器(文件扫描、路径发现) self._workspace_manager = WorkspaceManager() - self._workspace_manager.set_step_id_mapping(PIPELINE_TO_PANEL_STEP) + + # 全局输入缓存:{step_id: {output_type: path}} + # 存储非步骤产出但下游面板依赖的参数(如 Step1 的 reference_img) + self._global_inputs = {} # 订阅 StepCompleted 事件 → 自动扫描产物 global_event_bus.subscribe('StepCompleted', self._on_step_completed) @@ -89,6 +75,28 @@ class WorkspaceInitializer(QObject): def workspace_manager(self) -> WorkspaceManager: return self._workspace_manager + def cache_global_input(self, step_id: str, output_type: str, path: str): + """缓存全局输入参数。 + + 全局输入不是任何步骤的产出,但下游面板依赖它。 + 典型例子:Step1 的 reference_img(用户选择的输入影像), + Step2/Step3 等下游面板需要它来预填"影像文件"字段。 + + Args: + step_id: 源步骤 ID(如 'step1') + output_type: 输出类型标识(如 'reference_img') + path: 文件路径字符串 + """ + if not path: + return + if step_id not in self._global_inputs: + self._global_inputs[step_id] = {} + self._global_inputs[step_id][output_type] = path + + def get_global_inputs(self): + """返回所有已缓存的全局输入 {step_id: {output_type: path}}。""" + return dict(self._global_inputs) + def run(self): """启动时工作目录选择对话框(由 QTimer.singleShot 延迟调用)。 @@ -183,12 +191,23 @@ class WorkspaceInitializer(QObject): if step1_panel and hasattr(step1_panel, 'img_file'): ref_img = step1_panel.img_file.get_path() if ref_img: + # 缓存到全局输入,供后续懒加载面板苏醒时回放 + self.cache_global_input('step1', 'reference_img', ref_img) global_event_bus.publish('OutputUpdated', { 'step_id': 'step1', 'output_type': 'reference_img', 'path': ref_img, }) + # 兜底:遍历已加载面板调用 update_from_config,重建内存级参数和默认输出路径 + for step_id, panel in self._panel_factory.get_loaded_panels().items(): + if not hasattr(panel, 'update_from_config'): + continue + try: + panel.update_from_config(work_dir=work_dir, pipeline=None) + except Exception: + pass + global_event_bus.publish('LogMessage', { 'message': '✓ 工作目录扫描完成,事件总线已通知所有面板自动填充', 'level': 'info', diff --git a/src/gui/water_quality_gui.py b/src/gui/water_quality_gui.py index bc55e22..8cb639f 100644 --- a/src/gui/water_quality_gui.py +++ b/src/gui/water_quality_gui.py @@ -157,23 +157,6 @@ from src.gui.core.pipeline_mode_dialog import PipelineModeDialog from src.gui.core.viz_thread import VisualizationWorkerThread, _viz_training_spectra_csv_path from src.core.workspace_manager import WorkspaceManager -# pipeline step_id → panel step_id 映射(pipeline 内部编号与 GUI 面板编号不同) -PIPELINE_TO_PANEL_STEP = { - 'step1': 'step1', - 'step2': 'step2', - 'step3': 'step3', - 'step4': 'step5_clean', - 'step5': 'step6_feature', - 'step7': 'step7_index', - 'step8': 'step8_ml_train', - 'step9': 'step10_watercolor', - 'step10': 'step4_sampling', - 'step11_ml': 'step9_ml_predict', - 'step11': 'step11_map', - 'step14': 'step11_map', -} - - class WaterQualityGUI(QMainWindow): """水质参数反演分析系统主窗口""" @@ -199,7 +182,6 @@ class WaterQualityGUI(QMainWindow): # 工作空间管理器(文件扫描、路径发现、配置裁剪) self.workspace_manager = WorkspaceManager() - self.workspace_manager.set_step_id_mapping(PIPELINE_TO_PANEL_STEP) # 面板实例字典(step_id → panel instance),由 create_content_area 填充 self._panels = {}