Files
WQ_GUI/tmp_concentration_rescue.py

239 lines
8.6 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
Step10 面板 - 浓度反演(基于 QAA 物理反演的二次反演)
"""
import os
from PyQt5.QtWidgets import (
QWidget, QVBoxLayout, QGroupBox, QFormLayout, QHBoxLayout,
QLabel, QCheckBox, QPushButton, QMessageBox, QComboBox,
QFileDialog,
)
from PyQt5.QtGui import QFont
from PyQt5.QtCore import Qt
from src.gui.components.custom_widgets import FileSelectWidget
from src.gui.styles import ModernStylesheet
class Step10ConcentrationPanel(QWidget):
"""步骤10浓度反演物理模型二次反演"""
def __init__(self, parent=None):
super().__init__(parent)
self.init_ui()
def init_ui(self):
layout = QVBoxLayout()
title = QLabel("步骤10浓度反演物理模型二次反演")
title.setFont(QFont("Arial", 12, QFont.Bold))
layout.addWidget(title)
# 输入 QAA 结果文件
self.input_file = FileSelectWidget(
"QAA 结果文件:",
"CSV Files (*.csv);;All Files (*.*)"
)
self.input_file.line_edit.setPlaceholderText(
"选择 Step 8 输出的 a_lambda_results.csv"
)
layout.addWidget(self.input_file)
# 输出路径
self.output_file = FileSelectWidget(
"输出文件:",
"CSV Files (*.csv);;All Files (*.*)",
mode="save"
)
self.output_file.line_edit.setPlaceholderText(
"自动生成到 9_Concentration或手动指定..."
)
layout.addWidget(self.output_file)
# 选择反演指标
indicators_group = QGroupBox("选择反演指标")
indicators_layout = QFormLayout()
self.chla_check = QCheckBox("叶绿素 A (Chl-a)")
self.chla_check.setChecked(True)
self.cdom_check = QCheckBox("CDOM 吸收系数 a_dg(440)")
self.cdom_check.setChecked(True)
self.turbidity_check = QCheckBox("浊度 (Turbidity)")
self.turbidity_check.setChecked(True)
self.tn_check = QCheckBox("总氮 (TN)")
self.tn_check.setChecked(True)
self.tp_check = QCheckBox("总磷 (TP)")
self.tp_check.setChecked(True)
chk_layout = QVBoxLayout()
chk_layout.setSpacing(6)
for cb in [self.chla_check, self.cdom_check,
self.turbidity_check, self.tn_check, self.tp_check]:
chk_layout.addWidget(cb)
indicators_layout.addRow("水质参数:", chk_layout)
indicators_group.setLayout(indicators_layout)
layout.addWidget(indicators_group)
# 水体类型(用于比吸收系数自适应)
lake_group = QGroupBox("水体类型")
lake_layout = QFormLayout()
self.lake_case_combo = QComboBox()
self.lake_case_combo.addItems([
"通用 (medium)",
"oligotrophic_clear寡营养清澈",
"bloom_dominant藻华主导",
"turbid_mixed高浊混合",
])
self.lake_case_combo.setCurrentIndex(0)
lake_layout.addRow("水体类型:", self.lake_case_combo)
lake_group.setLayout(lake_layout)
layout.addWidget(lake_group)
# 启用步骤
self.enable_checkbox = QCheckBox("启用此步骤")
self.enable_checkbox.setChecked(False)
layout.addWidget(self.enable_checkbox)
# 独立运行按钮
self.run_btn = QPushButton("执行浓度反演")
self.run_btn.setStyleSheet(ModernStylesheet.get_button_stylesheet('success'))
self.run_btn.clicked.connect(self.run_step)
layout.addWidget(self.run_btn)
layout.addStretch()
self.setLayout(layout)
def _get_default_work_dir(self) -> str:
if hasattr(self, 'work_dir') and self.work_dir:
return str(self.work_dir)
mw = self.window()
if mw and hasattr(mw, 'work_dir') and mw.work_dir:
return str(mw.work_dir)
return ""
def browse_output_path(self):
current = self.output_file.get_path().strip()
if current:
initial_dir = os.path.dirname(current)
initial_file = os.path.basename(current)
else:
initial_dir = ""
initial_file = ""
if not initial_dir or not os.path.isdir(initial_dir):
work_dir = self._get_default_work_dir()
initial_dir = os.path.join(work_dir, "9_Concentration") if work_dir else ""
if initial_dir and not os.path.isdir(initial_dir):
os.makedirs(initial_dir, exist_ok=True)
file_path, _ = QFileDialog.getSaveFileName(
self, "保存输出文件",
os.path.join(initial_dir, initial_file) if initial_file else initial_dir,
"CSV Files (*.csv);;All Files (*.*)"
)
if file_path:
self.output_file.set_path(file_path)
def get_config(self) -> dict:
enabled_indicators = []
if self.chla_check.isChecked():
enabled_indicators.append('chla')
if self.cdom_check.isChecked():
enabled_indicators.append('cdom')
if self.turbidity_check.isChecked():
enabled_indicators.append('turbidity')
if self.tn_check.isChecked():
enabled_indicators.append('tn')
if self.tp_check.isChecked():
enabled_indicators.append('tp')
lake_case_map = {
0: "medium",
1: "oligotrophic_clear",
2: "bloom_dominant",
3: "turbid_mixed",
}
lake_case = lake_case_map.get(self.lake_case_combo.currentIndex(), "medium")
return {
'input_csv': self.input_file.get_path(),
'output_csv': self.output_file.get_path(),
'enabled_indicators': enabled_indicators,
'lake_case': lake_case,
}
def set_config(self, config: dict):
if 'input_csv' in config:
self.input_file.set_path(config['input_csv'])
if 'output_csv' in config:
self.output_file.set_path(config['output_csv'])
def update_from_config(self, work_dir=None, pipeline=None):
if work_dir:
self.work_dir = work_dir
elif hasattr(self, 'work_dir') and self.work_dir:
pass
else:
self.work_dir = None
if self.work_dir:
step8_dir = os.path.join(self.work_dir, "8_QAA_Inversion")
if os.path.isdir(step8_dir):
candidates = []
for f in sorted(os.listdir(step8_dir)):
if f.lower().endswith('.csv'):
candidates.append(os.path.join(step8_dir, f))
if candidates:
self.input_file.set_path(candidates[0])
conc_dir = os.path.join(self.work_dir, "9_Concentration")
os.makedirs(conc_dir, exist_ok=True)
output_path = os.path.join(conc_dir, "final_concentrations.csv").replace('\\', '/')
self.output_file.set_path(output_path)
def run_step(self):
input_path = self.input_file.get_path()
if not input_path:
QMessageBox.warning(self, "输入错误", "请选择 QAA 结果文件!")
return
main_window = self.window()
if hasattr(main_window, 'run_single_step'):
config = {'step9_concentration': self.get_config()}
main_window.run_single_step('step9_concentration', config)
else:
self._run_concentration_direct()
def _run_concentration_direct(self):
from src.core.algorithms.concentration_inversion import ConcentrationPipeline
input_path = self.input_file.get_path()
output_path = self.output_file.get_path()
if not output_path:
work_dir = self._get_default_work_dir()
conc_dir = os.path.join(work_dir, "9_Concentration") if work_dir else ""
if conc_dir and not os.path.isdir(conc_dir):
os.makedirs(conc_dir, exist_ok=True)
output_path = os.path.join(conc_dir, "final_concentrations.csv").replace('\\', '/')
lake_case_map = {
0: "medium",
1: "oligotrophic_clear",
2: "bloom_dominant",
3: "turbid_mixed",
}
lake_case = lake_case_map.get(self.lake_case_combo.currentIndex(), "medium")
try:
pipeline = ConcentrationPipeline(lake_case=lake_case)
result_csv = pipeline.run_pipeline(input_path, output_path)
QMessageBox.information(
self, "执行成功",
f"浓度反演完成!\n结果已保存到:\n{result_csv}"
)
except Exception as e:
QMessageBox.critical(self, "执行错误", f"浓度反演失败:\n{str(e)}")