EnergySpectrumAnalyer/src/AntiConformEnergySpectrumView/AntiConformEnergySpectrumView.cpp
2026-07-10 18:23:33 +08:00

201 lines
6.5 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "AntiConformEnergySpectrumView.h"
#include "BusyIndicator.h"
#include "CustomQwtPlot.h"
#include "csv.h"
#include <GlobalDefine.h>
#include <QFileInfo>
#include <QMenu>
#include <QPen>
#include <QThread>
#include <QVBoxLayout>
#include <QwtPlotCanvas>
#include <QwtPlotCurve>
#include <QwtText>
#include <algorithm>
#include <cstdint>
#include <map>
#include <vector>
//反符合能谱
AntiConformEnergySpectrumView::AntiConformEnergySpectrumView(QWidget* parent)
: MeasureAnalysisView(parent)
{
this->setViewType(PlotFrame);
this->_menu = new QMenu(this);
setupMenu();
_plot = new CustomQwtPlot();
QVBoxLayout* layout = new QVBoxLayout(this);
layout->addWidget(_plot);
_plot->setCanvasBackground(Qt::white);
QwtPlotCanvas* canvas = qobject_cast<QwtPlotCanvas*>(_plot->canvas());
canvas->setFrameStyle(QFrame::NoFrame);
_roi = new RegionOfInterest();
connect(_roi, &RegionOfInterest::roiSelected,this, &AntiConformEnergySpectrumView::slot_roi_data);
QFont font = this->font();
font.setBold(false);
QwtText x_label = QStringLiteral(u"能量(KeV)");
QwtText y_label = QStringLiteral(u"反符合事件次数");
x_label.setFont(font);
y_label.setFont(font);
_plot->setAxisTitle(QwtPlot::xBottom, x_label);
_plot->setAxisTitle(QwtPlot::yLeft, y_label);
_plot->setAxisAutoScale(QwtPlot::xBottom, true);
_plot->setAxisAutoScale(QwtPlot::yLeft, true);
_plot->enableAxis(QwtPlot::xBottom);
_plot->enableAxis(QwtPlot::yLeft);
_plot->SetAxisDragScale(QwtPlot::xBottom, true);
_plot->SetAxisDragScale(QwtPlot::yLeft, true);
_curve = new QwtPlotCurve();
_curve->setStyle(QwtPlotCurve::Lines);
_curve->setPen(QPen(QColor(23, 229, 238), 2));
_plot->AddCurve(_curve);
_busy_indicator = new BusyIndicatorWidget(this);
}
AntiConformEnergySpectrumView::~AntiConformEnergySpectrumView()
{
}
void AntiConformEnergySpectrumView::InitViewWorkspace(const QString& project_name)
{
Q_UNUSED(project_name);
}
void AntiConformEnergySpectrumView::SetAnalyzeDataFilename(const QMap<QString, QVariant>& data_files_set)
{
const QString& data_filename = data_files_set.first().toString();
if (!data_filename.isEmpty() && QFileInfo(data_filename).exists()) {
this->_data_filename = data_filename;
this->loadAndProcess();
}
}
QwtPlotMarker *AntiConformEnergySpectrumView::createVLine(double x, Qt::GlobalColor color, double lineWidth)
{
QwtPlotMarker* marker = new QwtPlotMarker();
marker->setXValue(x);
marker->setLineStyle(QwtPlotMarker::VLine);
QPen pen(color);
pen.setWidthF(lineWidth);
marker->setLinePen(pen);
marker->attach(_plot);
return marker;
}
void AntiConformEnergySpectrumView::loadAndProcess()
{
_busy_indicator->Start();
auto functionToRun = [this]() {
if (_data_filename.isEmpty()) {
QMetaObject::invokeMethod(this, [this]() {
_busy_indicator->Stop();
}, Qt::QueuedConnection);
return;
}
io::CSVReader<5> in(QStrToSysPath(_data_filename));
in.read_header(io::ignore_extra_column,
QString(QStringLiteral(u"时间窗口")).toStdString(),
QString(QStringLiteral(u"板卡号")).toStdString(),
QString(QStringLiteral(u"通道号")).toStdString(),
QString(QStringLiteral(u"能量(KeV)")).toStdString(),
QString(QStringLiteral(u"时间计数")).toStdString());
const int STEP = 1;
std::map<int, double> hist;
int time_win, board, channel;
double energy;
unsigned long long time_count;
while (in.read_row(time_win, board, channel, energy, time_count)) {
int idx = static_cast<int>(energy) / STEP;
hist[idx] += 1.0;
}
QVector<double> vx, vy;
for (const auto& pair : hist) {
vx.push_back(pair.first * STEP);
vy.push_back(pair.second);
}
if (vx.isEmpty()) {
QMetaObject::invokeMethod(this, [this]() {
_busy_indicator->Stop();
}, Qt::QueuedConnection);
return;
}
double dmaxx = *std::max_element(vx.begin(), vx.end());
double dmaxy = *std::max_element(vy.begin(), vy.end());
QMetaObject::invokeMethod(this, [this, vx, vy, dmaxx, dmaxy]() {
_curve->setSamples(vx, vy);
_plot->SetAxisInitRange(QwtPlot::xBottom, 0.0f, dmaxx);
_plot->SetAxisInitRange(QwtPlot::yLeft, 0.0f, dmaxy);
_plot->replot();
_busy_indicator->Stop(); }, Qt::QueuedConnection);
};
QThread* load_thread = QThread::create(functionToRun);
load_thread->start();
}
void AntiConformEnergySpectrumView::onActionPlotConfigure()
{
}
void AntiConformEnergySpectrumView::onActionRoiTriggered()
{
_roi->show();
}
void AntiConformEnergySpectrumView::slot_roi_data(ROIItem &item)
{
// 第一组起始1、结束1 红色竖线,必须存在才插入,所以一定绘制
createVLine(item.s1, Qt::red, 1.2);
createVLine(item.e1, Qt::red, 1.2);
// 第二组起始2、结束2 有有效数值才绘制,无值跳过
bool secondGroupValid = !(qIsNaN(item.s2) || qIsNaN(item.e2) || (item.s2 == 0 && item.e2 == 0));
if (secondGroupValid)
{
createVLine(item.s2, Qt::blue, 1.2);
createVLine(item.e2, Qt::blue, 1.2);
}
_plot->replot();
}
void AntiConformEnergySpectrumView::showEvent(QShowEvent* e)
{
Q_UNUSED(e);
if (_busy_indicator) {
_busy_indicator->setGeometry(this->rect());
this->update();
}
}
void AntiConformEnergySpectrumView::setupMenu()
{
this->setContextMenuPolicy(Qt::CustomContextMenu);
connect(this, &AntiConformEnergySpectrumView::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, &AntiConformEnergySpectrumView::onActionPlotConfigure);
QAction* action_roi = this->_menu->addAction(QStringLiteral(u"感兴趣区"));
action_roi->setObjectName("roi");
connect(action_roi,&QAction::triggered,this,&AntiConformEnergySpectrumView::onActionRoiTriggered);
}