180 lines
5.4 KiB
C++
180 lines
5.4 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>
|
|
|
|
struct SpectrumData {
|
|
int board_id;
|
|
int channel_id;
|
|
double energy;
|
|
uint64_t timestamp;
|
|
};
|
|
|
|
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);
|
|
|
|
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 BusyIndicator(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();
|
|
}
|
|
}
|
|
|
|
void AntiConformEnergySpectrumView::loadAndProcess()
|
|
{
|
|
auto functionToRun = [this]() {
|
|
if (_data_filename.isEmpty())
|
|
return;
|
|
|
|
_busy_indicator->Start();
|
|
|
|
std::vector<SpectrumData> rawData;
|
|
io::CSVReader<4> in(QStrToSysPath(_data_filename));
|
|
in.read_header(io::ignore_extra_column,
|
|
QString(QStringLiteral(u"板卡号")).toStdString(),
|
|
QString(QStringLiteral(u"通道号")).toStdString(),
|
|
QString(QStringLiteral(u"能量(KeV)")).toStdString(),
|
|
QString(QStringLiteral(u"时间计数")).toStdString());
|
|
|
|
int board, channel;
|
|
double energy;
|
|
unsigned long long time_count;
|
|
while (in.read_row(board, channel, energy, time_count)) {
|
|
SpectrumData sd;
|
|
sd.board_id = board;
|
|
sd.channel_id = channel;
|
|
sd.energy = energy;
|
|
sd.timestamp = time_count;
|
|
rawData.push_back(sd);
|
|
}
|
|
|
|
if (rawData.empty()) {
|
|
_busy_indicator->Stop();
|
|
return;
|
|
}
|
|
|
|
const int STEP = 1;
|
|
std::map<int, double> hist;
|
|
|
|
for (const auto& spdt : rawData) {
|
|
int idx = static_cast<int>(spdt.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()) {
|
|
_busy_indicator->Stop();
|
|
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::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);
|
|
}
|