EnergySpectrumAnalyer/src/CountRateAnalysisView/CountRateAnalysisView.cpp
2026-05-20 19:53:21 +08:00

205 lines
6.0 KiB
C++

#include "CountRateAnalysisView.h"
#include "ui_CountRateAnalysisView.h"
#include <QVBoxLayout>
#include <QPushButton>
#include <QMessageBox>
#include <QwtPlotCurve>
#include <QwtPlotMarker>
#include <QwtPlotZoneItem>
#include <QwtPlotCanvas>
#include <QwtLegend>
#include <QwtText>
#include <cmath>
#include <QtMath>
#include "CustomQwtPlot.h"
#include <QDebug>
#include <GlobalDefine.h>
#include "csv.h"
#include <QThread>
#include "BusyIndicator.h"
#include <QMenu>
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<QString, QVariant> &data_files_set)
{
if(!data_files_set.isEmpty()) {
_busy_indicator->Start();
auto functionToRun = [this,data_files_set] {
QVector<ParticleInjectTime> 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<ParticleInjectTime> 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<double> x;
QVector<double> y;
const ParticleInjectTime& lostdt = data.last();
const qint64 totalNanoseconds = lostdt.dTime * 5;
const int nAllS = static_cast<int>(totalNanoseconds / NS_PER_SECOND) + 1;
const int nVecSize = nAllS / nInv;
QVector<double> 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<int>(ns / nInv); // 整数除法,速度快
if (nidx < nVecSize) {
++vec[nidx]; // 使用 ++ 而非 vec[nidx]++
if ( y_max < vec[nidx] )
y_max = vec[nidx];
}
}
QVector<double> vecXpt(vec.size());
for (int i = 0; i < vec.size(); ++i) {
vecXpt[i] = static_cast<double>(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<ParticleInjectTime> CountRateAnalysisView::getParticleInjectTimeData(QString path)
{
QVector<ParticleInjectTime> 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<QwtPlotCanvas*>(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()
{
}