1、调整代码结构;2、添加多通道能量刻度;

This commit is contained in:
徐海 2026-03-17 18:38:50 +08:00
parent 0564843147
commit bfd9485c8b
15 changed files with 570 additions and 317 deletions

View File

@ -85,6 +85,9 @@ void CustomQwtPlot::AddMarker(QwtPlotMarker *marker, const QString &marker_name,
QPen pen = curve->pen(); QPen pen = curve->pen();
pen.setWidth(2); pen.setWidth(2);
marker->setLinePen(pen); marker->setLinePen(pen);
QwtText label_text = marker->label();
label_text.setColor(Qt::black);
marker->setLabel(label_text);
marker->attach(this); marker->attach(this);
_markers[marker_name][postion] = marker; _markers[marker_name][postion] = marker;
} }

View File

@ -83,7 +83,7 @@ public:
void clearSelection(); void clearSelection();
signals: signals:
void selectionFinished(double minX, double maxX); void selectionFinished(double min_x, double max_x);
protected: protected:
virtual void move(const QPoint& pos) override; virtual void move(const QPoint& pos) override;

View File

@ -85,6 +85,31 @@ std::vector<FindPeaksBySvd::PeakInfo> FindPeaksBySvd::FindPeaks(const arma::mat
vec peak_region = spec_data_col1.subvec(Lc, Rc); vec peak_region = spec_data_col1.subvec(Lc, Rc);
double height = peak_region.max(); double height = peak_region.max();
uword HWP_idx = peak_region.index_max(); // 峰值位置 uword HWP_idx = peak_region.index_max(); // 峰值位置
// 计算半高宽(FWHM)
double half_height = height / 2.0;
int left_half = 0, right_half = peak_region.n_elem - 1;
// 找到左侧半高位置
for (int i = HWP_idx; i >= 0; i--) {
if (peak_region(i) <= half_height) {
left_half = i;
break;
}
}
// 找到右侧半高位置
for (int i = HWP_idx; i < peak_region.n_elem; i++) {
if (peak_region(i) <= half_height) {
right_half = i;
break;
}
}
// 计算半高宽(转换为原始坐标)
double fwhm = (right_half - left_half + 1);
// 计算峰面积(使用梯形法则)
double area = 0.0;
for (int i = 0; i < peak_region.n_elem - 1; i++) {
// 梯形面积 = (上底 + 下底) * 高 / 2
area += (peak_region(i) + peak_region(i + 1)) / 2.0;
}
// 峰中心 // 峰中心
int pl = round((Lc + Rc) / 2.0); int pl = round((Lc + Rc) / 2.0);
// 筛选有效峰:峰宽>2且中心DistV>0 // 筛选有效峰:峰宽>2且中心DistV>0
@ -98,6 +123,8 @@ std::vector<FindPeaksBySvd::PeakInfo> FindPeaksBySvd::FindPeaks(const arma::mat
peak_info.width = spec_data_col0.at(width); peak_info.width = spec_data_col0.at(width);
peak_info.height = height; peak_info.height = height;
peak_info.pos = spec_data_col0.at(pos); peak_info.pos = spec_data_col0.at(pos);
peak_info.fwhm = fwhm;
peak_info.area = area;
peak_info_vec.push_back(peak_info); peak_info_vec.push_back(peak_info);
} }
} }

View File

@ -13,7 +13,8 @@ public:
double width = 0.0f; // 峰所在数据区域的宽度 double width = 0.0f; // 峰所在数据区域的宽度
double height = 0.0f; // 峰所在数据区域的高度 double height = 0.0f; // 峰所在数据区域的高度
double pos = 0.0f; // 峰所在位置 double pos = 0.0f; // 峰所在位置
double fwhm = 0.0f; // 峰所在位置 double fwhm = 0.0f; // 峰的半高宽
double area = 0.0f; // 峰的面积
} PeakInfo; } PeakInfo;
std::vector<FindPeaksBySvd::PeakInfo> FindPeaks(const arma::mat& spec_data, int step_w = 7); std::vector<FindPeaksBySvd::PeakInfo> FindPeaks(const arma::mat& spec_data, int step_w = 7);

View File

@ -154,11 +154,13 @@ bool EveryChannelParticleDataSeparateTask::processEveryChannelParticleData()
*ch_particle_data_of << board_id << "," << channel_id << "," << address << "," << time << std::endl; *ch_particle_data_of << board_id << "," << channel_id << "," << address << "," << time << std::endl;
} }
} catch (const std::runtime_error& e) { } catch (const std::runtime_error& e) {
QString error = QString(QStringLiteral(u"处理%1发生运行时异常:%2")).arg(all_channel_particle_data_filename).arg(e.what()); const QString& e_what = QString::fromLatin1(e.what());
QString error = QString(QStringLiteral(u"处理%1发生运行时异常:%2")).arg(all_channel_particle_data_filename).arg(e_what);
LOG_ERROR(error) LOG_ERROR(error)
ret_ok = false; ret_ok = false;
} catch (const std::exception& e) { } catch (const std::exception& e) {
QString error = QString(QStringLiteral(u"处理%1异常:%2")).arg(all_channel_particle_data_filename).arg(e.what()); const QString& e_what = QString::fromLatin1(e.what());
QString error = QString(QStringLiteral(u"处理%1异常:%2")).arg(all_channel_particle_data_filename).arg(e_what);
LOG_ERROR(error) LOG_ERROR(error)
ret_ok = false; ret_ok = false;
} catch (...) { } catch (...) {
@ -303,15 +305,17 @@ bool EveryChannelParticleCountDataTask::processEveryChannelParticleData()
// all_channel_out.close(); // all_channel_out.close();
} catch (const std::runtime_error& e) { } catch (const std::runtime_error& e) {
QString error = QString(QStringLiteral(u"处理%1发生运行时异常:%2")).arg(all_channel_particle_data_filename).arg(e.what()); const QString& e_what = QString::fromLatin1(e.what());
QString error = QStringLiteral(u"处理%1发生运行时异常:%2").arg(all_channel_particle_data_filename).arg(e_what);
LOG_ERROR(error) LOG_ERROR(error)
ret_ok = false; ret_ok = false;
} catch (const std::exception& e) { } catch (const std::exception& e) {
QString error = QString(QStringLiteral(u"处理%1异常:%2")).arg(all_channel_particle_data_filename).arg(e.what()); const QString& e_what = QString::fromLatin1(e.what());
QString error = QStringLiteral(u"处理%1异常:%2").arg(all_channel_particle_data_filename).arg(e_what);
LOG_ERROR(error) LOG_ERROR(error)
ret_ok = false; ret_ok = false;
} catch (...) { } catch (...) {
QString error = QString(QStringLiteral(u"处理%1未知异常.").arg(all_channel_particle_data_filename)); QString error = QStringLiteral(u"处理%1未知异常.").arg(all_channel_particle_data_filename);
LOG_ERROR(error) LOG_ERROR(error)
ret_ok = false; ret_ok = false;
} }
@ -529,7 +533,8 @@ bool ParticleDataSortTask::processEveryChannelParticleData()
} }
} catch (const std::exception& e) { } catch (const std::exception& e) {
QString error = QString(QStringLiteral(u"处理%1异常:%2")).arg(all_channel_particle_data_filename).arg(e.what()); const QString& e_what = QString::fromLatin1(e.what());
QString error = QString(QStringLiteral(u"处理%1异常:%2")).arg(all_channel_particle_data_filename).arg(e_what);
LOG_ERROR(error) LOG_ERROR(error)
ret_ok = false; ret_ok = false;
} catch (...) { } catch (...) {
@ -576,7 +581,7 @@ bool AutoFindPeaksTask::IsValidSetWorkParameters() const
bool AutoFindPeaksTask::processTask() bool AutoFindPeaksTask::processTask()
{ {
QString result_filename = QDir(this->_result_dir).filePath("AutoFindPeaksResult.csv"); QString result_filename = QDir(this->_result_dir).filePath(QStringLiteral(u"自动寻峰结果.csv"));
std::ofstream out_file(QStrToSysPath(result_filename)); std::ofstream out_file(QStrToSysPath(result_filename));
std::string channel_str = QString(QStringLiteral(u"通道")).toStdString(); std::string channel_str = QString(QStringLiteral(u"通道")).toStdString();
std::string addr_str = QString(QStringLiteral(u"峰位")).toStdString(); std::string addr_str = QString(QStringLiteral(u"峰位")).toStdString();
@ -585,38 +590,48 @@ bool AutoFindPeaksTask::processTask()
std::string width_str = QString(QStringLiteral(u"峰宽")).toStdString(); std::string width_str = QString(QStringLiteral(u"峰宽")).toStdString();
std::string height_str = QString(QStringLiteral(u"峰高")).toStdString(); std::string height_str = QString(QStringLiteral(u"峰高")).toStdString();
std::string fwhm_str = QString(QStringLiteral(u"FWHM")).toStdString(); std::string fwhm_str = QString(QStringLiteral(u"FWHM")).toStdString();
out_file << channel_str << "," << addr_str << "," << left_addr_str << "," << lright_addr_str << "," << width_str << "," << height_str << "," << fwhm_str << "\n"; std::string area_str = QString(QStringLiteral(u"峰面积")).toStdString();
out_file << channel_str << "," << addr_str << "," << left_addr_str << "," << lright_addr_str
<< "," << width_str << "," << height_str << "," << fwhm_str << "," << area_str << "\n";
for (auto it = this->_data_files_set.begin(); it != this->_data_files_set.end(); ++it) { QStringList ch_count_data_name = this->_data_files_set.keys();
std::string channel = it.key().toStdString(); std::sort(ch_count_data_name.begin(), ch_count_data_name.end(), [](const QString& a, const QString& b) {
arma::mat data; int num_a = ExtractNumberFromString(a);
const std::string data_filename = QStrToSysPath(it.value().toString()); int num_b = ExtractNumberFromString(b);
if (!data.load(data_filename, arma::csv_ascii)) { return num_a < num_b;
QString error = QString(QStringLiteral(u"%1自动寻峰数据加载异常!")).arg(it.key()); });
LOG_WARN(error); for (const QString& ch_count_data_name : ch_count_data_name) {
continue; if (ch_count_data_name.contains(ch_count_data_name)) {
} const QString& ch_count_data_filename = this->_data_files_set.value(ch_count_data_name).toString();
FindPeaksBySvd peak_svd; std::string channel = ch_count_data_name.toStdString();
std::vector<FindPeaksBySvd::PeakInfo> peak_info_vec = peak_svd.FindPeaks(data, this->_step_win_width); arma::mat data;
if (!peak_info_vec.empty()) { const std::string data_filename = QStrToSysPath(ch_count_data_filename);
for(auto peak_info : peak_info_vec) { if (!data.load(data_filename, arma::csv_ascii)) {
int addr = peak_info.pos; QString error = QString(QStringLiteral(u"%1自动寻峰数据加载异常!")).arg(ch_count_data_name);
int left = peak_info.left; LOG_WARN(error);
int right = peak_info.left + peak_info.width; continue;
int width = peak_info.width;
int height = peak_info.height;
int fwhm = peak_info.fwhm;
out_file << channel << "," << addr << "," << left << "," << right << "," << width << "," << height << "," << fwhm << "\n";
double p_right(peak_info.left + peak_info.width);
qDebug() << QString::fromStdString(channel) << "," << peak_info.pos << "," << peak_info.left << "," << p_right << "," << peak_info.width << "," << peak_info.height << "," << peak_info.fwhm << "\n";
} }
} else { FindPeaksBySvd peak_svd;
const QString& error = QStringLiteral(u"%1自动寻峰异常!").arg(it.key()); std::vector<FindPeaksBySvd::PeakInfo> peak_info_vec = peak_svd.FindPeaks(data, this->_step_win_width);
LOG_WARN(error); if (!peak_info_vec.empty()) {
for(auto peak_info : peak_info_vec) {
int addr = peak_info.pos;
int left = peak_info.left;
int right = peak_info.left + peak_info.width;
int width = peak_info.width;
int height = peak_info.height;
int fwhm = peak_info.fwhm;
double area = peak_info.area;
out_file << channel << "," << addr << "," << left << "," << right << ","
<< width << "," << height << "," << fwhm << "," << area << "\n";
}
} else {
const QString& error = QStringLiteral(u"%1自动寻峰异常!").arg(ch_count_data_name);
LOG_WARN(error);
}
const QString& info = QStringLiteral(u"%1自动寻峰完成").arg(ch_count_data_name);
LOG_INFO(info);
} }
const QString& info = QStringLiteral(u"%1自动寻峰完成").arg(it.key());
LOG_INFO(info);
} }
const QString& project_name = GetProjectName(); const QString& project_name = GetProjectName();

View File

@ -4,6 +4,7 @@
#include "MainWindow.h" #include "MainWindow.h"
#include "QsLog.h" #include "QsLog.h"
#include <QTextCodec> #include <QTextCodec>
#include <QRegularExpression>
#include <QDebug> #include <QDebug>
// 转换Qt字符串路径为系统编码的C字符串解决中文路径问题 // 转换Qt字符串路径为系统编码的C字符串解决中文路径问题
@ -22,6 +23,16 @@ static const char* QStrToSysPath(const QString& qstr_path)
return sys_path.c_str(); return sys_path.c_str();
} }
static int ExtractNumberFromString(const QString& str) {
int ret_num = -1;
QRegularExpression regex("\\d+");
QRegularExpressionMatch match = regex.match(str);
if (match.hasMatch()) {
ret_num = match.captured().toInt();
}
return ret_num;
};
#define STATUS_BAR_MSG(msg) \ #define STATUS_BAR_MSG(msg) \
{ \ { \

View File

@ -1,15 +1,39 @@
#include "BatchEneryScaleDialog.h" #include "BatchEneryScaleDialog.h"
#include "ui_BatchEneryScaleDialog.h" #include "ui_BatchEneryScaleDialog.h"
#include <QDebug>
BatchEneryScaleDialog::BatchEneryScaleDialog(QWidget *parent) BatchEneryScaleDialog::BatchEneryScaleDialog(QWidget* parent)
: QDialog(parent) : QDialog(parent)
, ui(new Ui::BatchEneryScaleDialog) , ui(new Ui::BatchEneryScaleDialog)
{ {
ui->setupUi(this); ui->setupUi(this);
this->setWindowFlags(Qt::Dialog | Qt::WindowCloseButtonHint); 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);
} }
BatchEneryScaleDialog::~BatchEneryScaleDialog() BatchEneryScaleDialog::~BatchEneryScaleDialog()
{ {
delete ui; delete ui;
} }
void BatchEneryScaleDialog::SetPeakResultDataModel(QAbstractTableModel* peaks_result_model)
{
_peaks_result_model = peaks_result_model;
qDebug() << _peaks_result_model->rowCount();
}
void BatchEneryScaleDialog::onSelectedScaleRange(double min, double max)
{
qDebug() << min << ", " << max;
}
void BatchEneryScaleDialog::closeEvent(QCloseEvent *e)
{
emit close();
}

View File

@ -3,6 +3,8 @@
#include <QDialog> #include <QDialog>
class QAbstractTableModel;
namespace Ui { namespace Ui {
class BatchEneryScaleDialog; class BatchEneryScaleDialog;
} }
@ -15,8 +17,20 @@ public:
explicit BatchEneryScaleDialog(QWidget *parent = nullptr); explicit BatchEneryScaleDialog(QWidget *parent = nullptr);
~BatchEneryScaleDialog(); ~BatchEneryScaleDialog();
void SetPeakResultDataModel(QAbstractTableModel *peaks_result_model);
public slots:
void onSelectedScaleRange(double min, double max);
signals:
void close();
protected:
void closeEvent(QCloseEvent *e);
private: private:
Ui::BatchEneryScaleDialog *ui; Ui::BatchEneryScaleDialog *ui;
QAbstractTableModel* _peaks_result_model;
}; };
#endif // BATCHENERYSCALEDIALOG_H #endif // BATCHENERYSCALEDIALOG_H

View File

@ -6,18 +6,35 @@
<rect> <rect>
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>824</width> <width>929</width>
<height>409</height> <height>404</height>
</rect> </rect>
</property> </property>
<property name="windowTitle"> <property name="windowTitle">
<string>Dialog</string> <string>多通道能量刻度</string>
</property> </property>
<layout class="QVBoxLayout" name="verticalLayout"> <layout class="QVBoxLayout" name="verticalLayout">
<item> <item>
<layout class="QHBoxLayout" name="horizontalLayout_3"> <layout class="QHBoxLayout" name="horizontalLayout_3">
<property name="spacing">
<number>16</number>
</property>
<item> <item>
<layout class="QHBoxLayout" name="horizontalLayout"> <layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QPushButton" name="btn_all_select">
<property name="text">
<string>全选</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="btn_reserve_select">
<property name="text">
<string>反选</string>
</property>
</widget>
</item>
<item> <item>
<widget class="QLabel" name="label_channel"> <widget class="QLabel" name="label_channel">
<property name="text"> <property name="text">
@ -26,7 +43,14 @@
</widget> </widget>
</item> </item>
<item> <item>
<widget class="QComboBox" name="comboBox_channel"/> <widget class="QComboBox" name="comboBox_channel">
<property name="minimumSize">
<size>
<width>75</width>
<height>0</height>
</size>
</property>
</widget>
</item> </item>
</layout> </layout>
</item> </item>
@ -40,10 +64,24 @@
</widget> </widget>
</item> </item>
<item> <item>
<widget class="QComboBox" name="comboBox_enery"/> <widget class="QComboBox" name="comboBox_enery">
<property name="minimumSize">
<size>
<width>125</width>
<height>0</height>
</size>
</property>
</widget>
</item> </item>
</layout> </layout>
</item> </item>
<item>
<widget class="QPushButton" name="btn_remove_selected">
<property name="text">
<string>删除勾选</string>
</property>
</widget>
</item>
<item> <item>
<spacer name="horizontalSpacer"> <spacer name="horizontalSpacer">
<property name="orientation"> <property name="orientation">
@ -64,10 +102,26 @@
</property> </property>
</widget> </widget>
</item> </item>
<item>
<widget class="QPushButton" name="btn_save">
<property name="text">
<string>保存</string>
</property>
</widget>
</item>
</layout> </layout>
</item> </item>
<item> <item>
<widget class="QTableWidget" name="tableWidget_process_data"> <widget class="QTableWidget" name="tablew_process_data">
<property name="editTriggers">
<set>QAbstractItemView::NoEditTriggers</set>
</property>
<property name="selectionMode">
<enum>QAbstractItemView::SingleSelection</enum>
</property>
<property name="selectionBehavior">
<enum>QAbstractItemView::SelectRows</enum>
</property>
<column> <column>
<property name="text"> <property name="text">
<string>通道</string> <string>通道</string>
@ -111,6 +165,11 @@
<string>分辨率偏差</string> <string>分辨率偏差</string>
</property> </property>
</column> </column>
<column>
<property name="text">
<string>操作</string>
</property>
</column>
</widget> </widget>
</item> </item>
</layout> </layout>

View File

@ -0,0 +1,272 @@
#include "FindPeaksResultDialog.h"
#include "GlobalDefine.h"
#include <QHBoxLayout>
#include <QHeaderView>
#include <QCheckBox>
#include <QComboBox>
#include <QLabel>
#include <QTableWidget>
#include <QPushButton>
#include "csv.h"
#include <fstream>
#include <QFileInfo>
FindPeaksResultDialog::FindPeaksResultDialog(QWidget *parent)
{
this->setWindowTitle(QString(QStringLiteral(u"寻峰结果")));
this->setWindowModality(Qt::WindowModal);
this->setModal(false);
QPushButton* btn_all_select = new QPushButton(QString(QStringLiteral(u"全选")));
QPushButton* btn_reserve_select = new QPushButton(QString(QStringLiteral(u"反选")));
QLabel* filter_channel_label = new QLabel(QString(QStringLiteral(u"筛选通道:")));
_filter_channel_combo_box = new QComboBox();
_filter_channel_combo_box->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum);
_filter_channel_combo_box->setMinimumWidth(75);
_filter_channel_combo_box->addItem(QString(QStringLiteral(u"所有通道")));
_filter_channel_combo_box->setMaxVisibleItems(10);
_filter_channel_combo_box->view()->setVerticalScrollMode(QAbstractItemView::ScrollPerPixel);
QPushButton* btn_save = new QPushButton(QString(QStringLiteral(u"保存")));
QHBoxLayout* top_layout = new QHBoxLayout();
top_layout->addWidget(btn_all_select);
top_layout->addWidget(btn_reserve_select);
top_layout->addSpacing(10);
top_layout->addWidget(filter_channel_label);
top_layout->addWidget(_filter_channel_combo_box);
top_layout->addStretch();
top_layout->addWidget(btn_save);
const QString& channel_col_name = QString(QStringLiteral(u"通道"));
const QString& peak_pos_col_name = QString(QStringLiteral(u"峰位"));
const QString& left_bound_col_name = QString(QStringLiteral(u"左边界"));
const QString& right_bound_col_name = QString(QStringLiteral(u"右边界"));
const QString& peak_width_col_name = QString(QStringLiteral(u"峰宽"));
const QString& peak_height_col_name = QString(QStringLiteral(u"峰高"));
const QString& peak_fwhm_col_name = QString(QStringLiteral(u"FWHM"));
const QString& peak_area_col_name = QString(QStringLiteral(u"峰面积"));
const QString& operation_col_name = QString(QStringLiteral(u"操作"));
_peaks_result_table = new QTableWidget();
_peaks_result_table->setObjectName("peaks_result_table");
_peaks_result_table->setColumnCount(9);
_peaks_result_table->setHorizontalHeaderLabels({ channel_col_name, peak_pos_col_name, left_bound_col_name, right_bound_col_name,
peak_width_col_name, peak_height_col_name, peak_fwhm_col_name, peak_area_col_name, operation_col_name });
_peaks_result_table->horizontalHeader()->setSectionResizeMode(QHeaderView::ResizeToContents);
_peaks_result_table->horizontalHeader()->setSectionResizeMode(_peaks_result_table->columnCount() - 1, QHeaderView::ResizeToContents);
_peaks_result_table->horizontalHeader()->setDefaultAlignment(Qt::AlignLeft | Qt::AlignVCenter);
_peaks_result_table->setSelectionBehavior(QAbstractItemView::SelectRows);
_peaks_result_table->setSelectionMode(QAbstractItemView::SingleSelection);
_peaks_result_table->setEditTriggers(QTableWidget::NoEditTriggers);
connect(_filter_channel_combo_box, &QComboBox::currentTextChanged, [this](const QString& text) {
_peaks_result_table->setCurrentItem(nullptr);
auto row_count = _peaks_result_table->rowCount();
if (text == QString(QStringLiteral(u"所有通道"))) {
for (int i = 0; i < row_count - 1; i++) {
_peaks_result_table->setRowHidden(i, false);
}
} else {
for (int i = row_count - 1; i >= 0; i--) {
const QString& channel = _peaks_result_table->item(i, 0)->text();
bool is_hidden = text == channel ? false : true;
_peaks_result_table->setRowHidden(i, is_hidden);
}
}
});
connect(btn_all_select, &QPushButton::clicked, [this]() {
_peaks_result_table->setCurrentItem(nullptr);
auto row_count = _peaks_result_table->rowCount();
for (int i = 0; i < row_count - 1; i++) {
if (_peaks_result_table->isRowHidden(i)) {
continue;
}
auto item = _peaks_result_table->item(i, 0);
if (item) {
item->setCheckState(Qt::Checked);
}
}
});
connect(btn_reserve_select, &QPushButton::clicked, [this]() {
_peaks_result_table->setCurrentItem(nullptr);
auto row_count = _peaks_result_table->rowCount();
for (int i = 0; i < row_count - 1; i++) {
if (_peaks_result_table->isRowHidden(i)) {
continue;
}
auto item = _peaks_result_table->item(i, 0);
if (item) {
Qt::CheckState check_state = (item->checkState() == Qt::Checked) ? Qt::Unchecked : Qt::Checked;
item->setCheckState(check_state);
}
}
});
connect(btn_save, &QPushButton::clicked, [this]() {
saveCurrentPeakResult();
});
connect(_peaks_result_table, &QTableWidget::itemChanged, [this](QTableWidgetItem* item) {
bool is_watch_item_changed = _peaks_result_table->property("WatchItemChanged").toBool();
if (is_watch_item_changed && bool(item->column() == 0)) {
emit peakInfoChanged(peakInfo(item, true, false));
}
});
connect(_peaks_result_table, &QTableWidget::currentItemChanged, [this](QTableWidgetItem* current, QTableWidgetItem* previous) {
bool is_watch_item_changed = _peaks_result_table->property("WatchItemChanged").toBool();
if (is_watch_item_changed) {
emit peakInfoChanged(peakInfo(previous, false, false));
emit peakInfoChanged(peakInfo(current, true, true));
}
});
QVBoxLayout* layout = new QVBoxLayout(this);
layout->addLayout(top_layout);
layout->addWidget(_peaks_result_table);
}
void FindPeaksResultDialog::SetPeakResultDataFilename(const QString &data_filename)
{
this->_peaks_result_data_filename = data_filename;
}
void FindPeaksResultDialog::SetChannelNameList(const QStringList &ch_name_list)
{
_filter_channel_combo_box->clear();
_filter_channel_combo_box->addItem(QString(QStringLiteral(u"所有通道")));
_filter_channel_combo_box->addItems(ch_name_list);
}
void FindPeaksResultDialog::UpdatePeakResult()
{
if (!QFileInfo(_peaks_result_data_filename).exists())
return;
_peaks_result_table->setCurrentItem(nullptr);
_peaks_result_table->setProperty("WatchItemChanged", false);
auto row_count = _peaks_result_table->rowCount();
for (int i = row_count - 1; i >= 0; i--) {
_peaks_result_table->removeRow(i);
}
const QString& channel_col_name = QString(QStringLiteral(u"通道"));
const QString& peak_pos_col_name = QString(QStringLiteral(u"峰位"));
const QString& left_bound_col_name = QString(QStringLiteral(u"左边界"));
const QString& right_bound_col_name = QString(QStringLiteral(u"右边界"));
const QString& peak_width_col_name = QString(QStringLiteral(u"峰宽"));
const QString& peak_height_col_name = QString(QStringLiteral(u"峰高"));
const QString& peak_fwhm_col_name = QString(QStringLiteral(u"FWHM"));
const QString& peak_area_col_name = QString(QStringLiteral(u"峰面积"));
io::CSVReader<
8,
io::trim_chars<' ', '\t'>,
io::double_quote_escape<',', '"'>,
io::throw_on_overflow,
io::empty_line_comment>
reader(QStrToSysPath(_peaks_result_data_filename));
reader.read_header(
io::ignore_extra_column,
channel_col_name.toStdString(),
peak_pos_col_name.toStdString(),
left_bound_col_name.toStdString(),
right_bound_col_name.toStdString(),
peak_width_col_name.toStdString(),
peak_height_col_name.toStdString(),
peak_fwhm_col_name.toStdString(),
peak_area_col_name.toStdString());
std::string ch_name;
int peak_pos;
int left_bound, right_bound, peak_width, peak_height, peak_fwhm;
double peak_area;
while (reader.read_row(ch_name, peak_pos, left_bound, right_bound, peak_width, peak_height, peak_fwhm, peak_area)) {
if (!ch_name.empty()) {
int row = _peaks_result_table->rowCount();
_peaks_result_table->insertRow(row);
_peaks_result_table->setItem(row, 0, new QTableWidgetItem(QString::fromStdString(ch_name)));
_peaks_result_table->item(row, 0)->setCheckState(Qt::Unchecked);
_peaks_result_table->setItem(row, 1, new QTableWidgetItem(QString::number(peak_pos)));
_peaks_result_table->setItem(row, 2, new QTableWidgetItem(QString::number(left_bound)));
_peaks_result_table->setItem(row, 3, new QTableWidgetItem(QString::number(right_bound)));
_peaks_result_table->setItem(row, 4, new QTableWidgetItem(QString::number(peak_width)));
_peaks_result_table->setItem(row, 5, new QTableWidgetItem(QString::number(peak_height)));
_peaks_result_table->setItem(row, 6, new QTableWidgetItem(QString::number(peak_fwhm)));
_peaks_result_table->setItem(row, 7, new QTableWidgetItem(QString::number(peak_area)));
QTableWidgetItem* item = new QTableWidgetItem;
_peaks_result_table->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);
emit peakInfoChanged(peakInfo(item, false, false));
int remove_row = item->row();
this->_peaks_result_table->removeRow(remove_row);
btn_remove_row->deleteLater();
});
_peaks_result_table->setCellWidget(row, 8, btn_remove_row);
}
}
_peaks_result_table->setProperty("WatchItemChanged", true);
}
QAbstractTableModel* FindPeaksResultDialog::GetPeakResultDataModel() const
{
QAbstractTableModel* peaks_result_model = dynamic_cast<QAbstractTableModel*>(_peaks_result_table->model());
return peaks_result_model;
}
void FindPeaksResultDialog::saveCurrentPeakResult()
{
std::ofstream out_file(QStrToSysPath(_peaks_result_data_filename));
std::string channel_str = QString(QStringLiteral(u"通道")).toStdString();
std::string addr_str = QString(QStringLiteral(u"峰位")).toStdString();
std::string left_addr_str = QString(QStringLiteral(u"左边界")).toStdString();
std::string lright_addr_str = QString(QStringLiteral(u"右边界")).toStdString();
std::string width_str = QString(QStringLiteral(u"峰宽")).toStdString();
std::string height_str = QString(QStringLiteral(u"峰高")).toStdString();
std::string fwhm_str = QString(QStringLiteral(u"FWHM")).toStdString();
std::string area_str = QString(QStringLiteral(u"峰面积")).toStdString();
out_file << channel_str << "," << addr_str << "," << left_addr_str << ","
<< lright_addr_str << "," << width_str << "," << height_str << ","
<< fwhm_str << "," << area_str << "\n";
auto row_count = _peaks_result_table->rowCount();
for (int i = 0; i < row_count - 1; i++) {
std::string channel = _peaks_result_table->item(i, 0)->text().toStdString();
int peak_pos = _peaks_result_table->item(i, 1)->text().toInt();
int left_bound = _peaks_result_table->item(i, 2)->text().toInt();
int right_bound = _peaks_result_table->item(i, 3)->text().toInt();
int peak_width = _peaks_result_table->item(i, 4)->text().toInt();
int peak_height = _peaks_result_table->item(i, 5)->text().toInt();
int peak_fwhm = _peaks_result_table->item(i, 6)->text().toInt();
double peak_area = _peaks_result_table->item(i, 7)->text().toDouble();
out_file << channel << "," << peak_pos << "," << left_bound << "," << right_bound << ","
<< peak_width << "," << peak_height << "," << peak_fwhm<< "," << peak_area << "\n";
}
LOG_INFO(QStringLiteral(u"保存峰信息完成."));
}
QVariantMap FindPeaksResultDialog::peakInfo(QTableWidgetItem *item, bool show_peak, bool show_peak_area)
{
QVariantMap peak_infos;
if (!item) {
return peak_infos;
}
int row = item->row();
bool is_checked = bool(_peaks_result_table->item(row, 0)->checkState() == Qt::Checked);
const QString& channel = _peaks_result_table->item(row, 0)->text();
int peak_pos = _peaks_result_table->item(row, 1)->text().toInt();
int left_bound = _peaks_result_table->item(row, 2)->text().toInt();
int right_bound = _peaks_result_table->item(row, 3)->text().toInt();
int peak_width = _peaks_result_table->item(row, 4)->text().toInt();
int peak_height = _peaks_result_table->item(row, 5)->text().toInt();
int peak_fwhm = _peaks_result_table->item(row, 6)->text().toInt();
double peak_area = _peaks_result_table->item(row, 7)->text().toDouble();
peak_infos["channel"] = channel;
peak_infos["peak_pos"] = peak_pos;
peak_infos["left_bound"] = left_bound;
peak_infos["right_bound"] = right_bound;
peak_infos["peak_width"] = peak_width;
peak_infos["peak_height"] = peak_height;
peak_infos["peak_fwhm"] = peak_fwhm;
peak_infos["peak_area"] = peak_area;
peak_infos["checked"] = is_checked || show_peak;
peak_infos["show_peak_area"] = show_peak_area || show_peak;
return peak_infos;
}

View File

@ -0,0 +1,36 @@
#ifndef FINDPEAKSRESULTDIALOG_H
#define FINDPEAKSRESULTDIALOG_H
#include <QDialog>
#include <QObject>
#include <QVariantMap>
class QTableWidget;
class QTableWidgetItem;
class QAbstractTableModel;
class QComboBox;
class FindPeaksResultDialog : public QDialog
{
Q_OBJECT
public:
FindPeaksResultDialog(QWidget* parent = nullptr);
void SetPeakResultDataFilename(const QString& data_filename);
void SetChannelNameList(const QStringList& ch_name_list);
void UpdatePeakResult();
QAbstractTableModel *GetPeakResultDataModel() const;
private:
void saveCurrentPeakResult();
QVariantMap peakInfo(QTableWidgetItem* item, bool show_peak, bool show_peak_area);
signals:
void peakInfoChanged(QVariantMap peak_infos);
private:
QComboBox* _filter_channel_combo_box = nullptr;
QTableWidget* _peaks_result_table = nullptr;
QString _peaks_result_data_filename;
};
#endif // FINDPEAKSRESULTDIALOG_H

View File

@ -15,7 +15,6 @@
#include <QMenu> #include <QMenu>
#include <QPen> #include <QPen>
#include <QPushButton> #include <QPushButton>
#include <QRegularExpression>
#include <QSpinBox> #include <QSpinBox>
#include <QTableWidget> #include <QTableWidget>
#include <QVector> #include <QVector>
@ -28,16 +27,7 @@
#include <QwtText> #include <QwtText>
#include <fstream> #include <fstream>
#include "BatchEneryScaleDialog.h" #include "BatchEneryScaleDialog.h"
#include "FindPeaksResultDialog.h"
static auto extractNumber = [](const QString& str) {
int ret_num = 0;
QRegularExpression regex("\\d+");
QRegularExpressionMatch match = regex.match(str);
if (match.hasMatch()) {
ret_num = match.captured().toInt();
}
return ret_num;
};
MeasureAnalysisParticleCountPlotView::MeasureAnalysisParticleCountPlotView(QWidget* parent) MeasureAnalysisParticleCountPlotView::MeasureAnalysisParticleCountPlotView(QWidget* parent)
: MeasureAnalysisView { parent } : MeasureAnalysisView { parent }
@ -47,11 +37,11 @@ MeasureAnalysisParticleCountPlotView::MeasureAnalysisParticleCountPlotView(QWidg
QHBoxLayout* layout = new QHBoxLayout(this); QHBoxLayout* layout = new QHBoxLayout(this);
this->_plot = new CustomQwtPlot(this); this->_plot = new CustomQwtPlot(this);
layout->addWidget(this->_plot); layout->addWidget(this->_plot);
this->_menu = new QMenu(this);
setupPlot(); setupPlot();
this->_menu = new QMenu(this);
setupMenu(); setupMenu();
setupPeakResultDlg();
} }
MeasureAnalysisParticleCountPlotView::~MeasureAnalysisParticleCountPlotView() MeasureAnalysisParticleCountPlotView::~MeasureAnalysisParticleCountPlotView()
@ -69,20 +59,23 @@ void MeasureAnalysisParticleCountPlotView::InitViewWorkspace(const QString& proj
return; return;
} }
QDir project_dir(project_model->GetProjectDir()); QDir project_dir(project_model->GetProjectDir());
QString workspace = project_dir.filePath("AddressCountSpectrumView"); QString workspace = project_dir.filePath(this->GetViewName());
if (QDir(workspace).exists()) { if (QDir(workspace).exists()) {
this->_workspace = workspace; this->_workspace = workspace;
} else if (project_dir.mkpath(workspace)) { } else if (project_dir.mkpath(workspace)) {
this->_workspace = workspace; this->_workspace = workspace;
} }
const QString& peaks_result_filename = QDir(this->_workspace).filePath(QStringLiteral(u"自动寻峰结果.csv"));
_find_peaks_result_dlg->SetPeakResultDataFilename(peaks_result_filename);
_find_peaks_result_dlg->UpdatePeakResult();
} }
void MeasureAnalysisParticleCountPlotView::SetAnalyzeDataFilename(const QMap<QString, QVariant>& data_files_set) void MeasureAnalysisParticleCountPlotView::SetAnalyzeDataFilename(const QMap<QString, QVariant>& data_files_set)
{ {
QStringList ch_count_data_name = data_files_set.keys(); QStringList ch_count_data_name = data_files_set.keys();
std::sort(ch_count_data_name.begin(), ch_count_data_name.end(), [](const QString& a, const QString& b) { std::sort(ch_count_data_name.begin(), ch_count_data_name.end(), [](const QString& a, const QString& b) {
int num_a = extractNumber(a); int num_a = ExtractNumberFromString(a);
int num_b = extractNumber(b); int num_b = ExtractNumberFromString(b);
return num_a < num_b; return num_a < num_b;
}); });
for (const QString& ch_count_data_name : ch_count_data_name) { for (const QString& ch_count_data_name : ch_count_data_name) {
@ -156,6 +149,26 @@ void MeasureAnalysisParticleCountPlotView::setupPlot()
_data_selector->setEnabled(false); _data_selector->setEnabled(false);
} }
void MeasureAnalysisParticleCountPlotView::setupPeakResultDlg()
{
if (!_find_peaks_result_dlg) {
_find_peaks_result_dlg = new FindPeaksResultDialog(this);
QStringList list_ch_names;
for (QwtPlotCurve* curve : this->_plot->GetCurveList()) {
list_ch_names.append(curve->title().text());
}
std::sort(list_ch_names.begin(), list_ch_names.end(), [](const QString& a, const QString& b) {
int num_a = ExtractNumberFromString(a);
int num_b = ExtractNumberFromString(b);
return num_a < num_b;
});
_find_peaks_result_dlg->SetChannelNameList(list_ch_names);
connect(_find_peaks_result_dlg, &FindPeaksResultDialog::peakInfoChanged, [this](QVariantMap peak_infos){
this->updatePlotPeakInfo(peak_infos);
});
}
}
void MeasureAnalysisParticleCountPlotView::loadDataFromFile(const QString& data_name, const QString& filename) void MeasureAnalysisParticleCountPlotView::loadDataFromFile(const QString& data_name, const QString& filename)
{ {
std::string address_str = QString(QStringLiteral(u"道址")).toStdString(); std::string address_str = QString(QStringLiteral(u"道址")).toStdString();
@ -185,72 +198,7 @@ void MeasureAnalysisParticleCountPlotView::loadDataFromFile(const QString& data_
_plot->AddCurve(curve); _plot->AddCurve(curve);
} }
void MeasureAnalysisParticleCountPlotView::loadPeaksResultToTable(QTableWidget* peaks_result_table) void MeasureAnalysisParticleCountPlotView::updatePlotPeakInfo(const QVariantMap &peak_infos)
{
this->_plot->CleanMarkers();
this->_plot->replot();
if (!peaks_result_table)
return;
peaks_result_table->setCurrentItem(nullptr);
peaks_result_table->setProperty("WatchItemChanged", false);
auto row_count = peaks_result_table->rowCount();
for (int i = row_count - 1; i >= 0; i--) {
peaks_result_table->removeRow(i);
}
const QString& channel_col_name = QString(QStringLiteral(u"通道"));
const QString& peak_pos_col_name = QString(QStringLiteral(u"峰位"));
const QString& left_bound_col_name = QString(QStringLiteral(u"左边界"));
const QString& right_bound_col_name = QString(QStringLiteral(u"右边界"));
const QString& peak_width_col_name = QString(QStringLiteral(u"峰宽"));
const QString& peak_height_col_name = QString(QStringLiteral(u"峰高"));
const QString& peaks_result_filename = QDir(this->_workspace).filePath("AutoFindPeaksResult.csv");
io::CSVReader<
6,
io::trim_chars<' ', '\t'>,
io::double_quote_escape<',', '"'>,
io::throw_on_overflow,
io::empty_line_comment>
reader(QStrToSysPath(peaks_result_filename));
reader.read_header(
io::ignore_extra_column,
channel_col_name.toStdString(),
peak_pos_col_name.toStdString(),
left_bound_col_name.toStdString(),
right_bound_col_name.toStdString(),
peak_width_col_name.toStdString(),
peak_height_col_name.toStdString());
std::string ch_name;
int peak_pos;
int left_bound, right_bound, peak_width, peak_height;
while (reader.read_row(ch_name, peak_pos, left_bound, right_bound, peak_width, peak_height)) {
if (!ch_name.empty()) {
int row = peaks_result_table->rowCount();
peaks_result_table->insertRow(row);
peaks_result_table->setItem(row, 0, new QTableWidgetItem(QString::fromStdString(ch_name)));
peaks_result_table->item(row, 0)->setCheckState(Qt::Unchecked);
peaks_result_table->setItem(row, 1, new QTableWidgetItem(QString::number(peak_pos)));
peaks_result_table->setItem(row, 2, new QTableWidgetItem(QString::number(left_bound)));
peaks_result_table->setItem(row, 3, new QTableWidgetItem(QString::number(right_bound)));
peaks_result_table->setItem(row, 4, new QTableWidgetItem(QString::number(peak_width)));
peaks_result_table->setItem(row, 5, new QTableWidgetItem(QString::number(peak_height)));
QTableWidgetItem* item = new QTableWidgetItem;
peaks_result_table->setItem(row, 6, item);
QPushButton* btn_remove_row = new QPushButton(QStringLiteral(u"删除"));
connect(btn_remove_row, &QPushButton::clicked, [this, peaks_result_table, item, btn_remove_row]() {
item->setCheckState(Qt::Unchecked);
this->updatePlotPeakInfoByTableItem(item, false);
int remove_row = item->row();
peaks_result_table->removeRow(remove_row);
btn_remove_row->deleteLater();
});
peaks_result_table->setCellWidget(row, 6, btn_remove_row);
}
}
peaks_result_table->setProperty("WatchItemChanged", true);
}
void MeasureAnalysisParticleCountPlotView::updatePlotPeakInfo(QVariantMap peak_infos)
{ {
const QString& channel = peak_infos["channel"].toString(); const QString& channel = peak_infos["channel"].toString();
int peak_pos = peak_infos["peak_pos"].toInt(); int peak_pos = peak_infos["peak_pos"].toInt();
@ -258,6 +206,8 @@ void MeasureAnalysisParticleCountPlotView::updatePlotPeakInfo(QVariantMap peak_i
int right_bound = peak_infos["right_bound"].toInt(); int right_bound = peak_infos["right_bound"].toInt();
int peak_width = peak_infos["peak_width"].toInt(); int peak_width = peak_infos["peak_width"].toInt();
int peak_height = peak_infos["peak_height"].toInt(); int peak_height = peak_infos["peak_height"].toInt();
int peak_fwhm = peak_infos["peak_fwhm"].toInt();
double peak_area = peak_infos["peak_area"].toDouble();
bool is_checked = peak_infos["checked"].toBool(); bool is_checked = peak_infos["checked"].toBool();
bool is_show_peak_area = peak_infos["show_peak_area"].toBool(); bool is_show_peak_area = peak_infos["show_peak_area"].toBool();
@ -268,7 +218,9 @@ void MeasureAnalysisParticleCountPlotView::updatePlotPeakInfo(QVariantMap peak_i
peak_marker->setLineStyle(QwtPlotMarker::VLine); peak_marker->setLineStyle(QwtPlotMarker::VLine);
peak_marker->setValue(peak_pos, 0.0); peak_marker->setValue(peak_pos, 0.0);
peak_marker->setLabelAlignment(Qt::AlignTop | Qt::AlignRight); peak_marker->setLabelAlignment(Qt::AlignTop | Qt::AlignRight);
const QString& label_text = QStringLiteral(u"峰位:%1\n峰宽:%2\n左界:%3\n右界:%4\n峰高:%5\n").arg(peak_pos).arg(peak_width).arg(left_bound).arg(right_bound).arg(peak_height); const QString& label_text = QStringLiteral(u"峰位:%1\n峰宽:%2\n左界:%3\n右界:%4\n峰高:%5\nFWHM:%6\n峰面积:%7\n")
.arg(peak_pos).arg(peak_width).arg(left_bound).arg(right_bound)
.arg(peak_height).arg(peak_fwhm).arg(peak_area);
peak_marker->setLabel(label_text); peak_marker->setLabel(label_text);
this->_plot->AddMarker(peak_marker, channel, postion); this->_plot->AddMarker(peak_marker, channel, postion);
} else if (!is_checked) { } else if (!is_checked) {
@ -286,46 +238,15 @@ void MeasureAnalysisParticleCountPlotView::updatePlotPeakInfo(QVariantMap peak_i
this->_plot->replot(); this->_plot->replot();
} }
void MeasureAnalysisParticleCountPlotView::updatePlotPeakInfoByTableItem(QTableWidgetItem* item, bool checked, bool show_peak_area)
{
if (item) {
auto peaks_result_table = item->tableWidget();
int row = item->row();
bool is_checked = bool(peaks_result_table->item(row, 0)->checkState() == Qt::Checked);
const QString& channel = peaks_result_table->item(row, 0)->text();
int peak_pos = peaks_result_table->item(row, 1)->text().toInt();
int left_bound = peaks_result_table->item(row, 2)->text().toInt();
int right_bound = peaks_result_table->item(row, 3)->text().toInt();
int peak_width = peaks_result_table->item(row, 4)->text().toInt();
int peak_height = peaks_result_table->item(row, 5)->text().toInt();
QVariantMap peak_infos;
peak_infos["channel"] = channel;
peak_infos["peak_pos"] = peak_pos;
peak_infos["left_bound"] = left_bound;
peak_infos["right_bound"] = right_bound;
peak_infos["peak_width"] = peak_width;
peak_infos["peak_height"] = peak_height;
peak_infos["checked"] = is_checked || checked;
peak_infos["show_peak_area"] = show_peak_area || checked;
this->updatePlotPeakInfo(peak_infos);
}
}
void MeasureAnalysisParticleCountPlotView::onAutoFindPeaksFinished(const QString& project_name) void MeasureAnalysisParticleCountPlotView::onAutoFindPeaksFinished(const QString& project_name)
{ {
Q_UNUSED(project_name); Q_UNUSED(project_name);
if (_find_peaks_result_dlg) { this->_plot->CleanMarkers();
for (const auto& child_obj : _find_peaks_result_dlg->children()) { this->_plot->replot();
if ("peaks_result_table" == child_obj->objectName()) { if (this->_find_peaks_result_dlg) {
QTableWidget* table = qobject_cast<QTableWidget*>(child_obj); this->_find_peaks_result_dlg->UpdatePeakResult();
if (table) { _find_peaks_result_dlg->show();
loadPeaksResultToTable(table);
break;
}
}
}
} }
onActionFindPeaksResult();
} }
void MeasureAnalysisParticleCountPlotView::onActionCurveShowSetting() void MeasureAnalysisParticleCountPlotView::onActionCurveShowSetting()
@ -350,8 +271,8 @@ void MeasureAnalysisParticleCountPlotView::onActionCurveShowSetting()
list_ch_names.append(curve->title().text()); list_ch_names.append(curve->title().text());
} }
std::sort(list_ch_names.begin(), list_ch_names.end(), [](const QString& a, const QString& b) { std::sort(list_ch_names.begin(), list_ch_names.end(), [](const QString& a, const QString& b) {
int num_a = extractNumber(a); int num_a = ExtractNumberFromString(a);
int num_b = extractNumber(b); int num_b = ExtractNumberFromString(b);
return num_a < num_b; return num_a < num_b;
}); });
for (const QString& ch_name : list_ch_names) { for (const QString& ch_name : list_ch_names) {
@ -407,146 +328,9 @@ void MeasureAnalysisParticleCountPlotView::onActionCurveShowSetting()
void MeasureAnalysisParticleCountPlotView::onActionFindPeaksResult() void MeasureAnalysisParticleCountPlotView::onActionFindPeaksResult()
{ {
if (!_find_peaks_result_dlg) { if (_find_peaks_result_dlg) {
_find_peaks_result_dlg = new QDialog(this, Qt::Dialog | Qt::WindowCloseButtonHint); _find_peaks_result_dlg->show();
_find_peaks_result_dlg->setWindowTitle(QString(QStringLiteral(u"寻峰结果")));
_find_peaks_result_dlg->setWindowModality(Qt::WindowModal);
_find_peaks_result_dlg->setModal(false);
QPushButton* btn_all_select = new QPushButton(QString(QStringLiteral(u"全选")));
QPushButton* btn_reserve_select = new QPushButton(QString(QStringLiteral(u"反选")));
QLabel* filter_channel_label = new QLabel(QString(QStringLiteral(u"筛选通道:")));
QComboBox* filter_channel_combo_box = new QComboBox();
filter_channel_combo_box->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Minimum);
filter_channel_combo_box->addItem(QString(QStringLiteral(u"所有通道")));
QStringList list_ch_names;
for (QwtPlotCurve* curve : this->_plot->GetCurveList()) {
list_ch_names.append(curve->title().text());
}
std::sort(list_ch_names.begin(), list_ch_names.end(), [](const QString& a, const QString& b) {
int num_a = extractNumber(a);
int num_b = extractNumber(b);
return num_a < num_b;
});
filter_channel_combo_box->addItems(list_ch_names);
filter_channel_combo_box->setMaxVisibleItems(10);
filter_channel_combo_box->view()->setVerticalScrollMode(QAbstractItemView::ScrollPerPixel);
QPushButton* btn_save = new QPushButton(QString(QStringLiteral(u"保存")));
QHBoxLayout* top_layout = new QHBoxLayout();
top_layout->addWidget(btn_all_select);
top_layout->addWidget(btn_reserve_select);
top_layout->addSpacing(10);
top_layout->addWidget(filter_channel_label);
top_layout->addWidget(filter_channel_combo_box);
top_layout->addSpacing(10);
top_layout->addWidget(btn_save);
const QString& channel_col_name = QString(QStringLiteral(u"通道"));
const QString& peak_pos_col_name = QString(QStringLiteral(u"峰位"));
const QString& left_bound_col_name = QString(QStringLiteral(u"左边界"));
const QString& right_bound_col_name = QString(QStringLiteral(u"右边界"));
const QString& peak_width_col_name = QString(QStringLiteral(u"峰宽"));
const QString& peak_height_col_name = QString(QStringLiteral(u"峰高"));
const QString& operation_col_name = QString(QStringLiteral(u"操作"));
QTableWidget* peaks_result_table = new QTableWidget();
peaks_result_table->setObjectName("peaks_result_table");
peaks_result_table->setColumnCount(7);
peaks_result_table->setHorizontalHeaderLabels({ channel_col_name, peak_pos_col_name, left_bound_col_name, right_bound_col_name,
peak_width_col_name, peak_height_col_name, operation_col_name });
peaks_result_table->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch);
peaks_result_table->horizontalHeader()->setSectionResizeMode(0, QHeaderView::ResizeToContents);
peaks_result_table->horizontalHeader()->setSectionResizeMode(peaks_result_table->columnCount() - 1, QHeaderView::ResizeToContents);
peaks_result_table->horizontalHeader()->setDefaultAlignment(Qt::AlignLeft | Qt::AlignVCenter);
peaks_result_table->setSelectionBehavior(QAbstractItemView::SelectRows);
peaks_result_table->setSelectionMode(QAbstractItemView::SingleSelection);
peaks_result_table->setEditTriggers(QTableWidget::NoEditTriggers);
this->loadPeaksResultToTable(peaks_result_table);
connect(filter_channel_combo_box, &QComboBox::currentTextChanged, [this, peaks_result_table](const QString& text) {
peaks_result_table->setCurrentItem(nullptr);
auto row_count = peaks_result_table->rowCount();
if (text == QString(QStringLiteral(u"所有通道"))) {
for (int i = 0; i < row_count - 1; i++) {
peaks_result_table->setRowHidden(i, false);
}
} else {
for (int i = row_count - 1; i >= 0; i--) {
const QString& channel = peaks_result_table->item(i, 0)->text();
bool is_hidden = text == channel ? false : true;
peaks_result_table->setRowHidden(i, is_hidden);
}
}
});
connect(btn_all_select, &QPushButton::clicked, [peaks_result_table]() {
peaks_result_table->setCurrentItem(nullptr);
auto row_count = peaks_result_table->rowCount();
for (int i = 0; i < row_count - 1; i++) {
if (peaks_result_table->isRowHidden(i)) {
continue;
}
auto item = peaks_result_table->item(i, 0);
if (item) {
item->setCheckState(Qt::Checked);
}
}
});
connect(btn_reserve_select, &QPushButton::clicked, [peaks_result_table]() {
peaks_result_table->setCurrentItem(nullptr);
auto row_count = peaks_result_table->rowCount();
for (int i = 0; i < row_count - 1; i++) {
if (peaks_result_table->isRowHidden(i)) {
continue;
}
auto item = peaks_result_table->item(i, 0);
if (item) {
Qt::CheckState check_state = (item->checkState() == Qt::Checked) ? Qt::Unchecked : Qt::Checked;
item->setCheckState(check_state);
}
}
});
connect(btn_save, &QPushButton::clicked, [peaks_result_table, this]() {
const QString& peaks_result_filename = QDir(this->_workspace).filePath("AutoFindPeaksResult.csv");
std::ofstream out_file(QStrToSysPath(peaks_result_filename));
std::string channel_str = QString(QStringLiteral(u"通道")).toStdString();
std::string addr_str = QString(QStringLiteral(u"峰位")).toStdString();
std::string left_addr_str = QString(QStringLiteral(u"左边界")).toStdString();
std::string lright_addr_str = QString(QStringLiteral(u"右边界")).toStdString();
std::string width_str = QString(QStringLiteral(u"峰宽")).toStdString();
std::string height_str = QString(QStringLiteral(u"峰高")).toStdString();
out_file << channel_str << "," << addr_str << "," << left_addr_str << "," << lright_addr_str << "," << width_str << "," << height_str << "\n";
auto row_count = peaks_result_table->rowCount();
for (int i = 0; i < row_count - 1; i++) {
std::string channel = peaks_result_table->item(i, 0)->text().toStdString();
int peak_pos = peaks_result_table->item(i, 1)->text().toInt();
int left_bound = peaks_result_table->item(i, 2)->text().toInt();
int right_bound = peaks_result_table->item(i, 3)->text().toInt();
int peak_width = peaks_result_table->item(i, 4)->text().toInt();
int peak_height = peaks_result_table->item(i, 5)->text().toInt();
out_file << channel << "," << peak_pos << "," << left_bound << "," << right_bound << "," << peak_width << "," << peak_height << "\n";
}
LOG_INFO(QStringLiteral(u"保存峰信息完成."));
});
connect(peaks_result_table, &QTableWidget::itemChanged, [this, peaks_result_table](QTableWidgetItem* item) {
bool is_watch_item_changed = peaks_result_table->property("WatchItemChanged").toBool();
if (is_watch_item_changed && bool(item->column() == 0)) {
this->updatePlotPeakInfoByTableItem(item);
}
});
connect(peaks_result_table, &QTableWidget::currentItemChanged, [this, peaks_result_table](QTableWidgetItem* current, QTableWidgetItem* previous) {
bool is_watch_item_changed = peaks_result_table->property("WatchItemChanged").toBool();
if (is_watch_item_changed) {
this->updatePlotPeakInfoByTableItem(previous, false, false);
this->updatePlotPeakInfoByTableItem(current, true, true);
}
});
QVBoxLayout* layout = new QVBoxLayout(_find_peaks_result_dlg);
layout->addLayout(top_layout);
layout->addWidget(peaks_result_table);
} }
_find_peaks_result_dlg->show();
} }
void MeasureAnalysisParticleCountPlotView::onActionAutoFindPeaks() void MeasureAnalysisParticleCountPlotView::onActionAutoFindPeaks()
@ -594,18 +378,22 @@ void MeasureAnalysisParticleCountPlotView::onActionAutoFindPeaks()
void MeasureAnalysisParticleCountPlotView::onActionManualFindPeaks() void MeasureAnalysisParticleCountPlotView::onActionManualFindPeaks()
{ {
_data_selector->setEnabled(true); // _data_selector->setEnabled(true);
} }
void MeasureAnalysisParticleCountPlotView::onActionEneryScale() void MeasureAnalysisParticleCountPlotView::onActionEneryScale()
{ {
_data_selector->setEnabled(true);
if (!_batch_enery_scale_dlg) { if (!_batch_enery_scale_dlg) {
_batch_enery_scale_dlg = new BatchEneryScaleDialog(this); _batch_enery_scale_dlg = new BatchEneryScaleDialog(this);
_batch_enery_scale_dlg->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred); _batch_enery_scale_dlg->SetPeakResultDataModel(_find_peaks_result_dlg->GetPeakResultDataModel());
_batch_enery_scale_dlg->setWindowTitle(QString(QStringLiteral(u"多通道能量刻度"))); connect(_data_selector, &CustomQwtPlotXaxisSelector::selectionFinished, _batch_enery_scale_dlg, &BatchEneryScaleDialog::onSelectedScaleRange);
connect(_batch_enery_scale_dlg, &BatchEneryScaleDialog::close, [this](){
this->_data_selector->setEnabled(false);
disconnect(_data_selector, &CustomQwtPlotXaxisSelector::selectionFinished, _batch_enery_scale_dlg, &BatchEneryScaleDialog::onSelectedScaleRange);
});
} }
_batch_enery_scale_dlg->show(); _batch_enery_scale_dlg->show();
_data_selector->setEnabled(true);
} }
void MeasureAnalysisParticleCountPlotView::onActionPlotConfigure() void MeasureAnalysisParticleCountPlotView::onActionPlotConfigure()

View File

@ -13,6 +13,7 @@ class QTableWidget;
class QTableWidgetItem; class QTableWidgetItem;
class CustomQwtPlotXaxisSelector; class CustomQwtPlotXaxisSelector;
class BatchEneryScaleDialog; class BatchEneryScaleDialog;
class FindPeaksResultDialog;
class MeasureAnalysisParticleCountPlotView : public MeasureAnalysisView class MeasureAnalysisParticleCountPlotView : public MeasureAnalysisView
{ {
@ -27,10 +28,10 @@ public:
private: private:
void setupMenu(); void setupMenu();
void setupPlot(); void setupPlot();
void setupPeakResultDlg();
void loadDataFromFile(const QString &data_name, const QString& filename); void loadDataFromFile(const QString &data_name, const QString& filename);
void loadPeaksResultToTable(QTableWidget* peaks_result_table); void loadPeaksResultToTable(QTableWidget* peaks_result_table);
void updatePlotPeakInfo(QVariantMap peak_infos); void updatePlotPeakInfo(const QVariantMap& peak_infos);
void updatePlotPeakInfoByTableItem(QTableWidgetItem* item, bool checked = false, bool show_peak_area = false);
private slots: private slots:
void onAutoFindPeaksFinished(const QString& project_name); void onAutoFindPeaksFinished(const QString& project_name);
@ -48,7 +49,7 @@ private:
QMenu* _menu = nullptr; QMenu* _menu = nullptr;
QDialog* _curve_show_setting_dlg = nullptr; QDialog* _curve_show_setting_dlg = nullptr;
QMap<QString, QVariant> _data_files_set_ptr; QMap<QString, QVariant> _data_files_set_ptr;
QDialog* _find_peaks_result_dlg = nullptr; FindPeaksResultDialog* _find_peaks_result_dlg = nullptr;
CustomQwtPlotXaxisSelector* _data_selector = nullptr; CustomQwtPlotXaxisSelector* _data_selector = nullptr;
BatchEneryScaleDialog* _batch_enery_scale_dlg = nullptr; BatchEneryScaleDialog* _batch_enery_scale_dlg = nullptr;
}; };

View File

@ -92,7 +92,7 @@ void MeasureAnalysisTreeView::onNodeDoubleClicked(const QModelIndex& index)
if ( view ) { if ( view ) {
view->InitViewWorkspace(project_name); view->InitViewWorkspace(project_name);
view->SetProjectName(project_name); view->SetProjectName(project_name);
const auto& view_name = QStringLiteral(u"%1 [%2]").arg(item_text).arg(project_name); const auto& view_name = QStringLiteral(u"%1[%2]").arg(item_text).arg(project_name);
view->SetViewName(view_name); view->SetViewName(view_name);
view->SetViewDescription(view_name); view->SetViewDescription(view_name);
view->SetAnalyzeDataFilename(data_files_set); view->SetAnalyzeDataFilename(data_files_set);
@ -120,11 +120,11 @@ void MeasureAnalysisTreeView::onNodeDoubleClicked(const QModelIndex& index)
view = _item_views[item]; view = _item_views[item];
} else { } else {
view = MeasureAnalysisView::NewAnalyzeView(analysis_type); view = MeasureAnalysisView::NewAnalyzeView(analysis_type);
view->InitViewWorkspace(project_name);
view->SetProjectName(project_name); view->SetProjectName(project_name);
const auto& view_name = QStringLiteral(u"%1 [%2]").arg(item_text).arg(project_name); const auto& view_name = QStringLiteral(u"%1[%2]").arg(item_text).arg(project_name);
view->SetViewName(view_name); view->SetViewName(view_name);
view->SetViewDescription(view_name); view->SetViewDescription(view_name);
view->InitViewWorkspace(project_name);
view->SetAnalyzeDataFilename(data_files_set); view->SetAnalyzeDataFilename(data_files_set);
} }
if ( view ) { if ( view ) {

View File

@ -45,6 +45,7 @@ SOURCES += \
MeasureAnalysisDataTableView.cpp \ MeasureAnalysisDataTableView.cpp \
MeasureAnalysisHistoryForm.cpp \ MeasureAnalysisHistoryForm.cpp \
MeasureAnalysisParticleCountPlotView/BatchEneryScaleDialog.cpp \ MeasureAnalysisParticleCountPlotView/BatchEneryScaleDialog.cpp \
MeasureAnalysisParticleCountPlotView/FindPeaksResultDialog.cpp \
MeasureAnalysisParticleCountPlotView/MeasureAnalysisParticleCountPlotView.cpp \ MeasureAnalysisParticleCountPlotView/MeasureAnalysisParticleCountPlotView.cpp \
MeasureAnalysisTreeView.cpp \ MeasureAnalysisTreeView.cpp \
MeasureAnalysisView.cpp \ MeasureAnalysisView.cpp \
@ -68,6 +69,7 @@ HEADERS += \
MeasureAnalysisDataTableView.h \ MeasureAnalysisDataTableView.h \
MeasureAnalysisHistoryForm.h \ MeasureAnalysisHistoryForm.h \
MeasureAnalysisParticleCountPlotView/BatchEneryScaleDialog.h \ MeasureAnalysisParticleCountPlotView/BatchEneryScaleDialog.h \
MeasureAnalysisParticleCountPlotView/FindPeaksResultDialog.h \
MeasureAnalysisParticleCountPlotView/MeasureAnalysisParticleCountPlotView.h \ MeasureAnalysisParticleCountPlotView/MeasureAnalysisParticleCountPlotView.h \
MeasureAnalysisTreeView.h \ MeasureAnalysisTreeView.h \
MeasureAnalysisView.h \ MeasureAnalysisView.h \