feat: Step1~Step14 面板单步按钮 EventBus 解耦 + Handler 补全(Step8~Step14)+ 旧上帝类删除
- 9 个面板(step1~step6/step8_ml_train/step8_qaa/step9_ml_predict/step10)单步执行按钮从 parent 链上溯改为 global_event_bus.publish('RequestRunSingleStep')
- PipelineExecutor 新增 _on_request_run_single_step 订阅
- 新增 Handler: step8_ml_train / step9_ml_predict / step10_qaa_inversion / step11_concentration / step12_kriging / step13_visualization / step14_report
- 删除旧 water_quality_inversion_pipeline_GUI.py(上帝类已肢解完毕)
This commit is contained in:
@ -243,7 +243,7 @@ class Step10WatercolorPanel(QWidget):
|
||||
|
||||
self.run_btn = QPushButton("▶ 执行水色指数反演")
|
||||
self.run_btn.setStyleSheet(ModernStylesheet.get_button_stylesheet('success'))
|
||||
self.run_btn.clicked.connect(self.run_step)
|
||||
self.run_btn.clicked.connect(self._on_run_single_clicked)
|
||||
layout.addWidget(self.run_btn)
|
||||
|
||||
layout.addStretch()
|
||||
@ -484,7 +484,54 @@ class Step10WatercolorPanel(QWidget):
|
||||
if not self.output_dir.get_path():
|
||||
self.output_dir.set_path(out_dir)
|
||||
|
||||
def _on_run_single_clicked(self):
|
||||
"""通过 EventBus 发布单步执行请求(解耦面板与 PipelineExecutor)。"""
|
||||
from src.gui.core.event_bus import global_event_bus
|
||||
|
||||
bsq_path = self.bsq_file.get_path().strip()
|
||||
hdr_path = self.hdr_file.get_path().strip()
|
||||
output_dir = self.output_dir.get_path().strip()
|
||||
|
||||
if not bsq_path:
|
||||
QMessageBox.warning(self, "输入错误", "请选择去耀斑 BSQ 影像!")
|
||||
return
|
||||
if not Path(bsq_path).exists():
|
||||
QMessageBox.warning(self, "输入错误", f"BSQ 影像不存在:\n{bsq_path}")
|
||||
return
|
||||
if not hdr_path:
|
||||
auto_hdr = Path(bsq_path).with_suffix('.hdr')
|
||||
if auto_hdr.exists():
|
||||
hdr_path = str(auto_hdr)
|
||||
self.hdr_file.set_path(hdr_path)
|
||||
else:
|
||||
QMessageBox.warning(self, "输入错误", "请选择 ENVI 头文件!")
|
||||
return
|
||||
if not Path(hdr_path).exists():
|
||||
QMessageBox.warning(self, "输入错误", f"HDR 文件不存在:\n{hdr_path}")
|
||||
return
|
||||
if not output_dir:
|
||||
work_dir = self._get_default_work_dir()
|
||||
output_dir = resolve_subdir(work_dir, 'watercolor')
|
||||
os.makedirs(output_dir, exist_ok=True)
|
||||
self.output_dir.set_path(output_dir)
|
||||
|
||||
selected = self._get_selected_formula_names()
|
||||
if not selected:
|
||||
QMessageBox.warning(self, "输入错误", "请至少选择一个公式!")
|
||||
return
|
||||
|
||||
if self._waterindex_csv and not Path(self._waterindex_csv).exists():
|
||||
QMessageBox.warning(self, "配置错误", f"waterindex.csv 不存在:\n{self._waterindex_csv}")
|
||||
return
|
||||
|
||||
config = {'step10': self.get_config()}
|
||||
global_event_bus.publish('RequestRunSingleStep', {
|
||||
'step_name': 'step10',
|
||||
'config': config,
|
||||
})
|
||||
|
||||
def run_step(self):
|
||||
"""独立运行步骤10(旧版 parent 链上溯方式,保留兼容)。"""
|
||||
bsq_path = self.bsq_file.get_path().strip()
|
||||
hdr_path = self.hdr_file.get_path().strip()
|
||||
output_dir = self.output_dir.get_path().strip()
|
||||
|
||||
@ -27,12 +27,7 @@ from PyQt5.QtWidgets import (
|
||||
from src.gui.components.custom_widgets import FileSelectWidget
|
||||
from src.gui.styles import ModernStylesheet
|
||||
|
||||
# Pipeline 可用性(与 core/worker_thread.py 保持一致)
|
||||
try:
|
||||
from src.core.water_quality_inversion_pipeline_GUI import WaterQualityInversionPipeline
|
||||
PIPELINE_AVAILABLE = True
|
||||
except ImportError:
|
||||
PIPELINE_AVAILABLE = False
|
||||
PIPELINE_AVAILABLE = True
|
||||
|
||||
|
||||
class Step11MapBatchThread(QThread):
|
||||
@ -63,19 +58,19 @@ class Step11MapBatchThread(QThread):
|
||||
except Exception:
|
||||
mpl_prev = None
|
||||
try:
|
||||
from src.core.water_quality_inversion_pipeline_GUI import WaterQualityInversionPipeline
|
||||
pipeline = WaterQualityInversionPipeline(work_dir=self.work_dir)
|
||||
from src.core.steps.mapping_step import MappingStep
|
||||
n = len(self.csv_paths)
|
||||
for i, csv_p in enumerate(self.csv_paths):
|
||||
self.progress.emit(i + 1, n)
|
||||
self.log_message.emit(f"专题图 [{i + 1}/{n}] {csv_p}", "info")
|
||||
kw = {**self.step10_kwargs, "prediction_csv_path": csv_p, "skip_dependency_check": True}
|
||||
kw = {**self.step10_kwargs, "prediction_csv_path": csv_p}
|
||||
kw.pop("skip_dependency_check", None)
|
||||
if self.output_dir_optional:
|
||||
stem = Path(csv_p).stem
|
||||
kw["output_image_path"] = str(Path(self.output_dir_optional) / f"{stem}_distribution.png")
|
||||
else:
|
||||
kw["output_image_path"] = None
|
||||
pipeline.step10_map(**kw)
|
||||
MappingStep.generate_distribution_map(**kw)
|
||||
self.finished_ok.emit(n)
|
||||
except Exception as e:
|
||||
self.failed.emit(f"{e}\n{traceback.format_exc()}")
|
||||
|
||||
@ -32,12 +32,7 @@ from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
|
||||
from matplotlib.backends.backend_qt5agg import NavigationToolbar2QT as NavigationToolbar
|
||||
from matplotlib.figure import Figure
|
||||
|
||||
# Pipeline 可用性(与 core/worker_thread.py 保持一致)
|
||||
try:
|
||||
from src.core.water_quality_inversion_pipeline_GUI import WaterQualityInversionPipeline
|
||||
PIPELINE_AVAILABLE = True
|
||||
except ImportError:
|
||||
PIPELINE_AVAILABLE = False
|
||||
PIPELINE_AVAILABLE = True
|
||||
|
||||
|
||||
def _viz_training_spectra_csv_path(work_path: Path) -> Path:
|
||||
@ -208,7 +203,7 @@ class VisualizationWorkerThread(QThread):
|
||||
{"task": "statistics", "output_paths": output_paths}
|
||||
)
|
||||
elif self.task == "scatter":
|
||||
from src.core.water_quality_inversion_pipeline_GUI import WaterQualityInversionPipeline
|
||||
from src.core.visualization.scatter_plot import generate_model_scatter_plots
|
||||
|
||||
training_csv_path = (self.extra.get("training_csv_path") or "").strip()
|
||||
models_dir = (self.extra.get("models_dir") or "").strip()
|
||||
@ -218,10 +213,9 @@ class VisualizationWorkerThread(QThread):
|
||||
if not models_dir or not Path(models_dir).is_dir():
|
||||
self.failed.emit("模型目录无效或不存在,请确认步骤6已生成 7_Supervised_Model_Training 下的参数子文件夹。")
|
||||
return
|
||||
pipeline = WaterQualityInversionPipeline(work_dir=str(wp))
|
||||
scatter_paths = pipeline.generate_model_scatter_plots(
|
||||
training_csv_path=training_csv_path,
|
||||
scatter_paths = generate_model_scatter_plots(
|
||||
models_dir=models_dir,
|
||||
training_csv_path=training_csv_path,
|
||||
)
|
||||
self.finished_ok.emit({"task": "scatter", "scatter_paths": scatter_paths or {}})
|
||||
elif self.task == "generate_all_selected":
|
||||
@ -235,11 +229,10 @@ class VisualizationWorkerThread(QThread):
|
||||
if training_csv.is_file():
|
||||
models_dir = wp / "7_Supervised_Model_Training"
|
||||
if models_dir.is_dir() and any(d.is_dir() for d in models_dir.iterdir()):
|
||||
from src.core.water_quality_inversion_pipeline_GUI import WaterQualityInversionPipeline
|
||||
pipeline = WaterQualityInversionPipeline(work_dir=str(wp))
|
||||
scatter_paths = pipeline.generate_model_scatter_plots(
|
||||
training_csv_path=str(training_csv),
|
||||
from src.core.visualization.scatter_plot import generate_model_scatter_plots
|
||||
scatter_paths = generate_model_scatter_plots(
|
||||
models_dir=str(models_dir),
|
||||
training_csv_path=str(training_csv),
|
||||
)
|
||||
count = len(scatter_paths) if scatter_paths else 0
|
||||
parts.append(f"散点图: {count} 个")
|
||||
|
||||
@ -27,12 +27,7 @@ from PyQt5.QtWidgets import (
|
||||
from src.gui.components.custom_widgets import FileSelectWidget
|
||||
from src.gui.styles import ModernStylesheet
|
||||
|
||||
# Pipeline 可用性(与 core/worker_thread.py 保持一致)
|
||||
try:
|
||||
from src.core.water_quality_inversion_pipeline_GUI import WaterQualityInversionPipeline
|
||||
PIPELINE_AVAILABLE = True
|
||||
except ImportError:
|
||||
PIPELINE_AVAILABLE = False
|
||||
PIPELINE_AVAILABLE = True
|
||||
|
||||
|
||||
class Step14BatchThread(QThread):
|
||||
@ -63,19 +58,19 @@ class Step14BatchThread(QThread):
|
||||
except Exception:
|
||||
mpl_prev = None
|
||||
try:
|
||||
from src.core.water_quality_inversion_pipeline_GUI import WaterQualityInversionPipeline
|
||||
pipeline = WaterQualityInversionPipeline(work_dir=self.work_dir)
|
||||
from src.core.steps.mapping_step import MappingStep
|
||||
n = len(self.csv_paths)
|
||||
for i, csv_p in enumerate(self.csv_paths):
|
||||
self.progress.emit(i + 1, n)
|
||||
self.log_message.emit(f"专题图 [{i + 1}/{n}] {csv_p}", "info")
|
||||
kw = {**self.step14_kwargs, "prediction_csv_path": csv_p, "skip_dependency_check": True}
|
||||
kw = {**self.step14_kwargs, "prediction_csv_path": csv_p}
|
||||
kw.pop("skip_dependency_check", None)
|
||||
if self.output_dir_optional:
|
||||
stem = Path(csv_p).stem
|
||||
kw["output_image_path"] = str(Path(self.output_dir_optional) / f"{stem}_distribution.png")
|
||||
else:
|
||||
kw["output_image_path"] = None
|
||||
pipeline.step10_map(**kw)
|
||||
MappingStep.generate_distribution_map(**kw)
|
||||
self.finished_ok.emit(n)
|
||||
except Exception as e:
|
||||
self.failed.emit(f"{e}\n{traceback.format_exc()}")
|
||||
|
||||
@ -144,7 +144,7 @@ class Step1Panel(QWidget):
|
||||
# 独立运行按钮
|
||||
self.run_btn = QPushButton("独立运行此步骤")
|
||||
self.run_btn.setStyleSheet(ModernStylesheet.get_button_stylesheet('success'))
|
||||
self.run_btn.clicked.connect(self.run_step)
|
||||
self.run_btn.clicked.connect(self._on_run_single_clicked)
|
||||
layout.addWidget(self.run_btn)
|
||||
|
||||
# 连接信号
|
||||
@ -257,8 +257,40 @@ class Step1Panel(QWidget):
|
||||
|
||||
self.update_ui_state()
|
||||
|
||||
def _on_run_single_clicked(self):
|
||||
"""通过 EventBus 发布单步执行请求(解耦面板与 PipelineExecutor)。
|
||||
|
||||
替代旧有的 parent 链上溯查找 run_single_step 的紧耦合方式。
|
||||
PipelineExecutor 在 __init__ 中订阅 RequestRunSingleStep 事件,
|
||||
收到后调用 run_single_step(step_name, config) 统一处理预检/工作目录/执行。
|
||||
"""
|
||||
from src.gui.core.event_bus import global_event_bus
|
||||
|
||||
# 验证输入(与旧 run_step 逻辑一致)
|
||||
if self.use_ndwi_radio.isChecked():
|
||||
img_path = self.img_file.get_path()
|
||||
if not img_path:
|
||||
QMessageBox.warning(self, "输入错误", "请选择参考影像文件!")
|
||||
return
|
||||
else:
|
||||
mask_path = self.mask_file.get_path()
|
||||
if not mask_path:
|
||||
QMessageBox.warning(self, "输入错误", "请选择掩膜文件!")
|
||||
return
|
||||
if mask_path.lower().endswith('.shp'):
|
||||
img_path = self.img_file.get_path()
|
||||
if not img_path:
|
||||
QMessageBox.warning(self, "输入错误", "当使用shp文件时,需要提供参考影像用于栅格化!")
|
||||
return
|
||||
|
||||
config = {'step1': self.get_config()}
|
||||
global_event_bus.publish('RequestRunSingleStep', {
|
||||
'step_name': 'step1',
|
||||
'config': config,
|
||||
})
|
||||
|
||||
def run_step(self):
|
||||
"""独立运行步骤1"""
|
||||
"""独立运行步骤1(旧版 parent 链上溯方式,保留兼容)。"""
|
||||
# 验证输入
|
||||
if self.use_ndwi_radio.isChecked():
|
||||
# NDWI模式:需要影像文件
|
||||
|
||||
@ -108,7 +108,7 @@ class Step2Panel(QWidget):
|
||||
# 独立运行按钮
|
||||
self.run_btn = QPushButton("独立运行此步骤")
|
||||
self.run_btn.setStyleSheet(ModernStylesheet.get_button_stylesheet('success'))
|
||||
self.run_btn.clicked.connect(self.run_step)
|
||||
self.run_btn.clicked.connect(self._on_run_single_clicked)
|
||||
layout.addWidget(self.run_btn)
|
||||
|
||||
layout.addStretch()
|
||||
@ -203,8 +203,23 @@ class Step2Panel(QWidget):
|
||||
# 没有工作目录时,清空输出路径
|
||||
self.output_file.set_path("")
|
||||
|
||||
def _on_run_single_clicked(self):
|
||||
"""通过 EventBus 发布单步执行请求(解耦面板与 PipelineExecutor)。"""
|
||||
from src.gui.core.event_bus import global_event_bus
|
||||
|
||||
img_path = self.img_file.get_path()
|
||||
if not img_path:
|
||||
QMessageBox.warning(self, "输入错误", "请选择影像文件!")
|
||||
return
|
||||
|
||||
config = {'step2': self.get_config()}
|
||||
global_event_bus.publish('RequestRunSingleStep', {
|
||||
'step_name': 'step2',
|
||||
'config': config,
|
||||
})
|
||||
|
||||
def run_step(self):
|
||||
"""独立运行步骤2"""
|
||||
"""独立运行步骤2(旧版 parent 链上溯方式,保留兼容)。"""
|
||||
# 验证输入
|
||||
img_path = self.img_file.get_path()
|
||||
if not img_path:
|
||||
|
||||
@ -228,7 +228,7 @@ class Step3Panel(QWidget):
|
||||
# 独立运行按钮
|
||||
self.run_btn = QPushButton("独立运行此步骤")
|
||||
self.run_btn.setStyleSheet(ModernStylesheet.get_button_stylesheet('success'))
|
||||
self.run_btn.clicked.connect(self.run_step)
|
||||
self.run_btn.clicked.connect(self._on_run_single_clicked)
|
||||
layout.addWidget(self.run_btn)
|
||||
|
||||
layout.addStretch()
|
||||
@ -433,8 +433,34 @@ class Step3Panel(QWidget):
|
||||
if 'sugar_bounds' in config:
|
||||
self.sugar_bounds.setText(str(config['sugar_bounds']))
|
||||
|
||||
def _on_run_single_clicked(self):
|
||||
"""通过 EventBus 发布单步执行请求(解耦面板与 PipelineExecutor)。"""
|
||||
from src.gui.core.event_bus import global_event_bus
|
||||
|
||||
img_path = self.img_file.get_path()
|
||||
if not img_path:
|
||||
QMessageBox.warning(self, "输入错误", "请选择影像文件!")
|
||||
return
|
||||
if self.enable_checkbox.isChecked():
|
||||
water_mask_path = self.water_mask_file.get_path()
|
||||
if not water_mask_path:
|
||||
QMessageBox.warning(
|
||||
self,
|
||||
"输入错误",
|
||||
"独立运行耀斑去除时,必须选择水域掩膜或边界文件。\n\n"
|
||||
"请提供与当前影像空间一致的水域栅格掩膜(.dat/.tif),或水域矢量边界(.shp)。\n"
|
||||
"若刚跑过完整流程,可使用步骤1生成的水域掩膜文件。",
|
||||
)
|
||||
return
|
||||
|
||||
config = {'step3': self.get_config()}
|
||||
global_event_bus.publish('RequestRunSingleStep', {
|
||||
'step_name': 'step3',
|
||||
'config': config,
|
||||
})
|
||||
|
||||
def run_step(self):
|
||||
"""独立运行步骤3"""
|
||||
"""独立运行步骤3(旧版 parent 链上溯方式,保留兼容)。"""
|
||||
# 验证输入
|
||||
img_path = self.img_file.get_path()
|
||||
if not img_path:
|
||||
|
||||
@ -91,7 +91,7 @@ class Step4SamplingPanel(QWidget):
|
||||
# 独立运行按钮
|
||||
self.run_btn = QPushButton("独立运行此步骤")
|
||||
self.run_btn.setStyleSheet(ModernStylesheet.get_button_stylesheet('success'))
|
||||
self.run_btn.clicked.connect(self.run_step)
|
||||
self.run_btn.clicked.connect(self._on_run_single_clicked)
|
||||
layout.addWidget(self.run_btn)
|
||||
|
||||
# 交互式预览按钮
|
||||
@ -228,8 +228,23 @@ class Step4SamplingPanel(QWidget):
|
||||
# 4. 同步更新预览按钮状态(路径可能已自动填充)
|
||||
self._check_csv_exists()
|
||||
|
||||
def _on_run_single_clicked(self):
|
||||
"""通过 EventBus 发布单步执行请求(解耦面板与 PipelineExecutor)。"""
|
||||
from src.gui.core.event_bus import global_event_bus
|
||||
|
||||
deglint_img_path = self.deglint_img_file.get_path()
|
||||
if not deglint_img_path:
|
||||
QMessageBox.warning(self, "输入错误", "请选择去耀斑影像文件!")
|
||||
return
|
||||
|
||||
config = {'step4_sampling': self.get_config()}
|
||||
global_event_bus.publish('RequestRunSingleStep', {
|
||||
'step_name': 'step4_sampling',
|
||||
'config': config,
|
||||
})
|
||||
|
||||
def run_step(self):
|
||||
"""独立运行步骤4"""
|
||||
"""独立运行步骤4(旧版 parent 链上溯方式,保留兼容)。"""
|
||||
deglint_img_path = self.deglint_img_file.get_path()
|
||||
if not deglint_img_path:
|
||||
QMessageBox.warning(self, "输入错误", "请选择去耀斑影像文件!")
|
||||
|
||||
@ -95,7 +95,7 @@ class Step5CleanPanel(QWidget):
|
||||
# 独立运行按钮
|
||||
self.run_btn = QPushButton("独立运行此步骤")
|
||||
self.run_btn.setStyleSheet(ModernStylesheet.get_button_stylesheet('success'))
|
||||
self.run_btn.clicked.connect(self.run_step)
|
||||
self.run_btn.clicked.connect(self._on_run_single_clicked)
|
||||
layout.addWidget(self.run_btn)
|
||||
|
||||
layout.addStretch()
|
||||
@ -142,8 +142,23 @@ class Step5CleanPanel(QWidget):
|
||||
else:
|
||||
self.output_file.set_path("")
|
||||
|
||||
def _on_run_single_clicked(self):
|
||||
"""通过 EventBus 发布单步执行请求(解耦面板与 PipelineExecutor)。"""
|
||||
from src.gui.core.event_bus import global_event_bus
|
||||
|
||||
csv_path = self.csv_file.get_path()
|
||||
if not csv_path:
|
||||
QMessageBox.warning(self, "输入错误", "请选择水质参数文件!")
|
||||
return
|
||||
|
||||
config = {'step5_clean': self.get_config()}
|
||||
global_event_bus.publish('RequestRunSingleStep', {
|
||||
'step_name': 'step5_clean',
|
||||
'config': config,
|
||||
})
|
||||
|
||||
def run_step(self):
|
||||
"""独立运行步骤5"""
|
||||
"""独立运行步骤5(旧版 parent 链上溯方式,保留兼容)。"""
|
||||
csv_path = self.csv_file.get_path()
|
||||
if not csv_path:
|
||||
QMessageBox.warning(self, "输入错误", "请选择水质参数文件!")
|
||||
|
||||
@ -106,7 +106,7 @@ class Step6FeaturePanel(QWidget):
|
||||
# 独立运行按钮
|
||||
self.run_btn = QPushButton("独立运行此步骤")
|
||||
self.run_btn.setStyleSheet(ModernStylesheet.get_button_stylesheet('success'))
|
||||
self.run_btn.clicked.connect(self.run_step)
|
||||
self.run_btn.clicked.connect(self._on_run_single_clicked)
|
||||
layout.addWidget(self.run_btn)
|
||||
|
||||
layout.addStretch()
|
||||
@ -258,8 +258,35 @@ class Step6FeaturePanel(QWidget):
|
||||
if not existing_csv or not existing_csv.strip():
|
||||
self.csv_file.set_path(step5_clean_output_path)
|
||||
|
||||
def _on_run_single_clicked(self):
|
||||
"""通过 EventBus 发布单步执行请求(解耦面板与 PipelineExecutor)。"""
|
||||
from src.gui.core.event_bus import global_event_bus
|
||||
|
||||
deglint_img_path = self.deglint_img_file.get_path()
|
||||
csv_path = self.csv_file.get_path()
|
||||
if not deglint_img_path:
|
||||
QMessageBox.warning(self, "输入错误", "请选择去耀斑影像文件!")
|
||||
return
|
||||
if not csv_path:
|
||||
QMessageBox.warning(self, "输入错误", "请选择处理后的CSV文件!")
|
||||
return
|
||||
if not self.glint_mask_file.get_path():
|
||||
QMessageBox.warning(
|
||||
self,
|
||||
"输入错误",
|
||||
"独立运行光谱特征提取时,必须选择耀斑掩膜文件。\n\n"
|
||||
"请提供与去耀斑影像对应的耀斑二值掩膜(一般为步骤2输出的 severe_glint_area.dat)。",
|
||||
)
|
||||
return
|
||||
|
||||
config = {'step6_feature': self.get_config()}
|
||||
global_event_bus.publish('RequestRunSingleStep', {
|
||||
'step_name': 'step6_feature',
|
||||
'config': config,
|
||||
})
|
||||
|
||||
def run_step(self):
|
||||
"""独立运行步骤6"""
|
||||
"""独立运行步骤6(旧版 parent 链上溯方式,保留兼容)。"""
|
||||
# 验证输入
|
||||
deglint_img_path = self.deglint_img_file.get_path()
|
||||
csv_path = self.csv_file.get_path()
|
||||
|
||||
@ -119,7 +119,7 @@ class Step8MlTrainPanel(QWidget):
|
||||
# 独立运行按钮
|
||||
self.run_btn = QPushButton("独立运行此步骤")
|
||||
self.run_btn.setStyleSheet(ModernStylesheet.get_button_stylesheet('success'))
|
||||
self.run_btn.clicked.connect(self.run_step)
|
||||
self.run_btn.clicked.connect(self._on_run_single_clicked)
|
||||
layout.addWidget(self.run_btn)
|
||||
|
||||
layout.addStretch()
|
||||
@ -398,8 +398,23 @@ class Step8MlTrainPanel(QWidget):
|
||||
else:
|
||||
self.output_path.set_path("")
|
||||
|
||||
def _on_run_single_clicked(self):
|
||||
"""通过 EventBus 发布单步执行请求(解耦面板与 PipelineExecutor)。"""
|
||||
from src.gui.core.event_bus import global_event_bus
|
||||
|
||||
training_csv_path = self.training_csv_file.get_path()
|
||||
if not training_csv_path:
|
||||
QMessageBox.warning(self, "输入错误", "请选择训练数据CSV文件!")
|
||||
return
|
||||
|
||||
config = {'step8_ml_train': self.get_config()}
|
||||
global_event_bus.publish('RequestRunSingleStep', {
|
||||
'step_name': 'step8_ml_train',
|
||||
'config': config,
|
||||
})
|
||||
|
||||
def run_step(self):
|
||||
"""独立运行步骤8"""
|
||||
"""独立运行步骤8(旧版 parent 链上溯方式,保留兼容)。"""
|
||||
training_csv_path = self.training_csv_file.get_path()
|
||||
if not training_csv_path:
|
||||
QMessageBox.warning(self, "输入错误", "请选择训练数据CSV文件!")
|
||||
|
||||
@ -109,7 +109,7 @@ class Step8QAAPanel(QWidget):
|
||||
# 独立运行按钮
|
||||
self.run_btn = QPushButton("执行 QAA 反演")
|
||||
self.run_btn.setStyleSheet(ModernStylesheet.get_button_stylesheet('success'))
|
||||
self.run_btn.clicked.connect(self.run_step)
|
||||
self.run_btn.clicked.connect(self._on_run_single_clicked)
|
||||
layout.addWidget(self.run_btn)
|
||||
|
||||
layout.addStretch()
|
||||
@ -212,8 +212,23 @@ class Step8QAAPanel(QWidget):
|
||||
else:
|
||||
self.output_path.set_path("")
|
||||
|
||||
def _on_run_single_clicked(self):
|
||||
"""通过 EventBus 发布单步执行请求(解耦面板与 PipelineExecutor)。"""
|
||||
from src.gui.core.event_bus import global_event_bus
|
||||
|
||||
spectrum_path = self.spectrum_csv_file.get_path()
|
||||
if not spectrum_path:
|
||||
QMessageBox.warning(self, "输入错误", "请选择光谱 CSV 文件!")
|
||||
return
|
||||
|
||||
config = {'step8_qaa': self.get_config()}
|
||||
global_event_bus.publish('RequestRunSingleStep', {
|
||||
'step_name': 'step8_qaa',
|
||||
'config': config,
|
||||
})
|
||||
|
||||
def run_step(self):
|
||||
"""独立运行 QAA 反演"""
|
||||
"""独立运行 QAA 反演(旧版 parent 链上溯方式,保留兼容)。"""
|
||||
spectrum_path = self.spectrum_csv_file.get_path()
|
||||
if not spectrum_path:
|
||||
QMessageBox.warning(self, "输入错误", "请选择光谱 CSV 文件!")
|
||||
|
||||
@ -175,7 +175,7 @@ class Step9MlPredictPanel(QWidget):
|
||||
# 独立运行按钮
|
||||
self.run_btn = QPushButton("独立运行此步骤")
|
||||
self.run_btn.setStyleSheet(ModernStylesheet.get_button_stylesheet('success'))
|
||||
self.run_btn.clicked.connect(self.run_step)
|
||||
self.run_btn.clicked.connect(self._on_run_single_clicked)
|
||||
layout.addWidget(self.run_btn)
|
||||
|
||||
layout.addStretch()
|
||||
@ -414,8 +414,57 @@ class Step9MlPredictPanel(QWidget):
|
||||
if 'output_path' in config:
|
||||
self.output_file.set_path(config['output_path'])
|
||||
|
||||
def _on_run_single_clicked(self):
|
||||
"""通过 EventBus 发布单步执行请求(解耦面板与 PipelineExecutor)。"""
|
||||
from src.gui.core.event_bus import global_event_bus
|
||||
|
||||
sampling_csv_path = self.sampling_csv_file.get_path()
|
||||
if not sampling_csv_path:
|
||||
QMessageBox.warning(self, "输入错误", "请选择采样光谱CSV文件!")
|
||||
return
|
||||
|
||||
# 外部模型优先:用户选择了"导入本地预训练模型"
|
||||
if self.use_external_model.isChecked():
|
||||
if not self.external_models_dict:
|
||||
QMessageBox.warning(
|
||||
self,
|
||||
"模型未加载",
|
||||
"请先点击「浏览...」按钮选择模型母文件夹!",
|
||||
)
|
||||
return
|
||||
checked_dict = self._get_checked_models_dict()
|
||||
if not checked_dict:
|
||||
QMessageBox.warning(
|
||||
self,
|
||||
"未选择模型",
|
||||
"请至少勾选一个模型参与预测!",
|
||||
)
|
||||
return
|
||||
config = {
|
||||
'step9_ml_predict': self.get_config(),
|
||||
'_external_models_dict': checked_dict,
|
||||
'_external_model_dir': self.external_model_dir,
|
||||
}
|
||||
global_event_bus.publish('RequestRunSingleStep', {
|
||||
'step_name': 'step9_ml_predict',
|
||||
'config': config,
|
||||
})
|
||||
return
|
||||
|
||||
# 默认流程:使用模型目录
|
||||
models_dir = self.models_dir_file.get_path()
|
||||
if not models_dir:
|
||||
QMessageBox.warning(self, "输入错误", "请选择模型目录!")
|
||||
return
|
||||
|
||||
config = {'step9_ml_predict': self.get_config()}
|
||||
global_event_bus.publish('RequestRunSingleStep', {
|
||||
'step_name': 'step9_ml_predict',
|
||||
'config': config,
|
||||
})
|
||||
|
||||
def run_step(self):
|
||||
"""独立运行步骤11"""
|
||||
"""独立运行步骤11(旧版 parent 链上溯方式,保留兼容)。"""
|
||||
sampling_csv_path = self.sampling_csv_file.get_path()
|
||||
if not sampling_csv_path:
|
||||
QMessageBox.warning(self, "输入错误", "请选择采样光谱CSV文件!")
|
||||
|
||||
Reference in New Issue
Block a user