201 lines
6.5 KiB
C++
201 lines
6.5 KiB
C++
#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);
|
||
}
|