refactor: 重构所有面板 update_from_config 为文件系统扫描模式
=== 核心变更 ===
- _step_path_resolver 新增 scan_work_dir_for_input() 统一文件扫描工具
- 基于 _SCAN_TABLE 映射表,按 output_type 自动扫描 work_dir 子目录
- 支持扩展名匹配(.dat/.tif/.bsq/.csv 等)和文件名关键词匹配
- 按 mtime 排序,返回最新匹配文件
=== 各面板重构 ===
- step2/3/4/6: 废弃 main_window.stepX_panel 跨面板读取
统一改为 scan_work_dir_for_input(work_dir, 'water_mask/glint_mask/deglint_image')
- step6: 移除对 step1/2/3/5 panel 的4处跨面板依赖
- step8: 替换 _resolve_training_csv_from_workdir 为 scan_work_dir_for_input
优先级:training_spectra_indices -> training_spectra
- step9: 替换 _resolve_latest_wqi_test_csv 为 scan_work_dir_for_input
废弃 factory.get_panel('step4_sampling') 和 get_panel('step8_ml_train')
- step10: 替换3层回退链为 scan_work_dir_for_input('sampling_points')
- step11: 替换 factory.get_panel('step9')/('step1') 为文件扫描
=== 删除的冗余方法 ===
- step8._resolve_training_csv_from_workdir (~55行)
- step9._resolve_latest_wqi_test_csv (~56行)
=== 数据流原则 ===
1. pipeline context 为第一顺位(执行时内存状态)
2. 文件系统扫描为回退(仅信任硬盘上真实存在的文件)
3. 彻底禁止面板间 UI 控件互相读取
This commit is contained in:
@ -12,7 +12,7 @@ from pathlib import Path
|
||||
_HERE = os.path.dirname(os.path.abspath(__file__))
|
||||
if _HERE not in sys.path:
|
||||
sys.path.insert(0, _HERE)
|
||||
from src.gui.panels._step_path_resolver import resolve_subdir
|
||||
from src.gui.panels._step_path_resolver import resolve_subdir, scan_work_dir_for_input
|
||||
|
||||
from PyQt5.QtWidgets import (
|
||||
QWidget, QVBoxLayout, QHBoxLayout, QGroupBox, QFormLayout,
|
||||
@ -218,33 +218,22 @@ class Step6FeaturePanel(QWidget):
|
||||
else:
|
||||
self.work_dir = None
|
||||
|
||||
# 1. 水体掩膜:优先 pipeline,回退文件系统扫描
|
||||
mask_path = None
|
||||
if pipeline and hasattr(pipeline, 'water_mask_path') and pipeline.water_mask_path:
|
||||
mask_path = pipeline.water_mask_path
|
||||
if not mask_path and self.work_dir:
|
||||
mask_path = scan_work_dir_for_input(self.work_dir, 'water_mask')
|
||||
if mask_path and os.path.exists(str(mask_path)):
|
||||
self.water_mask_file.set_path(str(mask_path))
|
||||
|
||||
main_window = self.window()
|
||||
if not mask_path and hasattr(main_window, 'step1_panel'):
|
||||
if main_window.step1_panel.use_ndwi_radio.isChecked():
|
||||
mask_path = main_window.step1_panel.output_file.get_path()
|
||||
else:
|
||||
mask_path = main_window.step1_panel.mask_file.get_path()
|
||||
if mask_path and not os.path.isabs(mask_path):
|
||||
mask_path = os.path.join(self.work_dir or '', mask_path).replace('\\', '/')
|
||||
|
||||
if mask_path:
|
||||
if not os.path.isabs(mask_path):
|
||||
mask_path = os.path.join(self.work_dir or '', mask_path).replace('\\', '/')
|
||||
if os.path.exists(mask_path):
|
||||
self.water_mask_file.set_path(mask_path)
|
||||
|
||||
if hasattr(main_window, 'step2_panel'):
|
||||
glint_path = main_window.step2_panel.output_file.get_path()
|
||||
if glint_path:
|
||||
if not os.path.isabs(glint_path):
|
||||
glint_path = os.path.join(self.work_dir or '', glint_path).replace('\\', '/')
|
||||
if os.path.exists(glint_path):
|
||||
self.glint_mask_file.set_path(glint_path)
|
||||
# 2. 耀斑掩膜:文件系统扫描
|
||||
if self.work_dir:
|
||||
glint_path = scan_work_dir_for_input(self.work_dir, 'glint_mask')
|
||||
if glint_path and os.path.exists(str(glint_path)):
|
||||
self.glint_mask_file.set_path(str(glint_path))
|
||||
|
||||
# 3. 去耀斑影像:优先 pipeline.step_outputs,回退文件系统扫描
|
||||
deglint_path = None
|
||||
if pipeline and hasattr(pipeline, 'step_outputs'):
|
||||
step3_outputs = getattr(pipeline, 'step_outputs', {}).get('step3', {})
|
||||
@ -254,30 +243,22 @@ class Step6FeaturePanel(QWidget):
|
||||
or step3_outputs.get('output_file')
|
||||
or step3_outputs.get('deglint_img_path')
|
||||
)
|
||||
|
||||
if not deglint_path and hasattr(main_window, 'step3_panel'):
|
||||
step3_widget = getattr(main_window.step3_panel, 'output_file', None)
|
||||
if step3_widget is not None and hasattr(step3_widget, 'get_path'):
|
||||
deglint_path = step3_widget.get_path() or ""
|
||||
|
||||
if not deglint_path and self.work_dir:
|
||||
deglint_dir = resolve_subdir(self.work_dir, 'deglint')
|
||||
if os.path.isdir(deglint_dir):
|
||||
bsq_files = [
|
||||
f for f in os.listdir(deglint_dir)
|
||||
if f.lower().endswith('.bsq')
|
||||
]
|
||||
bsq_files.sort(key=lambda n: (0 if 'goodman' in n.lower() else 1, n))
|
||||
if bsq_files:
|
||||
deglint_path = os.path.join(deglint_dir, bsq_files[0]).replace('\\', '/')
|
||||
|
||||
if deglint_path:
|
||||
if not os.path.isabs(deglint_path):
|
||||
deglint_path = os.path.join(self.work_dir or '', deglint_path).replace('\\', '/')
|
||||
deglint_path = scan_work_dir_for_input(self.work_dir, 'deglint_image')
|
||||
if deglint_path and os.path.exists(str(deglint_path)):
|
||||
existing_deglint = self.deglint_img_file.get_path()
|
||||
if (not existing_deglint or not existing_deglint.strip()) and os.path.exists(deglint_path):
|
||||
self.deglint_img_file.set_path(deglint_path)
|
||||
if (not existing_deglint or not existing_deglint.strip()):
|
||||
self.deglint_img_file.set_path(str(deglint_path))
|
||||
|
||||
# 4. 处理后 CSV:文件系统扫描
|
||||
if self.work_dir:
|
||||
csv_path = scan_work_dir_for_input(self.work_dir, 'processed_data')
|
||||
if csv_path and os.path.exists(str(csv_path)):
|
||||
existing_csv = self.csv_file.get_path()
|
||||
if (not existing_csv or not existing_csv.strip()):
|
||||
self.csv_file.set_path(str(csv_path))
|
||||
|
||||
# 5. 输出路径
|
||||
if self.work_dir and not self.output_file.get_path():
|
||||
output_dir = resolve_subdir(self.work_dir, 'spectral_feature')
|
||||
default_output_path = os.path.join(output_dir, "training_spectra.csv").replace('\\', '/')
|
||||
@ -285,17 +266,6 @@ class Step6FeaturePanel(QWidget):
|
||||
elif not self.work_dir:
|
||||
self.output_file.set_path("")
|
||||
|
||||
if main_window and hasattr(main_window, 'step5_clean_panel'):
|
||||
step5_clean_output_path = main_window.step5_clean_panel.output_file.get_path()
|
||||
if step5_clean_output_path:
|
||||
if not os.path.isabs(step5_clean_output_path):
|
||||
step5_clean_output_path = os.path.join(
|
||||
self.work_dir or '', step5_clean_output_path
|
||||
).replace('\\', '/')
|
||||
existing_csv = self.csv_file.get_path()
|
||||
if (not existing_csv or not existing_csv.strip()) and os.path.exists(step5_clean_output_path):
|
||||
self.csv_file.set_path(step5_clean_output_path)
|
||||
|
||||
def _on_run_single_clicked(self):
|
||||
from src.gui.core.event_bus import global_event_bus
|
||||
|
||||
|
||||
Reference in New Issue
Block a user