#include "CountRateAnalysisView.h" #include "ui_CountRateAnalysisView.h" #include #include #include #include #include #include #include #include #include #include #include #include "CustomQwtPlot.h" #include #include #include "csv.h" #include #include "BusyIndicator.h" #include CountRateAnalysisView::CountRateAnalysisView(QWidget *parent) : MeasureAnalysisView(parent), ui(new Ui::CountRateAnalysisView) { ui->setupUi(this); this->setViewType(PlotFrame); this->_menu = new QMenu(this); _busy_indicator = new BusyIndicatorWidget(this); InitUi(); setupMenu(); } CountRateAnalysisView::~CountRateAnalysisView() { delete ui; } void CountRateAnalysisView::InitViewWorkspace(const QString &project_name) { } void CountRateAnalysisView::SetAnalyzeDataFilename(const QMap &data_files_set) { if(!data_files_set.isEmpty()) { _busy_indicator->Start(); auto functionToRun = [this,data_files_set] { QVector data = getParticleInjectTimeData(data_files_set.first().toString()); QMetaObject::invokeMethod(this, [this, data]() { setData(data); _busy_indicator->Stop(); }, Qt::QueuedConnection); }; QThread* load_data_thread = QThread::create(functionToRun); load_data_thread->start(); } } void CountRateAnalysisView::showEvent(QShowEvent *e) { Q_UNUSED(e); if (_busy_indicator) { _busy_indicator->setGeometry(this->rect()); this->update(); } } void CountRateAnalysisView::setData(QVector data) { int energyStart = ui->label_energyStart->text().toInt(); int energyEnd = ui->label_energyEnd->text().toInt(); int nInv = 1; constexpr qint64 NS_PER_SECOND = 1000000000; // 纳秒转秒的基数 if (data.isEmpty()) return; // 添加空列表保护 QVector x; QVector y; const ParticleInjectTime& lostdt = data.last(); const qint64 totalNanoseconds = lostdt.dTime * 5; const int nAllS = static_cast(totalNanoseconds / NS_PER_SECOND) + 1; const int nVecSize = nAllS / nInv; QVector vec(nVecSize); // 默认初始化为0 double x_max = 0; double y_max = 0; for(auto info : data) { const qint64 ns = (info.dTime * 5) / NS_PER_SECOND; const int nidx = static_cast(ns / nInv); // 整数除法,速度快 if (nidx < nVecSize) { ++vec[nidx]; // 使用 ++ 而非 vec[nidx]++ if ( y_max < vec[nidx] ) y_max = vec[nidx]; } } QVector vecXpt(vec.size()); for (int i = 0; i < vec.size(); ++i) { vecXpt[i] = static_cast(i); if ( x_max < vecXpt[i] ) x_max = vecXpt[i]; } plot->SetAxisInitRange(QwtPlot::xBottom, 0.0f, x_max); plot->SetAxisInitRange(QwtPlot::yLeft, 0.0f, y_max); // 创建曲线并设置数据 QwtPlotCurve *curve = new QwtPlotCurve(); curve->setSamples(vecXpt, vec); // 将曲线添加到 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 CountRateAnalysisView::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 CountRateAnalysisView::InitUi() { plot = new CustomQwtPlot(); setupPlot(); ui->verticalLayout_2->addWidget(plot); } void CountRateAnalysisView::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->SetAxisDragScale(QwtPlot::xBottom, true); } void CountRateAnalysisView::setupMenu() { this->setContextMenuPolicy(Qt::CustomContextMenu); connect(this, &CountRateAnalysisView::customContextMenuRequested, [this](const QPoint& pos) { this->_menu->exec(this->mapToGlobal(pos)); }); QAction* action_plot_reset = this->_menu->addAction(QStringLiteral(u"还原")); action_plot_reset->setObjectName("plot_reset"); connect(action_plot_reset, &QAction::triggered, [this]() { this->plot->ResetPlot(); }); this->_menu->addSeparator(); QAction* action_plot_config = this->_menu->addAction(QStringLiteral(u"图表配置")); action_plot_config->setObjectName("plot_config"); connect(action_plot_config, &QAction::triggered, this, &CountRateAnalysisView::onActionPlotConfigure); } void CountRateAnalysisView::onActionPlotConfigure() { }