From c0c1ee39e38791c8c3c534334dbdd4d379190742 Mon Sep 17 00:00:00 2001 From: anxinglong <2910824064@qq.com> Date: Thu, 26 Mar 2026 10:03:45 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E7=B2=92=E5=AD=90=E6=97=B6?= =?UTF-8?q?=E9=97=B4=E5=B7=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ParticleTimePoorView.cpp | 260 ++++++++++++++++++ .../ParticleTimePoorView.h | 44 +++ .../ParticleTimePoorView.ui | 64 +++++ 3 files changed, 368 insertions(+) create mode 100644 src/ParticleTimePoorView/ParticleTimePoorView.cpp create mode 100644 src/ParticleTimePoorView/ParticleTimePoorView.h create mode 100644 src/ParticleTimePoorView/ParticleTimePoorView.ui diff --git a/src/ParticleTimePoorView/ParticleTimePoorView.cpp b/src/ParticleTimePoorView/ParticleTimePoorView.cpp new file mode 100644 index 0000000..b3ada20 --- /dev/null +++ b/src/ParticleTimePoorView/ParticleTimePoorView.cpp @@ -0,0 +1,260 @@ +#include "ParticleTimePoorView.h" +#include "ui_ParticleTimePoorView.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "CustomQwtPlot.h" +#include +#include +#include +ParticleTimePoorView::ParticleTimePoorView(QWidget *parent) : + MeasureAnalysisView(parent), + ui(new Ui::ParticleTimePoorView) +{ + ui->setupUi(this); + this->setViewType(PlotFrame); + + InitUi(); + +} + +ParticleTimePoorView::~ParticleTimePoorView() +{ + delete ui; +} + +void ParticleTimePoorView::InitViewWorkspace(const QString &project_name) +{ + +} +#include +void ParticleTimePoorView::SetAnalyzeDataFilename(const QMap &data_files_set) +{ + if (data_files_set.isEmpty()) { + LOG_WARN("文件集合为空"); + return; + } + + QString filePath = data_files_set.first().toString(); + LOG_INFO("读取文件: " + filePath); + + io::CSVReader<4> in(QStrToSysPath(filePath)); + in.read_header(io::ignore_extra_column, "板卡号", "通道号", "道址", "时间计数"); + + int board, channel; + double energy, time_count; + QVector timestamps; + + while (in.read_row(board, channel, energy, time_count)) { + timestamps.append(static_cast(time_count)); + } + + if (timestamps.size() < 2) { + qDebug() << "数据不足,无法计算时间差"; + return; + } + + // 1. 统计时间差分布 + const int nNs = 50; // 分组宽度 + QMap mapVal; + for (int i = 0; i < timestamps.size() - 1; ++i) { + uint64_t diff = timestamps[i+1] - timestamps[i]; + uint64_t binIndex = diff / nNs; + mapVal[binIndex]++; + } + + // 2. 准备直方图数据 + QVector histogramData; + double xMin = 0.0, xMax = 0.0; // 用于记录实际数据的最小/最大 x 值 + int nmaxy = 0; + QMap::iterator it = mapVal.begin(); + for (; it != mapVal.end(); ++it) { + uint64_t binIndex = it.key(); + int count = it.value(); + + double center = binIndex * nNs + nNs / 2.0; + double halfWidth = (nNs - 1) / 2.0; + double left = center - halfWidth; + double right = center + halfWidth; + + if (left < xMin) xMin = left; + if (right > xMax) xMax = right; + + QwtInterval interval(left, right); + histogramData.append(QwtIntervalSample(count, interval)); + + if (count > nmaxy) nmaxy = count; + } + + // 3. 创建直方图 + QwtPlotHistogram* histogram = new QwtPlotHistogram(); + histogram->setSamples(histogramData); // 注意:QwtPlotHistogram 使用 setData() + histogram->setBrush(QBrush(QColor(23, 229, 238))); + histogram->setStyle(QwtPlotHistogram::Columns); + histogram->attach(plot); + m_histogram = histogram; // 保存指针以便后续动态调整 y 轴 + + // ========== 修改后的 x 轴范围设置 ========== + const double MAX_DISPLAY_TIME = 5000.0; // 最大显示时间差 (ns),可根据需求调整 + + // 确保 xMin 不为负 + if (xMin < 0.0) xMin = 0.0; + // x 轴显示上限:取实际数据最大值和 MAX_DISPLAY_TIME 的最小值 + double xDisplayMax = qMin(xMax, MAX_DISPLAY_TIME); + // 如果实际数据最大值小于最大显示上限,则使用实际最大值;否则使用限制值 + if (xDisplayMax <= xMin) xDisplayMax = xMin + 1.0; // 防止空范围 + + plot->setAxisScale(QwtPlot::xBottom, xMin, xDisplayMax); + plot->setAxisScale(QwtPlot::yLeft, 0, nmaxy * 1.05); + // ========================================== + + // 4. 启用水平拖拽 + QwtPlotPanner* panner = new QwtPlotPanner(plot->canvas()); + panner->setAxisEnabled(QwtPlot::yLeft, false); + panner->setAxisEnabled(QwtPlot::xBottom, true); + + // 获取 x 轴的 QwtScaleWidget + QwtScaleWidget* xAxisWidget = plot->axisWidget(QwtPlot::xBottom); + if (xAxisWidget) { + // 连接 x 轴的 scaleDivChanged 信号(无参版本) + connect(xAxisWidget, &QwtScaleWidget::scaleDivChanged, this, + [this]() { + if (m_histogram) { + // 获取当前 x 轴范围 + const QwtScaleDiv& scaleDiv = plot->axisScaleDiv(QwtPlot::xBottom); + double min = scaleDiv.lowerBound(); + double max = scaleDiv.upperBound(); + + // 计算当前 x 可见范围内的最大计数值 + double maxY = 0.0; + const QwtSeriesData* data = m_histogram->data(); + if (data) { + for (int i = 0; i < data->size(); ++i) { + QwtIntervalSample sample = data->sample(i); + if (sample.interval.intersects(QwtInterval(min, max))) { + if (sample.value > maxY) + maxY = sample.value; + } + } + } + if (maxY == 0.0) maxY = 1.0; + plot->setAxisScale(QwtPlot::yLeft, 0, maxY * 1.05); + plot->replot(); + } + }); + } + + // 6. 设置轴标题 + plot->setAxisTitle(QwtPlot::xBottom, QStringLiteral(u"时间差 (ns)")); + plot->setAxisTitle(QwtPlot::yLeft, QStringLiteral(u"粒子计数")); + + plot->replot(); + LOG_INFO("直方图已添加并刷新"); +} + +void ParticleTimePoorView::setData(QVector data) +{ +// int energyStart = ui->label_energyStart->text().toInt(); +// int energyEnd = ui->label_energyEnd->text().toInt(); + +// QVector x; +// QVector y; + +// double minValue = 0; +// double maxValue = 0; +// for(auto info : data) +// { +// if(info.dEnergy <= energyStart || info.dEnergy >= energyEnd) +// { +// continue; +// } +// x.append(info.index); +// y.append(info.dTime); +// minValue = qMin(minValue, info.dTime); +// maxValue = qMax(maxValue, info.dTime); +// } + +// // 创建曲线并设置数据 +// QwtPlotCurve *curve = new QwtPlotCurve(); +// curve->setSamples(x, y); +// // 将曲线添加到 CustomQwtPlot 中(会自动分配颜色) +// plot->AddCurve(curve); +// // 设置坐标轴范围和标题 +//// plot->setAxisScale(QwtPlot::xBottom, 0, x.last()); +//// plot->setAxisScale(QwtPlot::yLeft,minValue , maxValue); + +// LOG_INFO(QStringLiteral(u"%1数据读取完毕.").arg(this->GetViewName())); + +// // 刷新绘图 +// plot->replot(); + +} + +QVector ParticleTimePoorView::getParticleInjectTimeData(QString path) +{ + QVector records; + + io::CSVReader<4> in(QStrToSysPath(path)); + in.read_header(io::ignore_extra_column, "板卡号", "通道号", "能量(KeV)", "时间计数"); + + int board, channel; + double energy, time_count; + int lineNumber = 0; + + // 逐行读取 + while (in.read_row(board, channel, energy, time_count)) + { + int detector = board + channel * 8; + lineNumber++; + if(detector >= 32) + { + continue; + } + ParticleInjectTime rec; + rec.index = lineNumber; + rec.dEnergy = energy; + rec.dTime = time_count; + records.append(rec); + } + return records; +} + +void ParticleTimePoorView::InitUi() +{ + plot = new CustomQwtPlot(); + plot->SetXaxisDragScale(true); + setupPlot(); + ui->verticalLayout_2->addWidget(plot); +} + +void ParticleTimePoorView::setupPlot() +{ + plot->setCanvasBackground(Qt::white); + QwtPlotCanvas* canvas = qobject_cast(plot->canvas()); + canvas->setFrameStyle(QFrame::NoFrame); + + plot->setAxisTitle(QwtPlot::xBottom, QStringLiteral(u"粒子计数")); + plot->setAxisTitle(QwtPlot::yLeft, QStringLiteral(u"时间差")); + // set axis auto scale + plot->setAxisAutoScale(QwtPlot::xBottom, true); + plot->setAxisAutoScale(QwtPlot::yLeft, true); + // 启用网格线 + plot->enableAxis(QwtPlot::xBottom); + plot->enableAxis(QwtPlot::yLeft); + +// // 设置QWT图例 +// QwtLegend* legend = new QwtLegend(); +// legend->setDefaultItemMode(QwtLegendData::ReadOnly); +// plot->insertLegend(legend, QwtPlot::RightLegend); + + plot->SetXaxisDragScale(true); +} diff --git a/src/ParticleTimePoorView/ParticleTimePoorView.h b/src/ParticleTimePoorView/ParticleTimePoorView.h new file mode 100644 index 0000000..ff73490 --- /dev/null +++ b/src/ParticleTimePoorView/ParticleTimePoorView.h @@ -0,0 +1,44 @@ +#ifndef PARTICLETIMEPOORVIEW_H +#define PARTICLETIMEPOORVIEW_H + +#include +#include "qwt.h" +#include "CustomQwtPlot.h" +#include +#include +#include "MeasureAnalysisView.h" +#include "csv.h" +#include + + +namespace Ui { +class ParticleTimePoorView; +} + +class ParticleTimePoorView : public MeasureAnalysisView +{ + Q_OBJECT + +public: + explicit ParticleTimePoorView(QWidget *parent = nullptr); + virtual ~ParticleTimePoorView(); + + virtual void InitViewWorkspace(const QString& project_name) override final; + virtual void SetAnalyzeDataFilename(const QMap& data_files_set); + + void setData(QVector data); + + //获取数据 + QVector getParticleInjectTimeData(QString path); +private: + void InitUi(); + void setupPlot(); + +private: + Ui::ParticleTimePoorView *ui; + CustomQwtPlot *plot; + QVector m_AllData;//存储的所有的粒子入射时间数据 + QwtPlotHistogram* m_histogram; +}; + +#endif // PARTICLEINJECTTIMEANALYSIS_H diff --git a/src/ParticleTimePoorView/ParticleTimePoorView.ui b/src/ParticleTimePoorView/ParticleTimePoorView.ui new file mode 100644 index 0000000..13e5cdd --- /dev/null +++ b/src/ParticleTimePoorView/ParticleTimePoorView.ui @@ -0,0 +1,64 @@ + + + ParticleTimePoorView + + + + 0 + 0 + 997 + 307 + + + + ParticleInjectTimeAnalysis + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + 0 + 0 + + + + + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + + + + + + + +