From cad4ee2df76acc47c03a3368d0276c9b8e1820cf Mon Sep 17 00:00:00 2001 From: anxinglong <2910824064@qq.com> Date: Fri, 12 Jun 2026 18:43:51 +0800 Subject: [PATCH] =?UTF-8?q?=E6=96=B0=E5=A2=9E=E9=81=93=E5=9D=80=E8=AE=A1?= =?UTF-8?q?=E6=95=B0=E8=B0=B1=E5=AE=9E=E6=97=B6=E8=AF=BB=E5=8F=96=E6=95=B0?= =?UTF-8?q?=E6=8D=AE=EF=BC=8C=E4=BF=AE=E6=94=B9=E9=81=93=E5=9D=80=E8=AE=A1?= =?UTF-8?q?=E6=95=B0=E8=B0=B1=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/CustomQwtPlot.cpp | 5 + src/CustomQwtPlot.h | 1 + src/MainWindow.cpp | 108 +++++++++++++++--- src/MainWindow.h | 11 +- .../ParticleCountPlotView.cpp | 21 ++++ .../ParticleCountPlotView.h | 2 + 6 files changed, 129 insertions(+), 19 deletions(-) diff --git a/src/CustomQwtPlot.cpp b/src/CustomQwtPlot.cpp index a53049e..292a8ff 100644 --- a/src/CustomQwtPlot.cpp +++ b/src/CustomQwtPlot.cpp @@ -299,6 +299,11 @@ void CustomQwtPlot::AddCurve(QwtPlotCurve *curve, bool auto_color) } } +void CustomQwtPlot::clearCurve() +{ + _curves.clear(); +} + QwtPlotMarker *CustomQwtPlot::GetMarker(const QString &marker_name, const QString &postion) { return _markers.value(marker_name).value(postion); diff --git a/src/CustomQwtPlot.h b/src/CustomQwtPlot.h index 46e1650..1847176 100644 --- a/src/CustomQwtPlot.h +++ b/src/CustomQwtPlot.h @@ -72,6 +72,7 @@ public: QwtPlotCurve* GetCurve(const QString& curve_name); QList GetCurveList() const; void AddCurve(QwtPlotCurve* curve, bool auto_color = true); + void clearCurve(); QwtPlotMarker* GetMarker(const QString& marker_name, const QString& postion); QList GetMarkerList() const; diff --git a/src/MainWindow.cpp b/src/MainWindow.cpp index 674ef04..13d459d 100644 --- a/src/MainWindow.cpp +++ b/src/MainWindow.cpp @@ -34,6 +34,8 @@ #include "MeasureAnalysisDataTableView.h" #include "DataCalcProcess/GaussPolyCoe.h" #include "EnergyScaleDataModel.h" +#include "ParticleCountPlotView.h" +#include #include "csv.h" #include @@ -100,6 +102,10 @@ MainWindow::MainWindow(QWidget* parent) _status_bar = ui->statusbar; _gvfToCsv = new GvfToCsv; _measure_client = new MeasureClient; + m_AddressCountTimer = new QTimer(this); + m_AddressCountTimer->setInterval(10000);//10秒刷新一次 + connect(m_AddressCountTimer, &QTimer::timeout, this, &MainWindow::on_AddressCountTimer); + connect(_measure_client, &MeasureClient::getDeviceListResult, this, &MainWindow::onGetDeviceListResult); connect(_measure_client, &MeasureClient::startMeasureResult, this, &MainWindow::onStartMeasureResult); connect(_measure_client, &MeasureClient::stopMeasureResult, this, &MainWindow::onStopMeasureResult); @@ -611,6 +617,8 @@ void MainWindow::onGvfData(const QByteArray &data) changeParticleEnergyData(particles); //处理能量计数 changeEnergyCountData(particles); + //处理道址计数谱 + changeAddressCountView(particles); } //处理粒子数据 @@ -704,7 +712,15 @@ void MainWindow::changeChannelParticleCount(QList &data) // 计算本次数据的增量计数 for (const auto &info : data) { int channel_num = (info.boardId) * 4 + (info.channelId + 1); - deltaCounts[channel_num][info.address]++; + uint address = info.address; + + // 道址范围校验(防止越界) + if (address >= 4096) { + LOG_WARN(QStringLiteral(u"道址%1超出最大范围%2,已跳过").arg(address).arg(4096)); + continue; + } + + deltaCounts[channel_num][address]++; totalParticles++; } @@ -739,6 +755,22 @@ void MainWindow::changeChannelParticleCount(QList &data) uint channel_num = channelIt.key(); const auto& addressDeltas = channelIt.value(); + // 关键优化:如果是新通道,初始化4096个道址为0 + if (!channel_address_counts.contains(channel_num)) { + std::array initCounts; + initCounts.fill(0); // 所有道址初始化为0 + channel_address_counts.insert(channel_num, initCounts); + } + + // 更新内存中的总计数 + auto& channelCounts = channel_address_counts[channel_num]; + for (auto addressIt = addressDeltas.constBegin(); addressIt != addressDeltas.constEnd(); ++addressIt) { + uint address = addressIt.key(); + unsigned long long delta = addressIt.value(); + channelCounts[address] += delta; + } + + // 获取或创建通道文件名 QString count_data_filename; if (particle_count_filename_list.contains(channel_num)) { count_data_filename = particle_count_filename_list[channel_num]; @@ -749,12 +781,7 @@ void MainWindow::changeChannelParticleCount(QList &data) newChannelFiles.insert(channel_num, count_data_filename); } - for (auto addressIt = addressDeltas.constBegin(); addressIt != addressDeltas.constEnd(); ++addressIt) { - uint address = addressIt.key(); - unsigned long long delta = addressIt.value(); - channel_address_counts[channel_num][address] += delta; - } - + // 重写整个CSV文件(Truncate模式) QFile outFile(count_data_filename); if (!outFile.open(QIODevice::WriteOnly | QIODevice::Text | QIODevice::Truncate)) { LOG_ERROR(QStringLiteral(u"无法打开通道%1的计数文件: %2,错误: %3") @@ -771,16 +798,12 @@ void MainWindow::changeChannelParticleCount(QList &data) // 写入表头 out << QStringLiteral(u"道址,计数\n"); - // 写入所有道址的最新总计数(按道址排序) + // 关键修改:写入完整的0-4095道址数据 QString csvBuffer; - csvBuffer.reserve(channel_address_counts[channel_num].size() * 32); // 预分配内存 + csvBuffer.reserve(4096 * 32); // 预分配足够内存(约128KB) - // 获取排序后的道址列表 - QList sortedAddresses = channel_address_counts[channel_num].keys(); - std::sort(sortedAddresses.begin(), sortedAddresses.end()); - - for (uint address : sortedAddresses) { - unsigned long long total = channel_address_counts[channel_num][address]; + for (int address = 0; address < 4096; ++address) { + unsigned long long total = channelCounts[address]; csvBuffer += QString("%1,%2\n").arg(address).arg(total); } @@ -932,7 +955,60 @@ void MainWindow::changeEnergyCountData(QList &dataList) { } +//处理道址计数谱 +void MainWindow::changeAddressCountView(QList &dataList) +{ + if (dataList.isEmpty()) { + return; + } + MeasureAnalysisProjectModel* pro_model = ProjectList::Instance()->GetCurrentProjectModel(); + if (!pro_model) { + LOG_ERROR(QStringLiteral(u"当前没有打开的测量项目,无法处理能谱数据")); + return; + } + + bool status_ok = !pro_model->GetChannelAddressCountDataFilenameList().isEmpty(); + QString status = status_ok ? QStringLiteral(u"有效") : QStringLiteral(u"无效"); + QString item_name = QStringLiteral(u"道址计数谱"); + QStandardItem * particleData = nodeMap[item_name]; + //获取道址计数谱状态 + bool bStatus = ProjectList::Instance()->GetNodeStatus(particleData); + if(!bStatus) + { + ProjectList::Instance()->SetNodeStatus(particleData,status,true); + m_AddressCountTimer->start(); + } +} + +void MainWindow::on_AddressCountTimer() +{ + QMap data_files_set; + //获取道址计数谱 + auto dockList = _dock_manager->dockWidgetsMap().values(); + for(auto dock : dockList) + { + ParticleCountPlotView* view = dynamic_cast(dock->widget()); + if(!view) continue; + if(view->GetAnalyzeType() == AnalysisType::AddressCountSpectrumView) + { + MeasureAnalysisProjectModel* project_model = ProjectList::Instance()->GetCurrentProjectModel(); + if (project_model) { + auto file_name_list = project_model->GetChannelAddressCountDataFilenameList(); + if ( !file_name_list.isEmpty() ) { + auto ch_num_list = file_name_list.keys(); + for(auto ch_num : ch_num_list) { + auto file_name = file_name_list[ch_num]; + if ( !file_name.isEmpty() ) { + data_files_set[QStringLiteral(u"通道%1").arg(ch_num)] = file_name; + } + } + } + } + view->updateView(data_files_set); + } + } +} void MainWindow::on_action_stop_measure_triggered() { @@ -942,5 +1018,5 @@ void MainWindow::on_action_stop_measure_triggered() return; } _measure_client->stopMeasure(device_guid); + m_AddressCountTimer->stop(); } - diff --git a/src/MainWindow.h b/src/MainWindow.h index ab23733..8c095e6 100644 --- a/src/MainWindow.h +++ b/src/MainWindow.h @@ -5,6 +5,7 @@ #include #include "GvfToCsv/GvfToCsv.h" #include "MeasureAnalysisProjectModel.h" +#include QT_BEGIN_NAMESPACE namespace Ui { @@ -65,7 +66,8 @@ private: void changeParticleEnergyData(QList &dataList); //处理能量计数 void changeEnergyCountData(QList &dataList); - + //处理道址计数谱 + void changeAddressCountView(QList &dataList); signals: void newProject(const QString &project_name); @@ -93,7 +95,7 @@ private slots: void on_action_stop_measure_triggered(); - + void on_AddressCountTimer(); private: QMutex _mutex_info_output; QPlainTextEdit* _plain_edit_info_output; @@ -115,7 +117,7 @@ private: GvfToCsv *_gvfToCsv = nullptr; - QMap> channel_address_counts; // 通道号 -> 地址 -> 计数 + QHash> channel_address_counts; // 改为数组 QMap particle_count_filename_list; //2026-06-11 QMap nodeMap; @@ -128,5 +130,8 @@ private: QMap m_allChannelEnergyStats; // 全通道能量bin -> 计数 QMutex m_energyCountMutex; // 保护能量计数数据的互斥锁 QHash> m_energyScaleCoeffCache;// 能量刻度系数缓存 + + //道址计数视图定时器 + QTimer* m_AddressCountTimer; }; #endif // MAINWINDOW_H diff --git a/src/ParticleCountPlotView/ParticleCountPlotView.cpp b/src/ParticleCountPlotView/ParticleCountPlotView.cpp index 8cf1666..d59b3fc 100644 --- a/src/ParticleCountPlotView/ParticleCountPlotView.cpp +++ b/src/ParticleCountPlotView/ParticleCountPlotView.cpp @@ -116,6 +116,27 @@ void ParticleCountPlotView::SetAnalyzeDataFilename(const QMap } } +void ParticleCountPlotView::updateView(const QMap& data_files_set) +{ + // 清除现有所有曲线 + for (QwtPlotCurve* curve : this->_plot->GetCurveList()) { + curve->detach(); + delete curve; + } + _plot->clearCurve(); + + + // 重新加载数据 + if (!data_files_set.isEmpty()) { + SetAnalyzeDataFilename(data_files_set); + } + // 清除标记并重绘 + this->_plot->CleanMarkers(); + this->_plot->CleanZoneItems(); + this->_plot->ResetPlot(); + this->_plot->replot(); +} + void ParticleCountPlotView::setupMenu() { this->setContextMenuPolicy(Qt::CustomContextMenu); diff --git a/src/ParticleCountPlotView/ParticleCountPlotView.h b/src/ParticleCountPlotView/ParticleCountPlotView.h index 3667c89..8547c50 100644 --- a/src/ParticleCountPlotView/ParticleCountPlotView.h +++ b/src/ParticleCountPlotView/ParticleCountPlotView.h @@ -25,6 +25,8 @@ public: virtual void InitViewWorkspace(const QString& project_name) override final; virtual void SetAnalyzeDataFilename(const QMap& data_files_set); + void updateView(const QMap& data_files_set); + private: void setupMenu(); void setupPlot();