2026-03-26 17:35:58 +08:00
|
|
|
|
#ifndef CONFORMITYANALYSIS_H
|
|
|
|
|
|
#define CONFORMITYANALYSIS_H
|
|
|
|
|
|
|
|
|
|
|
|
#include <QWidget>
|
|
|
|
|
|
#include <iostream>
|
|
|
|
|
|
#include "ParticleDataStatistics.h"
|
|
|
|
|
|
#include "ThreeDDisplay.h"
|
|
|
|
|
|
#include "csv.h"
|
|
|
|
|
|
#include "MeasureAnalysisView.h"
|
2026-03-27 10:24:41 +08:00
|
|
|
|
#include <QVector>
|
2026-05-20 17:53:49 +08:00
|
|
|
|
#include <QDateTime>
|
|
|
|
|
|
#include <QJsonObject>
|
|
|
|
|
|
#include <QJsonArray>
|
|
|
|
|
|
#include <QtConcurrent>
|
|
|
|
|
|
#include <QFutureWatcher>
|
|
|
|
|
|
#include <QMutex>
|
|
|
|
|
|
#include <QMetaType>
|
|
|
|
|
|
#include <QTextStream>
|
|
|
|
|
|
#include <QDataStream>
|
|
|
|
|
|
|
|
|
|
|
|
// Ui类前向声明
|
2026-03-26 17:35:58 +08:00
|
|
|
|
namespace Ui {
|
|
|
|
|
|
class ConformityAnalysis;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-03-27 10:24:41 +08:00
|
|
|
|
typedef struct particleCoincidenceEvent
|
|
|
|
|
|
{
|
|
|
|
|
|
int eventId;//事件ID
|
|
|
|
|
|
int board;//板卡号
|
|
|
|
|
|
int channel;//通道号
|
|
|
|
|
|
double energy;//能量
|
|
|
|
|
|
qulonglong timeCounter;//时间计数
|
|
|
|
|
|
}PARTICLECOINCIDENCEEVENT;
|
|
|
|
|
|
|
2026-05-20 17:53:49 +08:00
|
|
|
|
// 预计算结果结构体(仅保存计算后的数据)
|
|
|
|
|
|
struct ConformityCalculatedResult {
|
|
|
|
|
|
int conformCount; // 符合粒子数
|
|
|
|
|
|
QString dataFileName; // 原始CSV文件名
|
|
|
|
|
|
int totalEvents; // 符合事件总计数
|
|
|
|
|
|
double primaryEnergyStart; // 初级粒子能量范围-起始
|
|
|
|
|
|
double primaryEnergyEnd; // 初级粒子能量范围-结束
|
|
|
|
|
|
double secondaryEnergyStart; // 次级粒子能量范围-起始
|
|
|
|
|
|
double secondaryEnergyEnd; // 次级粒子能量范围-结束
|
|
|
|
|
|
|
|
|
|
|
|
// 板卡通道计数数据(8板×4通道)
|
|
|
|
|
|
int boardChannelData[MAX_BOARD][MAX_CHANNEL];
|
|
|
|
|
|
// 初级粒子计数数据
|
|
|
|
|
|
QMap<QString, int> firstParticleData;
|
|
|
|
|
|
// 三维曲面数据
|
|
|
|
|
|
QVector<SurfacePoint> surfaceData;
|
|
|
|
|
|
|
|
|
|
|
|
// 构造函数
|
|
|
|
|
|
ConformityCalculatedResult() {
|
|
|
|
|
|
memset(boardChannelData, 0, sizeof(boardChannelData));
|
|
|
|
|
|
totalEvents = 0;
|
|
|
|
|
|
primaryEnergyStart = primaryEnergyEnd = 0.0;
|
|
|
|
|
|
secondaryEnergyStart = secondaryEnergyEnd = 0.0;
|
|
|
|
|
|
}
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
Q_DECLARE_METATYPE(ConformityCalculatedResult)
|
|
|
|
|
|
|
|
|
|
|
|
// 一致性分析历史数据结构体
|
|
|
|
|
|
struct ConformityHistoryItem {
|
|
|
|
|
|
QDateTime timestamp; // 保存时间戳
|
|
|
|
|
|
QString dataFileName; // 原始CSV文件名
|
|
|
|
|
|
int conformCount; // 符合粒子数(2/3/4...9)
|
|
|
|
|
|
int totalEvents; // 符合事件总计数
|
|
|
|
|
|
double primaryEnergyStart; // 初级粒子能量范围-起始
|
|
|
|
|
|
double primaryEnergyEnd; // 初级粒子能量范围-结束
|
|
|
|
|
|
double secondaryEnergyStart; // 次级粒子能量范围-起始
|
|
|
|
|
|
double secondaryEnergyEnd; // 次级粒子能量范围-结束
|
|
|
|
|
|
|
|
|
|
|
|
// 板卡通道计数数据(8板×4通道)
|
|
|
|
|
|
int boardChannelData[MAX_BOARD][MAX_CHANNEL];
|
|
|
|
|
|
// 初级粒子计数数据
|
|
|
|
|
|
QMap<QString, int> firstParticleData;
|
|
|
|
|
|
// 三维曲面数据
|
|
|
|
|
|
QVector<SurfacePoint> surfaceData;
|
|
|
|
|
|
|
|
|
|
|
|
// JSON序列化/反序列化方法
|
|
|
|
|
|
QJsonObject toJson() const;
|
|
|
|
|
|
static ConformityHistoryItem fromJson(const QJsonObject& obj);
|
|
|
|
|
|
// 转换为预计算结果
|
|
|
|
|
|
ConformityCalculatedResult toCalculatedResult() const;
|
|
|
|
|
|
// 从预计算结果创建历史记录
|
|
|
|
|
|
static ConformityHistoryItem fromCalculatedResult(const ConformityCalculatedResult& result);
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
Q_DECLARE_METATYPE(ConformityHistoryItem)
|
2026-05-09 16:50:34 +08:00
|
|
|
|
|
2026-03-26 17:35:58 +08:00
|
|
|
|
class ConformityAnalysis : public MeasureAnalysisView
|
|
|
|
|
|
{
|
|
|
|
|
|
Q_OBJECT
|
|
|
|
|
|
private:
|
|
|
|
|
|
QMap<QString, int> m_FirstParticle;
|
|
|
|
|
|
QMap<QString, int> m_subordinate;
|
2026-03-27 10:24:41 +08:00
|
|
|
|
QVector<particleCoincidenceEvent*> m_beginVector;
|
|
|
|
|
|
QVector<particleCoincidenceEvent*> m_secondVector;
|
2026-03-26 17:35:58 +08:00
|
|
|
|
QVector<SurfacePoint> m_surfaceData;
|
|
|
|
|
|
public:
|
|
|
|
|
|
explicit ConformityAnalysis(QWidget *parent = nullptr);
|
|
|
|
|
|
~ConformityAnalysis();
|
|
|
|
|
|
virtual void InitViewWorkspace(const QString& project_name) override final;
|
|
|
|
|
|
virtual void SetAnalyzeDataFilename(const QMap<QString, QVariant>& data_files_set);
|
|
|
|
|
|
//设置csv文件路径及文件名称
|
|
|
|
|
|
void setCsvFile(QString fileName);
|
2026-05-20 17:53:49 +08:00
|
|
|
|
//读取csv文件(兼容旧代码)
|
2026-03-26 17:35:58 +08:00
|
|
|
|
void readCsv();
|
|
|
|
|
|
|
|
|
|
|
|
private slots:
|
|
|
|
|
|
void slot_InitialState();
|
|
|
|
|
|
void slot_ClickedBoard(int board,int channel);
|
2026-05-20 17:53:49 +08:00
|
|
|
|
// 符合数切换槽函数
|
|
|
|
|
|
void slot_ConformCountChanged(int index);
|
|
|
|
|
|
// 单个符合数解析完成槽函数
|
|
|
|
|
|
void onSingleParseFinished(int conformCount);
|
|
|
|
|
|
// 所有符合数解析完成槽函数
|
|
|
|
|
|
void onAllParseFinished();
|
|
|
|
|
|
// 保存单个预计算结果到历史记录(主线程执行)
|
|
|
|
|
|
void saveResultToHistory(const ConformityCalculatedResult& result);
|
|
|
|
|
|
|
2026-03-26 17:35:58 +08:00
|
|
|
|
private:
|
|
|
|
|
|
//处理板卡信息
|
2026-05-20 17:53:49 +08:00
|
|
|
|
void handleBoard(const QVector<particleCoincidenceEvent*>& data, int boardChannelData[MAX_BOARD][MAX_CHANNEL]);
|
2026-03-26 17:35:58 +08:00
|
|
|
|
//统计每个板卡的初级粒子计数
|
2026-05-20 17:53:49 +08:00
|
|
|
|
QMap<QString, int> statisticsFirstParticleQuantity(const QVector<particleCoincidenceEvent*>& data);
|
2026-03-26 17:35:58 +08:00
|
|
|
|
//处理当前板卡初级粒子信息
|
2026-05-20 17:53:49 +08:00
|
|
|
|
QVector<particleCoincidenceEvent*> handleBasicSubordinate(int Board, int Channel, const QVector<particleCoincidenceEvent*>& data);
|
2026-03-26 17:35:58 +08:00
|
|
|
|
//处理次级粒子信息
|
2026-05-20 17:53:49 +08:00
|
|
|
|
QMap<QString,int> handleSubordinate(QVector<particleCoincidenceEvent*> &eventData,int Board, int Channel);
|
2026-03-26 17:35:58 +08:00
|
|
|
|
// 获取最大值
|
|
|
|
|
|
int getMaxValue();
|
|
|
|
|
|
//计算全部的初级粒子范围 和 次级粒子范围
|
2026-05-20 17:53:49 +08:00
|
|
|
|
void calculateFirstSecondRange(const QVector<particleCoincidenceEvent*>& data,
|
|
|
|
|
|
double& firstStart, double& firstEnd,
|
|
|
|
|
|
double& secondStart, double& secondEnd);
|
2026-03-26 17:35:58 +08:00
|
|
|
|
//设置板卡数据信息
|
|
|
|
|
|
void setAllBoardData();
|
|
|
|
|
|
//设置符合事件相关信息
|
|
|
|
|
|
void setThreeUiData();
|
|
|
|
|
|
//全部谱图数据处理
|
2026-05-20 17:53:49 +08:00
|
|
|
|
QVector<SurfacePoint> generateSurfaceData(const QVector<particleCoincidenceEvent*> events);
|
|
|
|
|
|
|
|
|
|
|
|
// 数据保存/加载核心方法(按符合数分文件)
|
|
|
|
|
|
void loadHistoryFromFile();
|
|
|
|
|
|
void saveHistoryToFile();
|
|
|
|
|
|
// 流式写入JSON(零大小限制)
|
|
|
|
|
|
void saveJsonStream(int conformCount, const ConformityHistoryItem& item);
|
|
|
|
|
|
// 二进制保存超大曲面数据
|
|
|
|
|
|
void saveSurfaceDataToBinary(int conformCount, const QVector<SurfacePoint>& data);
|
|
|
|
|
|
// 仅保存指定符合数的历史记录到对应文件
|
|
|
|
|
|
void saveSingleHistoryToFile(int conformCount, const ConformityHistoryItem& item);
|
|
|
|
|
|
int saveCurrentAnalysisToHistory(int conformCount);
|
|
|
|
|
|
// 根据符合数和文件名查找历史记录
|
|
|
|
|
|
int findHistoryIndex(const QString& fileName, int conformCount) const;
|
|
|
|
|
|
|
|
|
|
|
|
// 后台解析所有符合数数据(单线程串行,内存稳定)
|
|
|
|
|
|
void parseAllConformDataInBackground();
|
|
|
|
|
|
// 流式解析并计算单个符合数,内存占用<10MB
|
|
|
|
|
|
ConformityCalculatedResult streamParseAndCalculate(int conformCount, const QString& fileName);
|
|
|
|
|
|
// 显示指定符合数的数据(优先从历史/预计算缓存加载)
|
|
|
|
|
|
void displayConformData(int conformCount);
|
|
|
|
|
|
// 释放所有缓存数据
|
|
|
|
|
|
void clearAllCachedData();
|
|
|
|
|
|
// 读取csv文件(仅用于点击板卡时按需加载)
|
|
|
|
|
|
QVector<particleCoincidenceEvent*> readCsv(const QString& fileName);
|
|
|
|
|
|
// 释放事件数组内存
|
|
|
|
|
|
void freeEventVector(QVector<particleCoincidenceEvent*>& vec);
|
2026-03-26 17:35:58 +08:00
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
|
Ui::ConformityAnalysis *ui;
|
|
|
|
|
|
QString m_fileName;
|
|
|
|
|
|
int m_boardChannel[MAX_BOARD][MAX_CHANNEL];
|
2026-05-20 17:53:49 +08:00
|
|
|
|
// 当前显示的符合数数据(仅保留当前显示的原始数据)
|
|
|
|
|
|
QVector<particleCoincidenceEvent*> _currentSpectrumData;
|
2026-03-26 17:35:58 +08:00
|
|
|
|
double m_dFirstStart = 0.0;//初级粒子起始能量
|
|
|
|
|
|
double m_dFirstEnd = 0.0;//初级粒子终止能量
|
2026-05-20 17:53:49 +08:00
|
|
|
|
double m_dSecondStart = 0.0;//次级粒子起始能量
|
|
|
|
|
|
double m_dSecondEnd = 0.0;//次级粒子终止能量
|
2026-03-26 17:35:58 +08:00
|
|
|
|
int m_iComply = 0;//符合事件总计数
|
2026-05-20 17:53:49 +08:00
|
|
|
|
int m_currentConformCount = 2; // 当前选中的符合粒子数(默认2重)
|
|
|
|
|
|
|
|
|
|
|
|
// 数据持久化相关成员变量
|
|
|
|
|
|
QString _workspace; // 项目工作空间路径
|
|
|
|
|
|
QList<ConformityHistoryItem> _conformityHistoryList; // 所有历史记录列表
|
|
|
|
|
|
|
|
|
|
|
|
// 预计算结果缓存(仅保存计算后的数据,内存占用极小)
|
|
|
|
|
|
QMap<int, ConformityCalculatedResult> m_calculatedCache;
|
|
|
|
|
|
QMutex m_cacheMutex; // 缓存访问互斥锁
|
|
|
|
|
|
QMutex m_historyMutex; // 历史记录访问互斥锁
|
|
|
|
|
|
QFutureWatcher<void>* m_parseWatcher = nullptr; // 后台解析监视器
|
|
|
|
|
|
QMap<int, QString> m_conformFileMap; // 符合数->文件路径映射
|
|
|
|
|
|
bool m_isParsing = false; // 是否正在解析
|
2026-03-26 17:35:58 +08:00
|
|
|
|
};
|
|
|
|
|
|
|
2026-05-20 17:53:49 +08:00
|
|
|
|
#endif // CONFORMITYANALYSIS_H
|