旧 GUI 张冠李戴修复:step6/step8 ML 训练 CSV 强制读 Step 6 特征结果 + step3 默认算法切到 goodman
This commit is contained in:
@ -199,7 +199,43 @@ class Step6FeaturePanel(QWidget):
|
|||||||
glint_path = os.path.join(self.work_dir or '', glint_path).replace('\\', '/')
|
glint_path = os.path.join(self.work_dir or '', glint_path).replace('\\', '/')
|
||||||
self.glint_mask_file.set_path(glint_path)
|
self.glint_mask_file.set_path(glint_path)
|
||||||
|
|
||||||
# 4. 自动填充输出路径(基于工作目录)
|
# 4. 自动填充去耀斑影像路径(上游 Step 3 的输出,修复张冠李戴)
|
||||||
|
deglint_path = None
|
||||||
|
if pipeline and hasattr(pipeline, 'step_outputs'):
|
||||||
|
step3_outputs = getattr(pipeline, 'step_outputs', {}).get('step3', {})
|
||||||
|
deglint_path = (
|
||||||
|
step3_outputs.get('deglint_image')
|
||||||
|
or step3_outputs.get('output_path')
|
||||||
|
or step3_outputs.get('output_file')
|
||||||
|
or step3_outputs.get('deglint_img_path')
|
||||||
|
)
|
||||||
|
# 回退:从 step3 面板 widget 直接读取(可能是相对路径)
|
||||||
|
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 ""
|
||||||
|
# 兜底:扫描 3_deglint 目录下的 .bsq(优先 goodman,兼容 kutser/插值)
|
||||||
|
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')
|
||||||
|
]
|
||||||
|
# 优先匹配 goodman(默认算法),其次按文件名排序保证稳定
|
||||||
|
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:
|
||||||
|
# 若为相对路径,使用 work_dir 合成为绝对路径
|
||||||
|
if not os.path.isabs(deglint_path):
|
||||||
|
deglint_path = os.path.join(self.work_dir or '', deglint_path).replace('\\', '/')
|
||||||
|
existing_deglint = self.deglint_img_file.get_path()
|
||||||
|
if not existing_deglint or not existing_deglint.strip():
|
||||||
|
self.deglint_img_file.set_path(deglint_path)
|
||||||
|
|
||||||
|
# 5. 自动填充输出路径(基于工作目录)
|
||||||
if self.work_dir:
|
if self.work_dir:
|
||||||
output_dir = resolve_subdir(self.work_dir, 'spectral_feature')
|
output_dir = resolve_subdir(self.work_dir, 'spectral_feature')
|
||||||
os.makedirs(output_dir, exist_ok=True)
|
os.makedirs(output_dir, exist_ok=True)
|
||||||
@ -208,7 +244,7 @@ class Step6FeaturePanel(QWidget):
|
|||||||
else:
|
else:
|
||||||
self.output_file.set_path("")
|
self.output_file.set_path("")
|
||||||
|
|
||||||
# 5. 尝试从 Step5 Clean 界面读取已处理的清洗后 CSV 路径,自动填入本面板
|
# 6. 尝试从 Step5 Clean 界面读取已处理的清洗后 CSV 路径,自动填入本面板
|
||||||
main_window = self.window()
|
main_window = self.window()
|
||||||
if main_window and hasattr(main_window, 'step5_clean_panel'):
|
if main_window and hasattr(main_window, 'step5_clean_panel'):
|
||||||
step5_clean_output_path = main_window.step5_clean_panel.output_file.get_path()
|
step5_clean_output_path = main_window.step5_clean_panel.output_file.get_path()
|
||||||
|
|||||||
@ -137,6 +137,15 @@ class Step8MlTrainPanel(QWidget):
|
|||||||
self.feature_start.setText("374.285004")
|
self.feature_start.setText("374.285004")
|
||||||
params_layout.addRow("特征起始列:", self.feature_start)
|
params_layout.addRow("特征起始列:", self.feature_start)
|
||||||
|
|
||||||
|
# 特征起始列名提示:用记事本打开 training_spectra.csv 确认首个波长的精确表头
|
||||||
|
feature_start_hint = QLabel(
|
||||||
|
"提示:请使用记事本打开 training_spectra.csv 确认首个波长的精确表头名称"
|
||||||
|
"(如 374.285 或 374.285004)并在此填入,避免因浮点精度差异导致列名匹配失败。"
|
||||||
|
)
|
||||||
|
feature_start_hint.setWordWrap(True)
|
||||||
|
feature_start_hint.setStyleSheet("color: #666; font-size: 10px;")
|
||||||
|
params_layout.addRow(feature_start_hint)
|
||||||
|
|
||||||
self.cv_folds = QSpinBox()
|
self.cv_folds = QSpinBox()
|
||||||
self.cv_folds.setRange(2, 10)
|
self.cv_folds.setRange(2, 10)
|
||||||
self.cv_folds.setValue(3)
|
self.cv_folds.setValue(3)
|
||||||
@ -357,30 +366,20 @@ class Step8MlTrainPanel(QWidget):
|
|||||||
else:
|
else:
|
||||||
self.work_dir = None
|
self.work_dir = None
|
||||||
|
|
||||||
# 1. 尝试从 Step5 界面读取训练数据路径,并确保为绝对路径
|
# 1. 强制读 Step 6 的 training_spectra.csv(光谱特征提取结果)
|
||||||
# 修复张冠李戴:原代码 main_window.step5_panel 不存在,正确属性是 step5_clean_panel
|
# 修复张冠李戴:原链路 STEP_DATA_SOURCE['training_spectra_csv'] → step5_clean_panel
|
||||||
|
# 错误地指向了 Step 5 的 processed_data.csv(纯清洗数据,不含光谱特征),
|
||||||
|
# 实际 ML 训练需要的特征数据来自 Step 6 的 6_Spectral_Feature_Extraction/training_spectra.csv
|
||||||
main_window = self.window()
|
main_window = self.window()
|
||||||
step5_output = get_step_output_path(
|
existing_training_csv = self.training_csv_file.get_path()
|
||||||
main_window, 'training_spectra_csv', work_dir=self.work_dir,
|
if not existing_training_csv or not existing_training_csv.strip():
|
||||||
widget_attr='output_file', fallback_key='step6_feature',
|
if self.work_dir:
|
||||||
)
|
step6_dir = resolve_subdir(self.work_dir, 'spectral_feature')
|
||||||
if step5_output:
|
step6_training_csv = os.path.join(
|
||||||
self.training_csv_file.set_path(step5_output)
|
step6_dir, 'training_spectra.csv'
|
||||||
else:
|
).replace('\\', '/')
|
||||||
# 回退:从 Step5 的 config 字典中查找可能的键名
|
if step6_training_csv:
|
||||||
step5_panel = getattr(main_window, 'step5_clean_panel', None)
|
self.training_csv_file.set_path(step6_training_csv)
|
||||||
if step5_panel and hasattr(step5_panel, 'get_config'):
|
|
||||||
step5_cfg = step5_panel.get_config()
|
|
||||||
step5_csv = (
|
|
||||||
step5_cfg.get('training_csv_path')
|
|
||||||
or step5_cfg.get('output_file')
|
|
||||||
or step5_cfg.get('csv_path')
|
|
||||||
or step5_cfg.get('output_csv')
|
|
||||||
)
|
|
||||||
if step5_csv:
|
|
||||||
if not os.path.isabs(step5_csv):
|
|
||||||
step5_csv = os.path.join(self.work_dir or '', step5_csv).replace('\\', '/')
|
|
||||||
self.training_csv_file.set_path(step5_csv)
|
|
||||||
|
|
||||||
# 2. 自动填充输出文件路径(基于工作目录和输入文件名)
|
# 2. 自动填充输出文件路径(基于工作目录和输入文件名)
|
||||||
# 输入是 training_spectra.csv → 输出 {work_dir}/7_Water_Quality_Indices/training_spectra_indices.csv
|
# 输入是 training_spectra.csv → 输出 {work_dir}/7_Water_Quality_Indices/training_spectra_indices.csv
|
||||||
|
|||||||
@ -238,15 +238,19 @@ class Step8NonEmpiricalPanel(QWidget):
|
|||||||
# 借用父组件的 window() 方法,安全绕过当前类的命名冲突
|
# 借用父组件的 window() 方法,安全绕过当前类的命名冲突
|
||||||
parent_widget = self.parentWidget()
|
parent_widget = self.parentWidget()
|
||||||
main_window = parent_widget.window() if parent_widget else None
|
main_window = parent_widget.window() if parent_widget else None
|
||||||
# 1. 尝试从 Step5(数据清洗)读取训练光谱 CSV(修复张冠李戴:原 main_window.step5_panel 不存在)
|
# 1. 强制读 Step 6 的 training_spectra.csv(光谱特征提取结果)
|
||||||
step5_output_path = get_step_output_path(
|
# 修复张冠李戴:原链路 STEP_DATA_SOURCE['training_spectra_csv'] → step5_clean_panel
|
||||||
main_window, 'training_spectra_csv', work_dir=self.work_dir,
|
# 错误地指向 Step 5 的 processed_data.csv(纯清洗数据,不含光谱特征),
|
||||||
widget_attr='output_file', fallback_key='step6_feature',
|
# 实际非经验建模需要的特征数据来自 Step 6 的 6_Spectral_Feature_Extraction/training_spectra.csv
|
||||||
)
|
existing_csv = self.training_csv_file.get_path()
|
||||||
if step5_output_path:
|
if not existing_csv or not existing_csv.strip():
|
||||||
existing = self.training_csv_file.get_path()
|
if self.work_dir:
|
||||||
if not existing or not existing.strip():
|
step6_dir = resolve_subdir(self.work_dir, 'spectral_feature')
|
||||||
self.training_csv_file.set_path(step5_output_path)
|
step6_training_csv = os.path.join(
|
||||||
|
step6_dir, 'training_spectra.csv'
|
||||||
|
).replace('\\', '/')
|
||||||
|
if step6_training_csv:
|
||||||
|
self.training_csv_file.set_path(step6_training_csv)
|
||||||
|
|
||||||
# 2. 自动填充输出目录(8_Regression_Modeling)
|
# 2. 自动填充输出目录(8_Regression_Modeling)
|
||||||
if self.work_dir:
|
if self.work_dir:
|
||||||
|
|||||||
@ -1367,7 +1367,7 @@ class WaterQualityGUI(QMainWindow):
|
|||||||
self.step_default_outputs = {
|
self.step_default_outputs = {
|
||||||
'step1': "1_water_mask/water_mask_from_ndwi.dat",
|
'step1': "1_water_mask/water_mask_from_ndwi.dat",
|
||||||
'step2': "2_Glint_Detection/severe_glint_area.dat",
|
'step2': "2_Glint_Detection/severe_glint_area.dat",
|
||||||
'step3': "3_deglint/deglint_kutser.bsq",
|
'step3': "3_deglint/deglint_goodman.bsq",
|
||||||
'step4_sampling': "4_sampling/sampling_spectra.csv",
|
'step4_sampling': "4_sampling/sampling_spectra.csv",
|
||||||
'step5_clean': "5_Data_Cleaning/processed_data.csv",
|
'step5_clean': "5_Data_Cleaning/processed_data.csv",
|
||||||
'step6_feature': "6_Spectral_Feature_Extraction/training_spectra.csv",
|
'step6_feature': "6_Spectral_Feature_Extraction/training_spectra.csv",
|
||||||
@ -2361,9 +2361,11 @@ class WaterQualityGUI(QMainWindow):
|
|||||||
deglint_path = work_path / rel_path
|
deglint_path = work_path / rel_path
|
||||||
if deglint_path.exists():
|
if deglint_path.exists():
|
||||||
return str(deglint_path)
|
return str(deglint_path)
|
||||||
# 还要检查插值方法生成的文件
|
# 还要检查 Kutser 算法输出与插值方法生成的文件
|
||||||
deglint_dir = work_path / "3_deglint"
|
deglint_dir = work_path / "3_deglint"
|
||||||
if deglint_dir.exists():
|
if deglint_dir.exists():
|
||||||
|
for file_path in deglint_dir.glob("deglint_*.bsq"):
|
||||||
|
return str(file_path)
|
||||||
for file_path in deglint_dir.glob("interpolated_*.bsq"):
|
for file_path in deglint_dir.glob("interpolated_*.bsq"):
|
||||||
return str(file_path)
|
return str(file_path)
|
||||||
elif rel_path:
|
elif rel_path:
|
||||||
|
|||||||
Reference in New Issue
Block a user