EnergySpectrumAnalyer/src/MeasureAnalysisParticleCountPlotView/BatchEnergyScaleDialog.cpp

394 lines
18 KiB
C++

#include "BatchEnergyScaleDialog.h"
#include "ui_BatchEnergyScaleDialog.h"
#include <QDoubleSpinBox>
#include "DataProcessWorkPool.h"
#include "GlobalDefine.h"
#include "MeasureAnalysisProjectModel.h"
#include <QDir>
#include <QMessageBox>
#include "EnergyScaleDataModel.h"
#include <QDebug>
BatchEnergyScaleDialog::BatchEnergyScaleDialog(QWidget* parent)
: QDialog(parent)
, ui(new Ui::BatchEnergyScaleDialog)
, _energy_scale_data_model(std::make_unique<EnergyScaleDataModel>())
{
ui->setupUi(this);
this->setWindowTitle(QString(QStringLiteral(u"多通道能量刻度")));
this->setWindowFlags(Qt::Dialog | Qt::WindowCloseButtonHint);
this->setWindowModality(Qt::WindowModal);
this->setModal(false);
ui->tablew_process_data->horizontalHeader()->setSectionResizeMode(QHeaderView::ResizeToContents);
ui->tablew_process_data->horizontalHeader()->setSectionResizeMode(
ui->tablew_process_data->columnCount() - 1, QHeaderView::ResizeToContents);
ui->tablew_process_data->horizontalHeader()->setDefaultAlignment(Qt::AlignLeft | Qt::AlignVCenter);
ui->filter_set_energy_combo_box->addItem(QStringLiteral(u"所有设置能量"));
auto filterFunc = [this](){
ui->tablew_process_data->setCurrentItem(nullptr);
auto row_count = ui->tablew_process_data->rowCount();
const QString& channel_filter_text = ui->filter_channel_combo_box->currentText();
const QString& set_energy_filter_text = ui->filter_set_energy_combo_box->currentText();
for (int i = row_count - 1; i >= 0; i--) {
const QString& channel = ui->tablew_process_data->item(i, 0)->text();
const QString& set_energy = ui->tablew_process_data->item(i, 2)->text();
bool is_match_channel = false;
if (channel_filter_text != QStringLiteral(u"所有通道")) {
is_match_channel = (channel_filter_text == channel) ? false : true;
}
bool is_match_set_energy = false;
if (set_energy_filter_text != QStringLiteral(u"所有设置能量")) {
is_match_set_energy = (set_energy_filter_text == set_energy) ? false : true;
}
bool is_hidden = is_match_channel || is_match_set_energy;
ui->tablew_process_data->setRowHidden(i, is_hidden);
}
};
connect(ui->filter_channel_combo_box, &QComboBox::currentTextChanged, filterFunc);
connect(ui->filter_set_energy_combo_box, &QComboBox::currentTextChanged, filterFunc);
connect(ui->btn_all_select, &QPushButton::clicked, [this](){
ui->tablew_process_data->setCurrentItem(nullptr);
auto row_count = ui->tablew_process_data->rowCount();
for (int i = 0; i < row_count; ++i) {
if (ui->tablew_process_data->isRowHidden(i)) {
continue;
}
auto item = ui->tablew_process_data->item(i, 0);
if (item) {
item->setCheckState(Qt::Checked);
}
}
});
connect(ui->btn_reserve_select, &QPushButton::clicked, [this](){
ui->tablew_process_data->setCurrentItem(nullptr);
auto row_count = ui->tablew_process_data->rowCount();
for (int i = 0; i < row_count - 1; i++) {
if (ui->tablew_process_data->isRowHidden(i)) {
continue;
}
auto item = ui->tablew_process_data->item(i, 0);
if (item) {
Qt::CheckState check_state = (item->checkState() == Qt::Checked) ? Qt::Unchecked : Qt::Checked;
item->setCheckState(check_state);
}
}
});
connect(ui->btn_remove_selected, &QPushButton::clicked, [this](){
auto row_count = ui->tablew_process_data->rowCount();
for (int row = row_count - 1; row >= 0; --row) {
QTableWidgetItem* item = ui->tablew_process_data->item(row, 0);
if (Qt::Unchecked == item->checkState())
continue;
QPushButton* btn_remove_row = dynamic_cast<QPushButton*>(ui->tablew_process_data->cellWidget(row, 8));
if (btn_remove_row) {
ui->tablew_process_data->removeRow(row);
btn_remove_row->deleteLater();
this->updateSetEnergyFilter();
}
}
if ( row_count > ui->tablew_process_data->rowCount() ) {
this->saveEnergyScaleData();
}
});
connect(ui->btn_fit, &QPushButton::clicked, this, &BatchEnergyScaleDialog::onFitBtnClickedProcess);
connect(ui->btn_save, &QPushButton::clicked, [this](){
this->saveEnergyScaleData();
});
connect(ui->btn_apply, &QPushButton::clicked, [this](){
this->applyEnergyScaleFitResultData();
});
}
BatchEnergyScaleDialog::~BatchEnergyScaleDialog()
{
qDebug() << "~BatchEnergyScaleDialog";
delete ui;
}
void BatchEnergyScaleDialog::SetProjectName(const QString &project_name)
{
this->_project_name = project_name;
}
void BatchEnergyScaleDialog::SetChannelNameList(const QStringList &ch_name_list)
{
this->_channel_name_list = ch_name_list;
ui->filter_channel_combo_box->clear();
ui->filter_channel_combo_box->addItem(QString(QStringLiteral(u"所有通道")));
ui->filter_channel_combo_box->addItems(ch_name_list);
}
void BatchEnergyScaleDialog::SetPeakResultDataModel(QAbstractTableModel* peaks_result_model)
{
_peaks_result_model = peaks_result_model;
}
void BatchEnergyScaleDialog::SetViewWorkspace(const QString &workspace)
{
this->_workspace = workspace;
QDir workspace_dir(this->_workspace);
const QString& energy_scale_data_filename = workspace_dir.filePath(QStringLiteral(u"多通道能量刻度拟合.json"));
this->_energy_scale_data_model->SetDataFilename(energy_scale_data_filename);
}
void BatchEnergyScaleDialog::onSelectedScaleRange(double min, double max)
{
if (!_peaks_result_model) {
return;
}
QDialog set_energy_dlg(this, Qt::Dialog | Qt::WindowCloseButtonHint);
set_energy_dlg.setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
set_energy_dlg.setFixedSize(300, 100);
set_energy_dlg.setSizeGripEnabled(false);
set_energy_dlg.setWindowTitle(QString(QStringLiteral(u"设置刻度能量")));
QLabel* set_energy_label = new QLabel(QString(QStringLiteral(u"刻度能量:")));
QDoubleSpinBox* spinbox_set_energy = new QDoubleSpinBox();
spinbox_set_energy->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
spinbox_set_energy->setRange(0.0f, std::numeric_limits<double>::max());
spinbox_set_energy->setSingleStep(1.0f);
spinbox_set_energy->setDecimals(3);
QHBoxLayout* layout_input = new QHBoxLayout();
layout_input->addWidget(set_energy_label);
layout_input->addWidget(spinbox_set_energy);
QPushButton* btn_ok = new QPushButton(QStringLiteral(u"确认"));
connect(btn_ok, &QPushButton::clicked, &set_energy_dlg, &QDialog::accept);
QPushButton* btn_cancel = new QPushButton(QStringLiteral(u"取消"));
connect(btn_cancel, &QPushButton::clicked, &set_energy_dlg, &QDialog::reject);
QHBoxLayout* layout_btns = new QHBoxLayout();
layout_btns->addStretch();
layout_btns->addWidget(btn_ok);
layout_btns->addWidget(btn_cancel);
QVBoxLayout* layout = new QVBoxLayout(&set_energy_dlg);
layout->addLayout(layout_input);
layout->addStretch();
layout->addLayout(layout_btns);
if (QDialog::Accepted == set_energy_dlg.exec()) {
bool b_has_new_data = false;
double set_energy = spinbox_set_energy->value();
for (int i = 0; i < _peaks_result_model->rowCount(); i++) {
const QString& channel_name = _peaks_result_model->data(_peaks_result_model->index(i, 0)).toString();
int peak_pos = _peaks_result_model->data(_peaks_result_model->index(i, 1)).toInt();
int peak_fwhm = _peaks_result_model->data(_peaks_result_model->index(i, 6)).toInt();
if (min < peak_pos && peak_pos < max ) {
int row = ui->tablew_process_data->rowCount();
ui->tablew_process_data->insertRow(row);
ui->tablew_process_data->setItem(row, 0, new QTableWidgetItem(channel_name));
ui->tablew_process_data->item(row, 0)->setCheckState(Qt::Unchecked);
ui->tablew_process_data->setItem(row, 1, new QTableWidgetItem(QString::number(peak_pos)));
ui->tablew_process_data->setItem(row, 2, new QTableWidgetItem(QString::number(set_energy)));
ui->tablew_process_data->setItem(row, 3, new QTableWidgetItem);
ui->tablew_process_data->setItem(row, 4, new QTableWidgetItem);
ui->tablew_process_data->setItem(row, 5, new QTableWidgetItem(QString::number(peak_fwhm)));
ui->tablew_process_data->setItem(row, 6, new QTableWidgetItem);
ui->tablew_process_data->setItem(row, 7, new QTableWidgetItem);
QTableWidgetItem* item = new QTableWidgetItem;
ui->tablew_process_data->setItem(row, 8, item);
QPushButton* btn_remove_row = new QPushButton(QStringLiteral(u"删除"));
btn_remove_row->setMaximumWidth(35);
connect(btn_remove_row, &QPushButton::clicked, [this, item, btn_remove_row]() {
item->setCheckState(Qt::Unchecked);
int remove_row = item->row();
ui->tablew_process_data->removeRow(remove_row);
btn_remove_row->deleteLater();
this->updateSetEnergyFilter();
this->saveEnergyScaleData();
});
ui->tablew_process_data->setCellWidget(row, 8, btn_remove_row);
this->insertSetEnergyValueToFilter(set_energy);
b_has_new_data = true;
}
}
if (b_has_new_data) {
this->saveEnergyScaleData();
}
}
}
void BatchEnergyScaleDialog::insertSetEnergyValueToFilter(double energy)
{
int count = 0;
int index = ui->filter_set_energy_combo_box->findText(QString::number(energy));
if (index >= 0) {
count = ui->filter_set_energy_combo_box->itemData(index).toInt() + 1;
ui->filter_set_energy_combo_box->setItemData(index, count);
} else {
ui->filter_set_energy_combo_box->addItem(QString::number(energy), count);
}
}
void BatchEnergyScaleDialog::updateSetEnergyFilter()
{
int item_count = ui->filter_set_energy_combo_box->count();
for (int index = item_count - 1; index > 0; --index) {
int count = ui->filter_set_energy_combo_box->itemData(index).toInt();
count = count - 1;
ui->filter_set_energy_combo_box->setItemData(index, count);
if (0 == count) {
int current_index = ui->filter_set_energy_combo_box->currentIndex();
if (index == current_index) {
ui->filter_set_energy_combo_box->setCurrentIndex(0);
}
ui->filter_set_energy_combo_box->removeItem(index);
}
}
}
void BatchEnergyScaleDialog::LoadEnergyScaleData()
{
auto row_count = ui->tablew_process_data->rowCount();
for (int row = row_count - 1; row >= 0; --row) {
QPushButton* btn_remove_row = dynamic_cast<QPushButton*>(ui->tablew_process_data->cellWidget(row, 8));
if (btn_remove_row) {
ui->tablew_process_data->removeRow(row);
btn_remove_row->deleteLater();
this->updateSetEnergyFilter();
}
}
if (!this->_energy_scale_data_model->LoadData()) {
return;
}
for (const QString& channel_name : this->_channel_name_list) {
std::vector<std::vector<double>> energy_scale_fit_data_list = this->_energy_scale_data_model->GetFitData(channel_name);
for (const std::vector<double>& fit_data_item : energy_scale_fit_data_list) {
int row = ui->tablew_process_data->rowCount();
ui->tablew_process_data->insertRow(row);
ui->tablew_process_data->setItem(row, 0, new QTableWidgetItem(channel_name));
ui->tablew_process_data->item(row, 0)->setCheckState(Qt::Unchecked);
ui->tablew_process_data->setItem(row, 1, new QTableWidgetItem(QString::number(fit_data_item[0])));
ui->tablew_process_data->setItem(row, 2, new QTableWidgetItem(QString::number(fit_data_item[1])));
ui->tablew_process_data->setItem(row, 3, new QTableWidgetItem(QString::number(fit_data_item[2])));
ui->tablew_process_data->setItem(row, 4, new QTableWidgetItem(QString::number(fit_data_item[3])));
ui->tablew_process_data->setItem(row, 5, new QTableWidgetItem(QString::number(fit_data_item[4])));
ui->tablew_process_data->setItem(row, 6, new QTableWidgetItem(QString::number(fit_data_item[5])));
ui->tablew_process_data->setItem(row, 7, new QTableWidgetItem(QString::number(fit_data_item[6])));
QTableWidgetItem* item = new QTableWidgetItem;
ui->tablew_process_data->setItem(row, 8, item);
QPushButton* btn_remove_row = new QPushButton(QStringLiteral(u"删除"));
btn_remove_row->setMaximumWidth(35);
connect(btn_remove_row, &QPushButton::clicked, [this, item, btn_remove_row]() {
item->setCheckState(Qt::Unchecked);
int remove_row = item->row();
ui->tablew_process_data->removeRow(remove_row);
btn_remove_row->deleteLater();
this->updateSetEnergyFilter();
this->saveEnergyScaleData();
});
ui->tablew_process_data->setCellWidget(row, 8, btn_remove_row);
this->insertSetEnergyValueToFilter(fit_data_item[1]);
}
}
}
void BatchEnergyScaleDialog::saveEnergyScaleData()
{
QMap<QString, std::vector<std::vector<double> > > fit_data;
for (int i = 0; i < ui->tablew_process_data->rowCount(); i++) {
std::vector<double> fit_data_item;
const QString& channel_name = ui->tablew_process_data->item(i, 0)->text();
double peak_pos_addr = ui->tablew_process_data->item(i, 1)->text().toDouble();
double set_energy = ui->tablew_process_data->item(i, 2)->text().toDouble();
double fit_energy = ui->tablew_process_data->item(i, 3)->text().toDouble();
double energy_diff = ui->tablew_process_data->item(i, 4)->text().toDouble();
double peak_fwhm = ui->tablew_process_data->item(i, 5)->text().toDouble();
double fit_fwhm = ui->tablew_process_data->item(i, 6)->text().toDouble();
double fwhm_diff = ui->tablew_process_data->item(i, 7)->text().toDouble();
fit_data_item.push_back(peak_pos_addr);
fit_data_item.push_back(set_energy);
fit_data_item.push_back(fit_energy);
fit_data_item.push_back(energy_diff);
fit_data_item.push_back(peak_fwhm);
fit_data_item.push_back(fit_fwhm);
fit_data_item.push_back(fwhm_diff);
fit_data[channel_name].push_back(fit_data_item);
}
for (const QString& channel_name : fit_data.keys()) {
this->_energy_scale_data_model->SetFitData(channel_name, fit_data[channel_name]);
this->_energy_scale_data_model->SetEnergyFitDegree(channel_name, 0);
this->_energy_scale_data_model->SetEnergyFitResultCoeffs(channel_name, {});
this->_energy_scale_data_model->SetFwhmFitResultCoeffs(channel_name, {});
}
this->_energy_scale_data_model->SaveData();
}
void BatchEnergyScaleDialog::onFitBtnClickedProcess()
{
QMap<QString, int> fit_degree_map;
DataProcessWorkPool::ChannelEnergyScaleFittingTask::FitDataMap channel_energy_scale_fit_data_map;
for (int i = 0; i < ui->tablew_process_data->rowCount(); i++) {
const QString& channel_name = ui->tablew_process_data->item(i, 0)->text();
int peak_pos = ui->tablew_process_data->item(i, 1)->text().toInt();
double energy = ui->tablew_process_data->item(i, 2)->text().toDouble();
int peak_fwhm = ui->tablew_process_data->item(i, 5)->text().toInt();
channel_energy_scale_fit_data_map[channel_name].insert(peak_pos, QList<double>() << energy << peak_fwhm);
fit_degree_map[channel_name] = 1;
}
QStringList data_except_channel_name_list;
for (auto it = channel_energy_scale_fit_data_map.begin(); it != channel_energy_scale_fit_data_map.end(); ++it) {
const QString& channel_name = it.key();
const QMap<int, QList<double> >& fit_data = it.value();
if (fit_data.size() < 2) {
data_except_channel_name_list << channel_name;
}
}
if (data_except_channel_name_list.size() > 0) {
const QString& warn_msg = QStringLiteral(u"请为以下通道设置拟合数据:%1").arg(data_except_channel_name_list.join(QStringLiteral(u",")));
LOG_WARN(warn_msg);
QMessageBox::warning(this, QStringLiteral(u"警告"), warn_msg);
return;
}
if (!channel_energy_scale_fit_data_map.empty()) {
ui->btn_apply->setEnabled(false);
auto channel_erergy_scale_fit_task = new DataProcessWorkPool::ChannelEnergyScaleFittingTask;
channel_erergy_scale_fit_task->SetResultDir(this->_workspace);
channel_erergy_scale_fit_task->SetData(channel_energy_scale_fit_data_map, fit_degree_map);
channel_erergy_scale_fit_task->SetFinishedNotifier(this, "onEnergyScaleFitFinished", this->_project_name);
channel_erergy_scale_fit_task->StartTask();
}
}
void BatchEnergyScaleDialog::onEnergyScaleFitFinished(const QString &project_name)
{
Q_UNUSED(project_name);
this->LoadEnergyScaleData();
}
void BatchEnergyScaleDialog::applyEnergyScaleFitResultData()
{
if ( this->_energy_scale_data_model->IsValid() ) {
MeasureAnalysisProjectModel* project_model = ProjectList::Instance()->GetProjectModel(this->_project_name);
if (project_model == nullptr) {
return;
}
QDir project_dir(project_model->GetProjectDir());
const QString& energy_scale_data_filename = project_dir.filePath(QStringLiteral(u"能量刻度.json"));
QDir result_dir(this->_workspace);
const QString& energy_scale_result_filename = result_dir.filePath(QStringLiteral(u"多通道能量刻度拟合.json"));
if (QFile::copy(energy_scale_result_filename, energy_scale_data_filename)) {
project_model->SetEnergyScaleFilename(energy_scale_data_filename);
}
} else {
}
}
void BatchEnergyScaleDialog::energyScaleDataChange()
{
this->_is_fit_finished = false;
ui->btn_apply->setEnabled(false);
}
void BatchEnergyScaleDialog::closeEvent(QCloseEvent *e)
{
emit close();
}