二维符合谱修改

This commit is contained in:
anxinglong 2026-05-21 13:59:26 +08:00
parent 7b35e9b823
commit f56b544fa9
2 changed files with 16 additions and 75 deletions

View File

@ -17,6 +17,7 @@
#include <QwtInterval>
#include <QwtLegend>
#include <QwtLinearColorMap>
#include <QwtRasterData>
#include <QwtMatrixRasterData>
#include <QwtPlotCanvas>
#include <QwtPlotPicker>
@ -34,12 +35,18 @@
class HeatMapColorMap : public QwtLinearColorMap {
public:
HeatMapColorMap()
: QwtLinearColorMap(Qt::blue, Qt::red)
: QwtLinearColorMap(QColor(53, 42, 134), QColor(229, 58, 16))
{
addColorStop(0.25, Qt::cyan);
addColorStop(0.5, Qt::green);
addColorStop(0.75, Qt::yellow);
addColorStop(0.90, Qt::darkRed);
addColorStop(0.091, QColor(14, 92, 207)); // 蓝色
addColorStop(0.182, QColor(15, 132, 212)); // 青色
addColorStop(0.273, QColor(20, 169, 204)); // 蓝绿色
addColorStop(0.364, QColor(42, 200, 169)); // 绿色
addColorStop(0.455, QColor(85, 220, 112)); // 黄绿色
addColorStop(0.545, QColor(132, 228, 58)); // 黄色
addColorStop(0.636, QColor(180, 222, 17)); // 橙黄色
addColorStop(0.727, QColor(222, 202, 6)); // 橙色
addColorStop(0.818, QColor(250, 168, 2)); // 橙红色
addColorStop(0.909, QColor(248, 114, 7)); // 红色
}
};
@ -266,8 +273,8 @@ void TwoDSpectralCompliance::updateSpectrogram()
double secStart = minSec - secRange * 0.05;
double secEnd = maxSec + secRange * 0.05;
const int numCols = 200;
const int numRows = 200;
const int numCols = 4800;
const int numRows = 4800;
double stepX = (primEnd - primStart) / numCols;
double stepY = (secEnd - secStart) / numRows;

View File

@ -157,22 +157,16 @@ void ConformityAnalysis::InitViewWorkspace(const QString &project_name)
return;
QString projectRootDir = project_model->GetProjectDir();
qDebug() << "[ConformityAnalysis] 项目根目录:" << projectRootDir;
_workspace = QDir(projectRootDir).filePath(this->GetViewName());
qDebug() << "[ConformityAnalysis] 工作空间目录:" << _workspace;
QDir dir;
if (!dir.mkpath(_workspace)) {
qCritical() << "[ConformityAnalysis] 无法创建工作空间目录:" << _workspace;
} else {
qDebug() << "[ConformityAnalysis] 工作空间目录创建成功";
}
_conformityHistoryList.clear();
loadHistoryFromFile();
qDebug() << "[ConformityAnalysis] 工作空间初始化完成,已加载" << _conformityHistoryList.size() << "条历史记录";
}
void ConformityAnalysis::SetAnalyzeDataFilename(const QMap<QString, QVariant> &data_files_set)
@ -183,13 +177,11 @@ void ConformityAnalysis::SetAnalyzeDataFilename(const QMap<QString, QVariant> &d
freeEventVector(_currentSpectrumData);
m_conformFileMap.clear();
qDebug() << "[ConformityAnalysis] 开始导入数据,共" << data_files_set.size() << "个文件";
for (const QString& key : data_files_set.keys()) {
bool ok;
int cnt = key.toInt(&ok);
if (ok && cnt >=2 && cnt <=9) {
m_conformFileMap[cnt] = data_files_set[key].toString();
qDebug() << "[ConformityAnalysis] 已添加" << cnt << "重符合文件:" << data_files_set[key].toString();
}
}
@ -199,26 +191,19 @@ void ConformityAnalysis::SetAnalyzeDataFilename(const QMap<QString, QVariant> &d
}
if (m_conformFileMap.contains(2)) {
qDebug() << "[ConformityAnalysis] ========================================";
qDebug() << "[ConformityAnalysis] 开始解析2重符合数据优先显示";
ConformityCalculatedResult result = streamParseAndCalculate(2, m_conformFileMap[2]);
QMutexLocker cacheLocker(&m_cacheMutex);
m_calculatedCache[2] = result;
cacheLocker.unlock();
qDebug() << "[ConformityAnalysis] 正在将2重符合数据显示到界面";
displayConformData(2);
qDebug() << "[ConformityAnalysis] ✅ 2重符合数据已成功显示到界面";
qDebug() << "[ConformityAnalysis] 开始后台保存2重符合数据到文件";
QMetaObject::invokeMethod(this, [=]() {
saveResultToHistory(result);
}, Qt::QueuedConnection);
} else {
qCritical() << "[ConformityAnalysis] 未找到2重符合文件";
}
m_isParsing = true;
parseAllConformDataInBackground();
}
@ -226,11 +211,9 @@ void ConformityAnalysis::SetAnalyzeDataFilename(const QMap<QString, QVariant> &d
void ConformityAnalysis::parseAllConformDataInBackground()
{
QList<int> conformCounts = m_conformFileMap.keys();
// 移除已处理的2重符合
conformCounts.removeOne(2);
std::sort(conformCounts.begin(), conformCounts.end());
qDebug() << "[ConformityAnalysis] 开始后台处理剩余符合数:" << conformCounts;
auto parseTask = [this, conformCounts]() {
for (int conformCount : conformCounts) {
@ -238,8 +221,7 @@ void ConformityAnalysis::parseAllConformDataInBackground()
break;
QString fileName = m_conformFileMap[conformCount];
qDebug() << "[ConformityAnalysis] ========================================";
qDebug() << "[ConformityAnalysis] 开始解析" << conformCount << "重符合数据:" << fileName;
ConformityCalculatedResult result = streamParseAndCalculate(conformCount, fileName);
@ -247,14 +229,11 @@ void ConformityAnalysis::parseAllConformDataInBackground()
m_calculatedCache[conformCount] = result;
cacheLocker.unlock();
// 如果当前显示的是这个符合数,先显示
if (conformCount == m_currentConformCount) {
qDebug() << "[ConformityAnalysis] 当前显示" << conformCount << "重符合,立即更新界面";
QMetaObject::invokeMethod(this, "displayConformData", Qt::QueuedConnection,
Q_ARG(int, conformCount));
}
// 后台异步保存
QMetaObject::invokeMethod(this, [=]() {
saveResultToHistory(result);
}, Qt::QueuedConnection);
@ -316,12 +295,9 @@ ConformityCalculatedResult ConformityAnalysis::streamParseAndCalculate(int confo
while (reader.read_row(event.eventId, event.board, event.channel, event.energy, event.timeCounter)) {
eventCount++;
// 1. 更新板卡通道计数
result.boardChannelData[event.board][event.channel]++;
// 2. 处理事件分组和能量统计
if (event.eventId != currentEventId) {
// 保存上一个事件的曲面数据
if (currentEventId != -1) {
SurfacePoint point;
point.primaryEnergy = primaryEnergy;
@ -330,12 +306,10 @@ ConformityCalculatedResult ConformityAnalysis::streamParseAndCalculate(int confo
result.surfaceData.append(point);
}
// 新事件开始(初级粒子)
currentEventId = event.eventId;
primaryEnergy = static_cast<float>(event.energy);
secondaryEnergySum = 0.0f;
// 更新初级粒子计数
int boardId = event.board + 1;
int channelId = event.channel + 1;
if (boardId >= 1 && boardId <= 8 && channelId >= 1 && channelId <= 4) {
@ -343,20 +317,16 @@ ConformityCalculatedResult ConformityAnalysis::streamParseAndCalculate(int confo
result.firstParticleData[key]++;
}
// 更新初级粒子能量范围
if (event.energy < minFirstVal) minFirstVal = event.energy;
if (event.energy > maxFirstVal) maxFirstVal = event.energy;
} else {
// 次级粒子
secondaryEnergySum += static_cast<float>(event.energy);
// 更新次级粒子能量范围
if (event.energy < minSecondVal) minSecondVal = event.energy;
if (event.energy > maxSecondVal) maxSecondVal = event.energy;
}
}
// 保存最后一个事件的曲面数据
if (currentEventId != -1) {
SurfacePoint point;
point.primaryEnergy = primaryEnergy;
@ -365,7 +335,6 @@ ConformityCalculatedResult ConformityAnalysis::streamParseAndCalculate(int confo
result.surfaceData.append(point);
}
// 压缩曲面数据内存
result.surfaceData.squeeze();
} catch (const std::exception& e) {
@ -373,27 +342,16 @@ ConformityCalculatedResult ConformityAnalysis::streamParseAndCalculate(int confo
return result;
}
// 计算最终结果
result.totalEvents = eventCount;
result.primaryEnergyStart = (minFirstVal == std::numeric_limits<double>::max()) ? 0.0 : minFirstVal;
result.primaryEnergyEnd = maxFirstVal;
result.secondaryEnergyStart = (minSecondVal == std::numeric_limits<double>::max()) ? 0.0 : minSecondVal;
result.secondaryEnergyEnd = maxSecondVal;
qDebug() << "[ConformityAnalysis] " << conformCount << "重符合流式解析完成";
qDebug() << "[ConformityAnalysis] 总事件数:" << result.totalEvents;
qDebug() << "[ConformityAnalysis] 初级能量范围:" << result.primaryEnergyStart << "-" << result.primaryEnergyEnd;
qDebug() << "[ConformityAnalysis] 次级能量范围:" << result.secondaryEnergyStart << "-" << result.secondaryEnergyEnd;
qDebug() << "[ConformityAnalysis] 曲面数据点数:" << result.surfaceData.size();
qDebug() << "[ConformityAnalysis] 当前内存占用:约" << (result.surfaceData.size() * sizeof(SurfacePoint) + 1024*1024) / 1024 / 1024 << "MB";
return result;
}
// ==================== 保存单个结果到历史记录 ====================
void ConformityAnalysis::saveResultToHistory(const ConformityCalculatedResult& result)
{
qDebug() << "[ConformityAnalysis] 开始保存" << result.conformCount << "重符合数据到历史记录";
QMutexLocker locker(&m_historyMutex);
ConformityHistoryItem item = ConformityHistoryItem::fromCalculatedResult(result);
@ -404,7 +362,6 @@ void ConformityAnalysis::saveResultToHistory(const ConformityCalculatedResult& r
saveSurfaceDataToBinary(result.conformCount, item.surfaceData);
}
// ✅ 核心流式逐行写入JSON完全绕过QJsonDocument大小限制
void ConformityAnalysis::saveJsonStream(int conformCount, const ConformityHistoryItem& item)
{
QDir dir(_workspace);
@ -448,10 +405,8 @@ void ConformityAnalysis::saveJsonStream(int conformCount, const ConformityHistor
return result;
};
// 所有Qt::endl都替换为'\n'
stream << "{" << '\n';
// 基础字段
stream << " \"timestamp\": \"" << escapeJson(item.timestamp.toString(Qt::ISODate)) << "\"," << '\n';
stream << " \"dataFileName\": \"" << escapeJson(item.dataFileName) << "\"," << '\n';
stream << " \"conformCount\": " << item.conformCount << "," << '\n';
@ -461,7 +416,6 @@ void ConformityAnalysis::saveJsonStream(int conformCount, const ConformityHistor
stream << " \"secondaryEnergyStart\": " << item.secondaryEnergyStart << "," << '\n';
stream << " \"secondaryEnergyEnd\": " << item.secondaryEnergyEnd << "," << '\n';
// 板卡通道数据
stream << " \"boardChannelData\": [" << '\n';
for (int board = 0; board < MAX_BOARD; ++board) {
stream << " [";
@ -475,7 +429,6 @@ void ConformityAnalysis::saveJsonStream(int conformCount, const ConformityHistor
}
stream << " ]," << '\n';
// 初级粒子数据
stream << " \"firstParticleData\": {" << '\n';
QList<QString> keys = item.firstParticleData.keys();
for (int i = 0; i < keys.size(); ++i) {
@ -488,10 +441,8 @@ void ConformityAnalysis::saveJsonStream(int conformCount, const ConformityHistor
stream << "}" << '\n';
file.close();
qDebug() << "✅ JSON流式保存成功兼容Qt6" << path;
}
// 二进制保存超大曲面数据(无大小限制)
void ConformityAnalysis::saveSurfaceDataToBinary(int conformCount, const QVector<SurfacePoint>& data)
{
QDir dir(_workspace);
@ -506,10 +457,8 @@ void ConformityAnalysis::saveSurfaceDataToBinary(int conformCount, const QVector
QDataStream stream(&file);
stream << data;
file.close();
qDebug() << "✅ 三维曲面数据二进制保存成功:" << path;
}
// ==================== 加载历史数据 ====================
void ConformityAnalysis::loadHistoryFromFile()
{
_conformityHistoryList.clear();
@ -522,7 +471,6 @@ void ConformityAnalysis::loadHistoryFromFile()
continue;
}
// 加载JSON小数据
QFile f(jsonPath);
if (!f.open(QIODevice::ReadOnly)) {
qWarning() << "[ConformityAnalysis] 无法打开JSON文件" << jsonPath;
@ -533,7 +481,6 @@ void ConformityAnalysis::loadHistoryFromFile()
ConformityHistoryItem item = ConformityHistoryItem::fromJson(doc.object());
// 加载二进制曲面数据
if (QFile::exists(binPath)) {
QFile binFile(binPath);
if (binFile.open(QIODevice::ReadOnly)) {
@ -544,7 +491,6 @@ void ConformityAnalysis::loadHistoryFromFile()
}
_conformityHistoryList.append(item);
qDebug() << "[ConformityAnalysis] 加载" << c << "重符合历史记录完成";
}
}
@ -554,20 +500,14 @@ void ConformityAnalysis::onSingleParseFinished(int conformCount)
qDebug() << "[ConformityAnalysis] " << conformCount << "重符合数据处理完成";
}
// ==================== 所有符合数解析完成 ====================
void ConformityAnalysis::onAllParseFinished()
{
m_isParsing = false;
qDebug() << "[ConformityAnalysis] ========================================";
qDebug() << "[ConformityAnalysis] ✅ 所有符合数数据处理完成并已全部保存";
qDebug() << "[ConformityAnalysis] 所有文件已保存到:" << _workspace;
}
// ==================== 显示指定符合数的数据 ====================
void ConformityAnalysis::displayConformData(int conformCount)
{
if (!m_conformFileMap.contains(conformCount)) {
qWarning() << "[ConformityAnalysis] 无" << conformCount << "重符合数据";
return;
}
@ -596,10 +536,8 @@ void ConformityAnalysis::displayConformData(int conformCount)
setThreeUiData();
ui->widget_3D->setSurfaceData(m_surfaceData);
qDebug() << "[ConformityAnalysis] 显示" << conformCount << "重符合数据完成";
}
// ==================== 符合数切换槽函数 ====================
void ConformityAnalysis::slot_ConformCountChanged(int index)
{
int conformCount = index + 2;
@ -609,7 +547,6 @@ void ConformityAnalysis::slot_ConformCountChanged(int index)
displayConformData(conformCount);
}
// ==================== CSV文件读取仅用于点击板卡时按需加载 ====================
QVector<particleCoincidenceEvent*> ConformityAnalysis::readCsv(const QString& fileName)
{
QVector<particleCoincidenceEvent*> dataList;
@ -661,7 +598,6 @@ void ConformityAnalysis::freeEventVector(QVector<particleCoincidenceEvent*>& vec
vec.squeeze();
}
// ==================== 以下原有方法保持不变 ====================
void ConformityAnalysis::handleBoard(const QVector<particleCoincidenceEvent*>& data, int boardChannelData[MAX_BOARD][MAX_CHANNEL])
{
memset(boardChannelData, 0, sizeof(int) * MAX_BOARD * MAX_CHANNEL);
@ -911,7 +847,6 @@ void ConformityAnalysis::setThreeUiData()
void ConformityAnalysis::saveHistoryToFile()
{
qDebug() << "[ConformityAnalysis] 执行全局保存所有符合数文件";
for (int conformCount = 2; conformCount <= 9; ++conformCount) {
int idx = findHistoryIndex(m_conformFileMap.value(conformCount), conformCount);
if (idx >= 0) {
@ -979,6 +914,5 @@ void ConformityAnalysis::clearAllCachedData()
void ConformityAnalysis::saveSingleHistoryToFile(int conformCount, const ConformityHistoryItem& item)
{
// 兼容旧接口,实际使用流式写入
saveJsonStream(conformCount, item);
}