新增符合能谱视图,新增2维视图显示左侧悬浮窗口

This commit is contained in:
anxinglong 2026-04-09 17:55:20 +08:00
parent b209ba9737
commit 65e7a5787c
8 changed files with 529 additions and 42 deletions

View File

@ -8,6 +8,7 @@
#include <QwtLinearColorMap>
#include <QwtMatrixRasterData>
#include <QHBoxLayout>
#include <QVBoxLayout>
#include <QFile>
#include <QTextStream>
#include <QDebug>
@ -15,16 +16,21 @@
#include <QwtInterval>
#include <qwt_matrix_raster_data.h>
#include <algorithm>
// 自定义颜色映射(热力图)
#include <QFormLayout>
#include <QLabel>
#include <QPushButton>
#include <QLineEdit>
#include <QMouseEvent>
#include <QSet>
class HeatMapColorMap : public QwtLinearColorMap
{
public:
HeatMapColorMap() : QwtLinearColorMap(Qt::white, Qt::red)
HeatMapColorMap() : QwtLinearColorMap(Qt::blue, Qt::red)
{
addColorStop(0.25, Qt::blue);
addColorStop(0.25, Qt::cyan);
addColorStop(0.5, Qt::green);
addColorStop(0.75, Qt::yellow);
addColorStop(0.90, Qt::darkRed);
}
};
@ -38,6 +44,7 @@ TwoDSpectralCompliance::TwoDSpectralCompliance(QWidget *parent) :
this->_plot = new CustomQwtPlot(this);
layout->addWidget(this->_plot);
setupPlot();
createFloatingInfoWidget();
}
TwoDSpectralCompliance::~TwoDSpectralCompliance()
@ -47,7 +54,6 @@ TwoDSpectralCompliance::~TwoDSpectralCompliance()
void TwoDSpectralCompliance::InitViewWorkspace(const QString &project_name)
{
// 可预留用于项目初始化
Q_UNUSED(project_name);
}
@ -55,9 +61,6 @@ void TwoDSpectralCompliance::SetAnalyzeDataFilename(const QMap<QString, QVariant
{
if (data_files_set.isEmpty())
return;
// 约定data_files_set 的 key 为符合次数(如 "2", "3"...value 为 CSV 文件路径
// 我们只处理第一个文件(通常只有一个)
QString csvFile = data_files_set.first().toString();
if (csvFile.isEmpty())
return;
@ -67,6 +70,7 @@ void TwoDSpectralCompliance::SetAnalyzeDataFilename(const QMap<QString, QVariant
updateSpectrogram();
}
void TwoDSpectralCompliance::setupPlot()
{
_plot->setCanvasBackground(Qt::white);
@ -76,38 +80,29 @@ void TwoDSpectralCompliance::setupPlot()
QFont font = this->font();
font.setBold(false);
QwtText energy_label = QStringLiteral(u"次级粒子能量和 (keV)");
QwtText energy_label = QStringLiteral(u"初级粒子能量");
energy_label.setFont(font);
QwtText count_label = QStringLiteral(u"初级粒子能量 (keV)");
QwtText count_label = QStringLiteral(u"次级粒子能量");
count_label.setFont(font);
_plot->setAxisTitle(QwtPlot::xBottom, energy_label);
_plot->setAxisTitle(QwtPlot::yLeft, count_label);
// 自动缩放
_plot->setAxisAutoScale(QwtPlot::xBottom, true);
_plot->setAxisAutoScale(QwtPlot::yLeft, true);
_plot->enableAxis(QwtPlot::xBottom);
_plot->enableAxis(QwtPlot::yLeft);
// 图例
QwtLegend* legend = new QwtLegend();
legend->setDefaultItemMode(QwtLegendData::ReadOnly);
_plot->insertLegend(legend, QwtPlot::RightLegend);
// 启用拖拽缩放
_plot->SetAxisDragScale(QwtPlot::xBottom, true);
_plot->SetAxisDragScale(QwtPlot::yLeft, true);
// 创建 spectrogram
_spectrogram = new QwtPlotSpectrogram();
_spectrogram->setColorMap(new HeatMapColorMap());
_spectrogram->attach(_plot);
_plot->setAutoFillBackground(true);
QPalette pal = _plot->palette();
pal.setColor(QPalette::Window, Qt::white);
_plot->setPalette(pal);
}
void TwoDSpectralCompliance::readCsv(const QString &filename)
@ -115,12 +110,12 @@ void TwoDSpectralCompliance::readCsv(const QString &filename)
m_rawData.clear();
QFile file(filename);
if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
qWarning() << "无法打开文件:" << filename;
qWarning() << QStringLiteral(u"无法打开文件:") << filename;
return;
}
QTextStream stream(&file);
QString header = stream.readLine(); // 跳过标题行
QString header = stream.readLine();
Q_UNUSED(header);
while (!stream.atEnd()) {
@ -141,7 +136,6 @@ void TwoDSpectralCompliance::readCsv(const QString &filename)
m_rawData.append(data);
}
file.close();
qDebug() << "读取了" << m_rawData.size() << "条事件记录";
}
void TwoDSpectralCompliance::generateSurfaceData()
@ -150,13 +144,11 @@ void TwoDSpectralCompliance::generateSurfaceData()
if (m_rawData.isEmpty())
return;
// 按事件ID分组每个事件中第一个粒子为初级其余为次级
QMap<int, QVector<EventData>> eventMap;
for (const auto& ev : m_rawData) {
eventMap[ev.eventId].append(ev);
}
// 使用 QMap 来累加相同坐标的计数(初级能量,次级能量和)
QMap<QPair<float, float>, int> countMap;
for (auto it = eventMap.begin(); it != eventMap.end(); ++it) {
@ -164,7 +156,6 @@ void TwoDSpectralCompliance::generateSurfaceData()
if (events.isEmpty())
continue;
// 第一个事件作为初级粒子
float primaryEnergy = events[0].energy;
float secondarySum = 0.0f;
for (int i = 1; i < events.size(); ++i) {
@ -175,7 +166,6 @@ void TwoDSpectralCompliance::generateSurfaceData()
countMap[key]++;
}
// 转换为 SurfacePoint 列表
for (auto it = countMap.begin(); it != countMap.end(); ++it) {
TwoSurfacePoint point;
point.primaryEnergy = it.key().first;
@ -184,7 +174,6 @@ void TwoDSpectralCompliance::generateSurfaceData()
m_surfaceData.append(point);
}
qDebug() << "生成了" << m_surfaceData.size() << "个唯一坐标点";
}
void TwoDSpectralCompliance::updateSpectrogram()
@ -195,7 +184,6 @@ void TwoDSpectralCompliance::updateSpectrogram()
return;
}
// 找出能量范围
float minPrim = 1e9f, maxPrim = -1e9f;
float minSec = 1e9f, maxSec = -1e9f;
int maxCount = 0;
@ -208,7 +196,6 @@ void TwoDSpectralCompliance::updateSpectrogram()
maxCount = std::max(maxCount, pt.count);
}
// 增加边界
double primRange = maxPrim - minPrim;
double secRange = maxSec - minSec;
if (primRange < 1e-6) primRange = 1.0;
@ -218,9 +205,8 @@ void TwoDSpectralCompliance::updateSpectrogram()
double secStart = minSec - secRange * 0.05;
double secEnd = maxSec + secRange * 0.05;
// 使用不同名称,避免宏冲突
const int numCols = 200; // X轴方向点数初级能量
const int numRows = 200; // Y轴方向点数次级能量
const int numCols = 200;
const int numRows = 200;
double stepX = (primEnd - primStart) / numCols;
double stepY = (secEnd - secStart) / numRows;
@ -246,3 +232,203 @@ void TwoDSpectralCompliance::updateSpectrogram()
_plot->setAxisScale(QwtPlot::yLeft, secStart, secEnd);
_plot->replot();
}
void TwoDSpectralCompliance::createFloatingInfoWidget()
{
// 悬浮窗口
m_floatingWidget = new QWidget(this);
m_floatingWidget->setObjectName("FloatingInfoWidget");
m_floatingWidget->setStyleSheet(
"QWidget#FloatingInfoWidget {"
" background-color: rgba(240, 240, 240, 240);"
" border: 1px solid gray;"
" border-radius: 5px;"
"}"
);
m_floatingWidget->setFixedSize(320, 220);
m_floatingWidget->setAttribute(Qt::WA_TranslucentBackground, false);
QVBoxLayout* mainLayout = new QVBoxLayout(m_floatingWidget);
mainLayout->setSpacing(5);
mainLayout->setContentsMargins(8, 8, 8, 8);
// 标题栏(可拖动,并包含隐藏按钮)
QWidget* titleBar = new QWidget();
QHBoxLayout* titleLayout = new QHBoxLayout(titleBar);
titleLayout->setContentsMargins(0, 0, 0, 0);
QLabel* titleLabel = new QLabel(QStringLiteral(u"数据统计信息"));
titleLabel->setStyleSheet("font-weight: bold;");
titleLayout->addWidget(titleLabel);
titleLayout->addStretch();
QPushButton* hideBtn = new QPushButton(QStringLiteral(""));
hideBtn->setFixedSize(20, 20);
hideBtn->setToolTip(QStringLiteral(u"隐藏窗口"));
hideBtn->setStyleSheet("border: none; font-weight: bold;");
titleLayout->addWidget(hideBtn);
mainLayout->addWidget(titleBar);
QWidget* contentWidget = new QWidget();
QFormLayout* formLayout = new QFormLayout(contentWidget);
formLayout->setSpacing(8);
formLayout->setLabelAlignment(Qt::AlignRight);
m_totalEventsEdit = new QLineEdit;
m_totalEventsEdit->setReadOnly(true);
m_totalEventsEdit->setFixedWidth(130);
m_totalPointsEdit = new QLineEdit;
m_totalPointsEdit->setReadOnly(true);
m_totalPointsEdit->setFixedWidth(130);
m_maxCountEdit = new QLineEdit;
m_maxCountEdit->setReadOnly(true);
m_maxCountEdit->setFixedWidth(130);
m_primRangeEdit = new QLineEdit;
m_primRangeEdit->setReadOnly(true);
m_primRangeEdit->setFixedWidth(130);
m_secRangeEdit = new QLineEdit;
m_secRangeEdit->setReadOnly(true);
m_secRangeEdit->setFixedWidth(130);
formLayout->addRow(QStringLiteral(u"总事件数:"), m_totalEventsEdit);
formLayout->addRow(QStringLiteral(u"有效数据点:"), m_totalPointsEdit);
formLayout->addRow(QStringLiteral(u"最大计数:"), m_maxCountEdit);
formLayout->addRow(QStringLiteral(u"初级能量范围:"), m_primRangeEdit);
formLayout->addRow(QStringLiteral(u"次级能量和范围:"), m_secRangeEdit);
mainLayout->addWidget(contentWidget);
mainLayout->addStretch();
connect(hideBtn, &QPushButton::clicked, this, &TwoDSpectralCompliance::hideFloatingWidget);
titleBar->setCursor(Qt::SizeAllCursor);
m_floatingWidget->installEventFilter(this);
m_showButton = new QPushButton(this);
m_showButton->setFixedSize(28, 28);
m_showButton->setToolTip(QStringLiteral(u"显示信息窗口"));
m_showButton->setStyleSheet(
"QPushButton {"
" background-color: rgba(200,200,200,200);"
" border: 1px solid #888;"
" border-radius: 14px;"
" font-weight: bold;"
"}"
"QPushButton:hover { background-color: rgba(150,150,150,200); }"
);
m_showButton->setText("");
connect(m_showButton, &QPushButton::clicked, this, &TwoDSpectralCompliance::showFloatingWidget);
m_floatingWidget->move(10, 10);
updateShowButtonPosition();
m_floatingWidget->hide();
m_showButton->show();
// m_floatingWidget->raise();
updateInfoContent();
}
void TwoDSpectralCompliance::hideFloatingWidget()
{
m_floatingWidget->hide();
m_showButton->show();
updateShowButtonPosition();
}
void TwoDSpectralCompliance::showFloatingWidget()
{
m_floatingWidget->show();
m_floatingWidget->raise();
m_showButton->hide();
updateInfoContent(); // 刷新内容
}
void TwoDSpectralCompliance::updateShowButtonPosition()
{
if (m_showButton && m_showButton->isVisible()) {
m_showButton->move(10, 10);
}
}
void TwoDSpectralCompliance::updateInfoContent()
{
if (!m_totalEventsEdit)
return;
if (m_surfaceData.isEmpty()) {
m_totalEventsEdit->setText(QStringLiteral(u"无数据"));
m_totalPointsEdit->setText(QStringLiteral(u"无数据"));
m_maxCountEdit->setText(QStringLiteral(u"无数据"));
m_primRangeEdit->setText(QStringLiteral(u"无数据"));
m_secRangeEdit->setText(QStringLiteral(u"无数据"));
return;
}
int totalPoints = m_surfaceData.size();
int maxCount = 0;
float minPrim = 1e9f, maxPrim = -1e9f;
float minSec = 1e9f, maxSec = -1e9f;
for (const auto& pt : m_surfaceData) {
minPrim = std::min(minPrim, pt.primaryEnergy);
maxPrim = std::max(maxPrim, pt.primaryEnergy);
minSec = std::min(minSec, pt.secondaryEnergySum);
maxSec = std::max(maxSec, pt.secondaryEnergySum);
maxCount = std::max(maxCount, pt.count);
}
QSet<int> eventIds;
for (const auto& ev : m_rawData) {
eventIds.insert(ev.eventId);
}
int totalEvents = eventIds.size();
m_totalEventsEdit->setText(QString::number(totalEvents));
m_totalPointsEdit->setText(QString::number(totalPoints));
m_maxCountEdit->setText(QString::number(maxCount));
m_primRangeEdit->setText(QString("[%1, %2]").arg(minPrim, 0, 'f', 2).arg(maxPrim, 0, 'f', 2));
m_secRangeEdit->setText(QString("[%1, %2]").arg(minSec, 0, 'f', 2).arg(maxSec, 0, 'f', 2));
}
void TwoDSpectralCompliance::resizeEvent(QResizeEvent *event)
{
QWidget::resizeEvent(event);
updateShowButtonPosition();
if (m_floatingWidget && m_floatingWidget->isVisible()) {
// 限制悬浮窗口不超出父窗口边界
QRect rect = m_floatingWidget->geometry();
int newX = qBound(0, rect.x(), width() - rect.width());
int newY = qBound(0, rect.y(), height() - rect.height());
if (newX != rect.x() || newY != rect.y())
m_floatingWidget->move(newX, newY);
m_floatingWidget->raise();
}
}
bool TwoDSpectralCompliance::eventFilter(QObject *obj, QEvent *event)
{
if (obj == m_floatingWidget) {
if (event->type() == QEvent::MouseButtonPress) {
QMouseEvent *mouseEvent = static_cast<QMouseEvent*>(event);
if (mouseEvent->button() == Qt::LeftButton) {
m_dragging = true;
m_dragPosition = mouseEvent->globalPos() - m_floatingWidget->frameGeometry().topLeft();
event->accept();
return true;
}
} else if (event->type() == QEvent::MouseMove) {
if (m_dragging) {
QMouseEvent *mouseEvent = static_cast<QMouseEvent*>(event);
m_floatingWidget->move(mouseEvent->globalPos() - m_dragPosition);
event->accept();
return true;
}
} else if (event->type() == QEvent::MouseButtonRelease) {
if (m_dragging) {
m_dragging = false;
event->accept();
return true;
}
}
}
return QWidget::eventFilter(obj, event);
}

View File

@ -4,15 +4,17 @@
#include <QWidget>
#include <MeasureAnalysisView.h>
#include <QVector>
#include <QPoint>
class CustomQwtPlot;
class QwtPlotSpectrogram;
class QPushButton;
class QLineEdit;
class ScatterPlotItem;
namespace Ui {
class TwoDSpectralCompliance;
}
//// 用于存储三维数据点(初级能量,次级能量和,计数)
struct TwoSurfacePoint {
float primaryEnergy;
float secondaryEnergySum;
@ -29,6 +31,9 @@ public:
virtual void InitViewWorkspace(const QString& project_name) override final;
virtual void SetAnalyzeDataFilename(const QMap<QString, QVariant>& data_files_set) override;
protected:
void resizeEvent(QResizeEvent *event) override;
bool eventFilter(QObject *obj, QEvent *event) override;
private:
void setupPlot();
@ -36,12 +41,23 @@ private:
void generateSurfaceData();
void updateSpectrogram();
void createFloatingInfoWidget();
void updateInfoContent();
void updateToggleButtonText();
void updateFloatingWidgetPosition();
void updateToggleButtonPosition();
void updateShowButtonPosition();
private slots:
void showFloatingWidget();
void hideFloatingWidget();
private:
Ui::TwoDSpectralCompliance *ui;
CustomQwtPlot* _plot = nullptr;
QwtPlotSpectrogram* _spectrogram = nullptr;
// 原始数据
struct EventData {
int eventId;
int board;
@ -49,8 +65,21 @@ private:
double energy;
unsigned long long timeCounter;
};
QVector<EventData> m_rawData; // 从 CSV 读取的原始数据
QVector<TwoSurfacePoint> m_surfaceData; // 生成的曲面点(每个事件一个点,计数累加)
QVector<EventData> m_rawData;
QVector<TwoSurfacePoint> m_surfaceData;
QWidget* m_floatingWidget = nullptr;
QPushButton* m_toggleButton = nullptr;
QPushButton* m_showButton = nullptr;
QLineEdit* m_totalEventsEdit = nullptr;
QLineEdit* m_totalPointsEdit = nullptr;
QLineEdit* m_maxCountEdit = nullptr;
QLineEdit* m_primRangeEdit = nullptr;
QLineEdit* m_secRangeEdit = nullptr;
QPoint m_dragPosition;
bool m_dragging = false;
};
#endif // TWODSPECTRALCOMPLIANCE_H

View File

@ -0,0 +1,216 @@
#include "ConformToTheEnergySpectrum.h"
#include <QVBoxLayout>
#include <QwtPlotCurve>
#include <QwtPlotCanvas>
#include <QwtText>
#include "CustomQwtPlot.h"
#include <GlobalDefine.h>
#include "csv.h"
#include <QFileInfo>
#include <QThread>
#include "BusyIndicator.h"
#include <map>
#include <vector>
#include <algorithm>
#include <cstdint>
#include <QPen>
struct SpectrumData
{
int board_id;
int channel_id;
double energy;
uint64_t timestamp;
};
struct CoincidenceEvent
{
std::vector<SpectrumData> events;
};
ConformToTheEnergySpectrum::ConformToTheEnergySpectrum(QWidget *parent) :
MeasureAnalysisView(parent)
{
this->setViewType(PlotFrame);
_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);
_curve = new QwtPlotCurve();
_curve->setStyle(QwtPlotCurve::Lines);
_curve->setPen(QPen(QColor(23, 229, 238), 2));
_plot->AddCurve(_curve);
_busy_indicator = new BusyIndicator(this);
}
ConformToTheEnergySpectrum::~ConformToTheEnergySpectrum()
{
}
void ConformToTheEnergySpectrum::InitViewWorkspace(const QString &project_name)
{
Q_UNUSED(project_name);
}
void ConformToTheEnergySpectrum::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();
}
}
static std::vector<CoincidenceEvent> processCoincidence(const std::vector<SpectrumData>& data,
uint64_t time_window_ns = 50,
int min_order = 2,
int max_order = 9)
{
std::vector<CoincidenceEvent> result;
if (data.empty()) return result;
std::vector<SpectrumData> sorted = data;
std::sort(sorted.begin(), sorted.end(),
[](const SpectrumData& a, const SpectrumData& b) { return a.timestamp < b.timestamp; });
size_t n = sorted.size();
for (size_t i = 0; i < n; ++i)
{
std::vector<SpectrumData> cluster;
cluster.push_back(sorted[i]);
uint64_t base = sorted[i].timestamp;
for (size_t j = i + 1; j < n && (sorted[j].timestamp - base) <= time_window_ns; ++j)
cluster.push_back(sorted[j]);
for (size_t j = i; j > 0 && (base - sorted[j-1].timestamp) <= time_window_ns; --j)
if (j-1 != i) cluster.push_back(sorted[j-1]);
std::sort(cluster.begin(), cluster.end(),
[](const SpectrumData& a, const SpectrumData& b) { return a.timestamp < b.timestamp; });
cluster.erase(std::unique(cluster.begin(), cluster.end(),
[](const SpectrumData& a, const SpectrumData& b) {
return a.timestamp == b.timestamp && a.board_id == b.board_id && a.channel_id == b.channel_id;
}), cluster.end());
int order = (int)cluster.size();
if (order >= min_order && order <= max_order)
{
CoincidenceEvent ev;
ev.events = cluster;
result.push_back(ev);
i += (cluster.size() - 1);
}
}
return result;
}
void ConformToTheEnergySpectrum::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 uint64_t TIME_WINDOW_NS = 50;
const int MIN_ORDER = 2;
const int MAX_ORDER = 9;
std::vector<CoincidenceEvent> coincidences = processCoincidence(rawData, TIME_WINDOW_NS, MIN_ORDER, MAX_ORDER);
if (coincidences.empty()) {
_busy_indicator->Stop();
return;
}
const int STEP = 1;
std::map<int, double> hist;
for (const auto& ev : coincidences) {
for (const auto& spdt : ev.events) {
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->setAxisScale(QwtPlot::xBottom, 0, dmaxx);
_plot->setAxisScale(QwtPlot::yLeft, 0, dmaxy * 1.1);
_plot->replot();
_busy_indicator->Stop();
}, Qt::QueuedConnection);
};
QThread* load_thread = QThread::create(functionToRun);
load_thread->start();
}
void ConformToTheEnergySpectrum::showEvent(QShowEvent *e)
{
Q_UNUSED(e);
if (_busy_indicator) {
_busy_indicator->setGeometry(this->rect());
this->update();
}
}

View File

@ -0,0 +1,34 @@
#ifndef CONFORMTOTHEENERGYSPECTRUM_H
#define CONFORMTOTHEENERGYSPECTRUM_H
#include "MeasureAnalysisView.h"
class CustomQwtPlot;
class QwtPlotCurve;
class BusyIndicator;
class ConformToTheEnergySpectrum : public MeasureAnalysisView
{
Q_OBJECT
public:
explicit ConformToTheEnergySpectrum(QWidget *parent = nullptr);
virtual ~ConformToTheEnergySpectrum();
virtual void InitViewWorkspace(const QString& project_name) override final;
virtual void SetAnalyzeDataFilename(const QMap<QString, QVariant>& data_files_set) override;
protected:
virtual void showEvent(QShowEvent* e) override final;
private:
void loadAndProcess(); // 读取CSV执行符合处理绘制能谱折线图
private:
BusyIndicator* _busy_indicator = nullptr;
CustomQwtPlot* _plot = nullptr;
QwtPlotCurve* _curve = nullptr;
QString _data_filename;
};
#endif // CONFORMTOTHEENERGYSPECTRUM_H

View File

@ -260,6 +260,15 @@ void MeasureAnalysisTreeView::onNodeDoubleClicked(const QModelIndex& index)
}
}
} break;
case AnalysisType::CoincidenceParticleEnergySpectrumView: {
MeasureAnalysisProjectModel* project_model = _model->GetProjectModel(project_name);
if (project_model) {
auto file_name_list = project_model->GetTimeWinConformEnergyDataFilenameList(project_model->GetConformTimeWin());
for (auto it = file_name_list.constBegin(); it!=file_name_list.constEnd(); ++it) {
data_files_set[QString::number(it.key())] = it.value();
}
}
} break;
default:
break;
}

View File

@ -9,6 +9,7 @@
#include "ParticleInjectTimeAnalysisView.h"
#include "ParticleTimeDifferenceView.h"
#include "TwoDSpectralCompliance.h"
#include "ConformToTheEnergySpectrum.h"
#include <QMap>
MeasureAnalysisView* MeasureAnalysisView::NewAnalyzeView(AnalysisType view_type)
@ -96,8 +97,8 @@ MeasureAnalysisView* MeasureAnalysisView::NewAnalyzeView(AnalysisType view_type)
// new_view->setDeleteOnClose(false);
} break;
case AnalysisType::CoincidenceParticleEnergySpectrumView: {
// new_view = new MeasureAnalysisDataTableView;
// new_view->setDeleteOnClose(false);
new_view = new ConformToTheEnergySpectrum;
new_view->setDeleteOnClose(false);
} break;
case AnalysisType::AntiCoincidenceSpectrumView: {
// new_view = new MeasureAnalysisDataTableView;

View File

@ -13,7 +13,12 @@ ThreeDDisplay::ThreeDDisplay(QWidget *parent) :
ThreeDDisplay::~ThreeDDisplay()
{
delete ui;
// if(m_surface != nullptr) delete m_surface;
// if(m_dataProxy != nullptr) delete m_dataProxy;
// if(m_series != nullptr) delete m_series;
// if(m_surfaceContainer != nullptr) delete m_surfaceContainer;
}
void ThreeDDisplay::_init3DSurface()

View File

@ -36,7 +36,9 @@ INCLUDEPATH += \
$${PWD}/MeasureAnalysisHistoryForm \
$${PWD}/MeasureDeviceParamsConfigView \
$${PWD}/DeviceParameterConfig \
$${PWD}/2DSpectralCompliance
$${PWD}/2DSpectralCompliance \
$${PWD}/ConformToTheEnergySpectrum
DEPENDPATH += \
$${PWD}/BusyIndicator \
@ -52,7 +54,9 @@ DEPENDPATH += \
$${PWD}/MeasureAnalysisHistoryForm \
$${PWD}/MeasureDeviceParamsConfigView \
$${PWD}/DeviceParameterConfig \
$${PWD}/2DSpectralCompliance
$${PWD}/2DSpectralCompliance \
$${PWD}/ConformToTheEnergySpectrum
@ -95,6 +99,7 @@ SOURCES += \
ThreeDimensionalConformityAnalysisView/ThreeDDisplay.cpp \
EnergyCountPeakFitView/EnergyCountPeakFitView.cpp \
DeviceParameterConfig/DeviceParameterProxy.cpp \
ConformToTheEnergySpectrum/ConformToTheEnergySpectrum.cpp \
main.cpp
HEADERS += \
@ -138,7 +143,9 @@ HEADERS += \
ThreeDimensionalConformityAnalysisView/ParticleDataStatistics.h \
ThreeDimensionalConformityAnalysisView/ThreeDDisplay.h \
EnergyCountPeakFitView/EnergyCountPeakFitView.h \
DeviceParameterConfig/DeviceParameterProxy.h
DeviceParameterConfig/DeviceParameterProxy.h \
ConformToTheEnergySpectrum/ConformToTheEnergySpectrum.h \