From bfd9485c8b2f3b1a7ebb70f27bab12bbca000b36 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BE=90=E6=B5=B7?= Date: Tue, 17 Mar 2026 18:38:50 +0800 Subject: [PATCH] =?UTF-8?q?1=E3=80=81=E8=B0=83=E6=95=B4=E4=BB=A3=E7=A0=81?= =?UTF-8?q?=E7=BB=93=E6=9E=84=EF=BC=9B2=E3=80=81=E6=B7=BB=E5=8A=A0?= =?UTF-8?q?=E5=A4=9A=E9=80=9A=E9=81=93=E8=83=BD=E9=87=8F=E5=88=BB=E5=BA=A6?= =?UTF-8?q?=EF=BC=9B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/CustomQwtPlot.cpp | 3 + src/CustomQwtPlot.h | 2 +- src/DataCalcProcess/FindPeaksBySvd.cpp | 29 +- src/DataCalcProcess/FindPeaksBySvd.h | 5 +- src/DataProcessWorkPool.cpp | 87 +++-- src/GlobalDefine.h | 11 + .../BatchEneryScaleDialog.cpp | 26 +- .../BatchEneryScaleDialog.h | 14 + .../BatchEneryScaleDialog.ui | 71 +++- .../FindPeaksResultDialog.cpp | 272 +++++++++++++++ .../FindPeaksResultDialog.h | 36 ++ .../MeasureAnalysisParticleCountPlotView.cpp | 316 +++--------------- .../MeasureAnalysisParticleCountPlotView.h | 7 +- src/MeasureAnalysisTreeView.cpp | 6 +- src/src.pro | 2 + 15 files changed, 570 insertions(+), 317 deletions(-) create mode 100644 src/MeasureAnalysisParticleCountPlotView/FindPeaksResultDialog.cpp create mode 100644 src/MeasureAnalysisParticleCountPlotView/FindPeaksResultDialog.h diff --git a/src/CustomQwtPlot.cpp b/src/CustomQwtPlot.cpp index c3265d0..522b0b0 100644 --- a/src/CustomQwtPlot.cpp +++ b/src/CustomQwtPlot.cpp @@ -85,6 +85,9 @@ void CustomQwtPlot::AddMarker(QwtPlotMarker *marker, const QString &marker_name, QPen pen = curve->pen(); pen.setWidth(2); marker->setLinePen(pen); + QwtText label_text = marker->label(); + label_text.setColor(Qt::black); + marker->setLabel(label_text); marker->attach(this); _markers[marker_name][postion] = marker; } diff --git a/src/CustomQwtPlot.h b/src/CustomQwtPlot.h index b907599..88765f4 100644 --- a/src/CustomQwtPlot.h +++ b/src/CustomQwtPlot.h @@ -83,7 +83,7 @@ public: void clearSelection(); signals: - void selectionFinished(double minX, double maxX); + void selectionFinished(double min_x, double max_x); protected: virtual void move(const QPoint& pos) override; diff --git a/src/DataCalcProcess/FindPeaksBySvd.cpp b/src/DataCalcProcess/FindPeaksBySvd.cpp index d62d46f..b437225 100644 --- a/src/DataCalcProcess/FindPeaksBySvd.cpp +++ b/src/DataCalcProcess/FindPeaksBySvd.cpp @@ -85,6 +85,31 @@ std::vector FindPeaksBySvd::FindPeaks(const arma::mat vec peak_region = spec_data_col1.subvec(Lc, Rc); double height = peak_region.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); // 筛选有效峰:峰宽>2且中心DistV>0 @@ -98,6 +123,8 @@ std::vector FindPeaksBySvd::FindPeaks(const arma::mat peak_info.width = spec_data_col0.at(width); peak_info.height = height; peak_info.pos = spec_data_col0.at(pos); + peak_info.fwhm = fwhm; + peak_info.area = area; peak_info_vec.push_back(peak_info); } } @@ -112,4 +139,4 @@ std::vector FindPeaksBySvd::FindPeaks(const arma::mat throw std::string("Find peaks unkonow exception"); } return peak_info_vec; -} +} \ No newline at end of file diff --git a/src/DataCalcProcess/FindPeaksBySvd.h b/src/DataCalcProcess/FindPeaksBySvd.h index 0baa366..5ec46a7 100644 --- a/src/DataCalcProcess/FindPeaksBySvd.h +++ b/src/DataCalcProcess/FindPeaksBySvd.h @@ -13,11 +13,12 @@ public: double width = 0.0f; // 峰所在数据区域的宽度 double height = 0.0f; // 峰所在数据区域的高度 double pos = 0.0f; // 峰所在位置 - double fwhm = 0.0f; // 峰所在位置 + double fwhm = 0.0f; // 峰的半高宽 + double area = 0.0f; // 峰的面积 } PeakInfo; std::vector FindPeaks(const arma::mat& spec_data, int step_w = 7); }; -#endif // FINDPEAKSBYSVD_H +#endif // FINDPEAKSBYSVD_H \ No newline at end of file diff --git a/src/DataProcessWorkPool.cpp b/src/DataProcessWorkPool.cpp index 9490722..f486742 100644 --- a/src/DataProcessWorkPool.cpp +++ b/src/DataProcessWorkPool.cpp @@ -154,11 +154,13 @@ bool EveryChannelParticleDataSeparateTask::processEveryChannelParticleData() *ch_particle_data_of << board_id << "," << channel_id << "," << address << "," << time << std::endl; } } 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) ret_ok = false; } 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) ret_ok = false; } catch (...) { @@ -303,15 +305,17 @@ bool EveryChannelParticleCountDataTask::processEveryChannelParticleData() // all_channel_out.close(); } 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) ret_ok = false; } 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) ret_ok = false; } 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) ret_ok = false; } @@ -529,7 +533,8 @@ bool ParticleDataSortTask::processEveryChannelParticleData() } } 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) ret_ok = false; } catch (...) { @@ -576,7 +581,7 @@ bool AutoFindPeaksTask::IsValidSetWorkParameters() const 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::string channel_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 height_str = QString(QStringLiteral(u"峰高")).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) { - std::string channel = it.key().toStdString(); - arma::mat data; - const std::string data_filename = QStrToSysPath(it.value().toString()); - if (!data.load(data_filename, arma::csv_ascii)) { - QString error = QString(QStringLiteral(u"%1自动寻峰数据加载异常!")).arg(it.key()); - LOG_WARN(error); - continue; - } - FindPeaksBySvd peak_svd; - std::vector peak_info_vec = peak_svd.FindPeaks(data, this->_step_win_width); - 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; - 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"; + QStringList ch_count_data_name = this->_data_files_set.keys(); + std::sort(ch_count_data_name.begin(), ch_count_data_name.end(), [](const QString& a, const QString& b) { + int num_a = ExtractNumberFromString(a); + int num_b = ExtractNumberFromString(b); + return num_a < num_b; + }); + for (const QString& ch_count_data_name : ch_count_data_name) { + 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(); + std::string channel = ch_count_data_name.toStdString(); + arma::mat data; + const std::string data_filename = QStrToSysPath(ch_count_data_filename); + if (!data.load(data_filename, arma::csv_ascii)) { + QString error = QString(QStringLiteral(u"%1自动寻峰数据加载异常!")).arg(ch_count_data_name); + LOG_WARN(error); + continue; } - } else { - const QString& error = QStringLiteral(u"%1自动寻峰异常!").arg(it.key()); - LOG_WARN(error); + FindPeaksBySvd peak_svd; + std::vector peak_info_vec = peak_svd.FindPeaks(data, this->_step_win_width); + 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(); diff --git a/src/GlobalDefine.h b/src/GlobalDefine.h index ae4c39e..955a506 100644 --- a/src/GlobalDefine.h +++ b/src/GlobalDefine.h @@ -4,6 +4,7 @@ #include "MainWindow.h" #include "QsLog.h" #include +#include #include // 转换Qt字符串路径为系统编码的C字符串(解决中文路径问题) @@ -22,6 +23,16 @@ static const char* QStrToSysPath(const QString& qstr_path) 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) \ { \ diff --git a/src/MeasureAnalysisParticleCountPlotView/BatchEneryScaleDialog.cpp b/src/MeasureAnalysisParticleCountPlotView/BatchEneryScaleDialog.cpp index a1c2112..860d1fa 100644 --- a/src/MeasureAnalysisParticleCountPlotView/BatchEneryScaleDialog.cpp +++ b/src/MeasureAnalysisParticleCountPlotView/BatchEneryScaleDialog.cpp @@ -1,15 +1,39 @@ #include "BatchEneryScaleDialog.h" #include "ui_BatchEneryScaleDialog.h" +#include -BatchEneryScaleDialog::BatchEneryScaleDialog(QWidget *parent) +BatchEneryScaleDialog::BatchEneryScaleDialog(QWidget* parent) : QDialog(parent) , ui(new Ui::BatchEneryScaleDialog) { ui->setupUi(this); 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() { 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(); +} diff --git a/src/MeasureAnalysisParticleCountPlotView/BatchEneryScaleDialog.h b/src/MeasureAnalysisParticleCountPlotView/BatchEneryScaleDialog.h index 1ca278b..1a6f858 100644 --- a/src/MeasureAnalysisParticleCountPlotView/BatchEneryScaleDialog.h +++ b/src/MeasureAnalysisParticleCountPlotView/BatchEneryScaleDialog.h @@ -3,6 +3,8 @@ #include +class QAbstractTableModel; + namespace Ui { class BatchEneryScaleDialog; } @@ -15,8 +17,20 @@ public: explicit BatchEneryScaleDialog(QWidget *parent = nullptr); ~BatchEneryScaleDialog(); + void SetPeakResultDataModel(QAbstractTableModel *peaks_result_model); + +public slots: + void onSelectedScaleRange(double min, double max); + +signals: + void close(); + +protected: + void closeEvent(QCloseEvent *e); + private: Ui::BatchEneryScaleDialog *ui; + QAbstractTableModel* _peaks_result_model; }; #endif // BATCHENERYSCALEDIALOG_H diff --git a/src/MeasureAnalysisParticleCountPlotView/BatchEneryScaleDialog.ui b/src/MeasureAnalysisParticleCountPlotView/BatchEneryScaleDialog.ui index 9ce1f15..b87dff1 100644 --- a/src/MeasureAnalysisParticleCountPlotView/BatchEneryScaleDialog.ui +++ b/src/MeasureAnalysisParticleCountPlotView/BatchEneryScaleDialog.ui @@ -6,18 +6,35 @@ 0 0 - 824 - 409 + 929 + 404 - Dialog + 多通道能量刻度 + + 16 + + + + + 全选 + + + + + + + 反选 + + + @@ -26,7 +43,14 @@ - + + + + 75 + 0 + + + @@ -40,10 +64,24 @@ - + + + + 125 + 0 + + + + + + + 删除勾选 + + + @@ -64,10 +102,26 @@ + + + + 保存 + + + - + + + QAbstractItemView::NoEditTriggers + + + QAbstractItemView::SingleSelection + + + QAbstractItemView::SelectRows + 通道 @@ -111,6 +165,11 @@ 分辨率偏差 + + + 操作 + + diff --git a/src/MeasureAnalysisParticleCountPlotView/FindPeaksResultDialog.cpp b/src/MeasureAnalysisParticleCountPlotView/FindPeaksResultDialog.cpp new file mode 100644 index 0000000..7992aca --- /dev/null +++ b/src/MeasureAnalysisParticleCountPlotView/FindPeaksResultDialog.cpp @@ -0,0 +1,272 @@ +#include "FindPeaksResultDialog.h" +#include "GlobalDefine.h" +#include +#include +#include +#include +#include +#include +#include +#include "csv.h" +#include +#include + +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(_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; +} diff --git a/src/MeasureAnalysisParticleCountPlotView/FindPeaksResultDialog.h b/src/MeasureAnalysisParticleCountPlotView/FindPeaksResultDialog.h new file mode 100644 index 0000000..59cb2eb --- /dev/null +++ b/src/MeasureAnalysisParticleCountPlotView/FindPeaksResultDialog.h @@ -0,0 +1,36 @@ +#ifndef FINDPEAKSRESULTDIALOG_H +#define FINDPEAKSRESULTDIALOG_H + +#include +#include +#include + +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 diff --git a/src/MeasureAnalysisParticleCountPlotView/MeasureAnalysisParticleCountPlotView.cpp b/src/MeasureAnalysisParticleCountPlotView/MeasureAnalysisParticleCountPlotView.cpp index ec604de..ba7fc7d 100644 --- a/src/MeasureAnalysisParticleCountPlotView/MeasureAnalysisParticleCountPlotView.cpp +++ b/src/MeasureAnalysisParticleCountPlotView/MeasureAnalysisParticleCountPlotView.cpp @@ -15,7 +15,6 @@ #include #include #include -#include #include #include #include @@ -28,16 +27,7 @@ #include #include #include "BatchEneryScaleDialog.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; -}; +#include "FindPeaksResultDialog.h" MeasureAnalysisParticleCountPlotView::MeasureAnalysisParticleCountPlotView(QWidget* parent) : MeasureAnalysisView { parent } @@ -47,11 +37,11 @@ MeasureAnalysisParticleCountPlotView::MeasureAnalysisParticleCountPlotView(QWidg QHBoxLayout* layout = new QHBoxLayout(this); this->_plot = new CustomQwtPlot(this); layout->addWidget(this->_plot); + this->_menu = new QMenu(this); setupPlot(); - - this->_menu = new QMenu(this); setupMenu(); + setupPeakResultDlg(); } MeasureAnalysisParticleCountPlotView::~MeasureAnalysisParticleCountPlotView() @@ -69,20 +59,23 @@ void MeasureAnalysisParticleCountPlotView::InitViewWorkspace(const QString& proj return; } QDir project_dir(project_model->GetProjectDir()); - QString workspace = project_dir.filePath("AddressCountSpectrumView"); + QString workspace = project_dir.filePath(this->GetViewName()); if (QDir(workspace).exists()) { this->_workspace = workspace; } else if (project_dir.mkpath(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& data_files_set) { 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) { - int num_a = extractNumber(a); - int num_b = extractNumber(b); + int num_a = ExtractNumberFromString(a); + int num_b = ExtractNumberFromString(b); return num_a < num_b; }); for (const QString& ch_count_data_name : ch_count_data_name) { @@ -156,6 +149,26 @@ void MeasureAnalysisParticleCountPlotView::setupPlot() _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) { std::string address_str = QString(QStringLiteral(u"道址")).toStdString(); @@ -185,72 +198,7 @@ void MeasureAnalysisParticleCountPlotView::loadDataFromFile(const QString& data_ _plot->AddCurve(curve); } -void MeasureAnalysisParticleCountPlotView::loadPeaksResultToTable(QTableWidget* peaks_result_table) -{ - 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) +void MeasureAnalysisParticleCountPlotView::updatePlotPeakInfo(const QVariantMap &peak_infos) { const QString& channel = peak_infos["channel"].toString(); 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 peak_width = peak_infos["peak_width"].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_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->setValue(peak_pos, 0.0); 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); this->_plot->AddMarker(peak_marker, channel, postion); } else if (!is_checked) { @@ -286,46 +238,15 @@ void MeasureAnalysisParticleCountPlotView::updatePlotPeakInfo(QVariantMap peak_i 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) { Q_UNUSED(project_name); - if (_find_peaks_result_dlg) { - for (const auto& child_obj : _find_peaks_result_dlg->children()) { - if ("peaks_result_table" == child_obj->objectName()) { - QTableWidget* table = qobject_cast(child_obj); - if (table) { - loadPeaksResultToTable(table); - break; - } - } - } + this->_plot->CleanMarkers(); + this->_plot->replot(); + if (this->_find_peaks_result_dlg) { + this->_find_peaks_result_dlg->UpdatePeakResult(); + _find_peaks_result_dlg->show(); } - onActionFindPeaksResult(); } void MeasureAnalysisParticleCountPlotView::onActionCurveShowSetting() @@ -350,8 +271,8 @@ void MeasureAnalysisParticleCountPlotView::onActionCurveShowSetting() 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); + int num_a = ExtractNumberFromString(a); + int num_b = ExtractNumberFromString(b); return num_a < num_b; }); for (const QString& ch_name : list_ch_names) { @@ -407,146 +328,9 @@ void MeasureAnalysisParticleCountPlotView::onActionCurveShowSetting() void MeasureAnalysisParticleCountPlotView::onActionFindPeaksResult() { - if (!_find_peaks_result_dlg) { - _find_peaks_result_dlg = new QDialog(this, Qt::Dialog | Qt::WindowCloseButtonHint); - _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); + if (_find_peaks_result_dlg) { + _find_peaks_result_dlg->show(); } - _find_peaks_result_dlg->show(); } void MeasureAnalysisParticleCountPlotView::onActionAutoFindPeaks() @@ -594,18 +378,22 @@ void MeasureAnalysisParticleCountPlotView::onActionAutoFindPeaks() void MeasureAnalysisParticleCountPlotView::onActionManualFindPeaks() { - _data_selector->setEnabled(true); + // _data_selector->setEnabled(true); } void MeasureAnalysisParticleCountPlotView::onActionEneryScale() { - _data_selector->setEnabled(true); if (!_batch_enery_scale_dlg) { _batch_enery_scale_dlg = new BatchEneryScaleDialog(this); - _batch_enery_scale_dlg->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred); - _batch_enery_scale_dlg->setWindowTitle(QString(QStringLiteral(u"多通道能量刻度"))); + _batch_enery_scale_dlg->SetPeakResultDataModel(_find_peaks_result_dlg->GetPeakResultDataModel()); + 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(); + _data_selector->setEnabled(true); } void MeasureAnalysisParticleCountPlotView::onActionPlotConfigure() diff --git a/src/MeasureAnalysisParticleCountPlotView/MeasureAnalysisParticleCountPlotView.h b/src/MeasureAnalysisParticleCountPlotView/MeasureAnalysisParticleCountPlotView.h index 465cecb..3f4ecbb 100644 --- a/src/MeasureAnalysisParticleCountPlotView/MeasureAnalysisParticleCountPlotView.h +++ b/src/MeasureAnalysisParticleCountPlotView/MeasureAnalysisParticleCountPlotView.h @@ -13,6 +13,7 @@ class QTableWidget; class QTableWidgetItem; class CustomQwtPlotXaxisSelector; class BatchEneryScaleDialog; +class FindPeaksResultDialog; class MeasureAnalysisParticleCountPlotView : public MeasureAnalysisView { @@ -27,10 +28,10 @@ public: private: void setupMenu(); void setupPlot(); + void setupPeakResultDlg(); void loadDataFromFile(const QString &data_name, const QString& filename); void loadPeaksResultToTable(QTableWidget* peaks_result_table); - void updatePlotPeakInfo(QVariantMap peak_infos); - void updatePlotPeakInfoByTableItem(QTableWidgetItem* item, bool checked = false, bool show_peak_area = false); + void updatePlotPeakInfo(const QVariantMap& peak_infos); private slots: void onAutoFindPeaksFinished(const QString& project_name); @@ -48,7 +49,7 @@ private: QMenu* _menu = nullptr; QDialog* _curve_show_setting_dlg = nullptr; QMap _data_files_set_ptr; - QDialog* _find_peaks_result_dlg = nullptr; + FindPeaksResultDialog* _find_peaks_result_dlg = nullptr; CustomQwtPlotXaxisSelector* _data_selector = nullptr; BatchEneryScaleDialog* _batch_enery_scale_dlg = nullptr; }; diff --git a/src/MeasureAnalysisTreeView.cpp b/src/MeasureAnalysisTreeView.cpp index 71508c7..497b673 100644 --- a/src/MeasureAnalysisTreeView.cpp +++ b/src/MeasureAnalysisTreeView.cpp @@ -92,7 +92,7 @@ void MeasureAnalysisTreeView::onNodeDoubleClicked(const QModelIndex& index) if ( view ) { view->InitViewWorkspace(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->SetViewDescription(view_name); view->SetAnalyzeDataFilename(data_files_set); @@ -120,11 +120,11 @@ void MeasureAnalysisTreeView::onNodeDoubleClicked(const QModelIndex& index) view = _item_views[item]; } else { view = MeasureAnalysisView::NewAnalyzeView(analysis_type); - view->InitViewWorkspace(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->SetViewDescription(view_name); + view->InitViewWorkspace(project_name); view->SetAnalyzeDataFilename(data_files_set); } if ( view ) { diff --git a/src/src.pro b/src/src.pro index 276cede..c5d4bfd 100644 --- a/src/src.pro +++ b/src/src.pro @@ -45,6 +45,7 @@ SOURCES += \ MeasureAnalysisDataTableView.cpp \ MeasureAnalysisHistoryForm.cpp \ MeasureAnalysisParticleCountPlotView/BatchEneryScaleDialog.cpp \ + MeasureAnalysisParticleCountPlotView/FindPeaksResultDialog.cpp \ MeasureAnalysisParticleCountPlotView/MeasureAnalysisParticleCountPlotView.cpp \ MeasureAnalysisTreeView.cpp \ MeasureAnalysisView.cpp \ @@ -68,6 +69,7 @@ HEADERS += \ MeasureAnalysisDataTableView.h \ MeasureAnalysisHistoryForm.h \ MeasureAnalysisParticleCountPlotView/BatchEneryScaleDialog.h \ + MeasureAnalysisParticleCountPlotView/FindPeaksResultDialog.h \ MeasureAnalysisParticleCountPlotView/MeasureAnalysisParticleCountPlotView.h \ MeasureAnalysisTreeView.h \ MeasureAnalysisView.h \