1、添加反符合谱数据查看和修改反符合视图问题;

2、修改已知BUG;
This commit is contained in:
徐海 2026-05-19 14:34:22 +08:00
parent 51d9050e9a
commit e7f7e31d85
5 changed files with 119 additions and 44 deletions

View File

@ -13,6 +13,7 @@ enum class AnalysisType {
EnergyCountData, // 能量计数数据 EnergyCountData, // 能量计数数据
ChannelEnergyCountData, // 通道能量计数数据 ChannelEnergyCountData, // 通道能量计数数据
CoincidenceParticleEnergyData, // 符合粒子能量数据 CoincidenceParticleEnergyData, // 符合粒子能量数据
AntiCoincidenceParticleEnergyData, // 反符合粒子能量数据
AddressCountSpectrumView, // 粒子计数谱视图 AddressCountSpectrumView, // 粒子计数谱视图
EnergyCountSpectrumView, // 能量计数谱视图 EnergyCountSpectrumView, // 能量计数谱视图
CoincidenceParticleEnergySpectrum2DView, // 符合粒子能量2D视图 CoincidenceParticleEnergySpectrum2DView, // 符合粒子能量2D视图

View File

@ -16,13 +16,6 @@
#include <map> #include <map>
#include <vector> #include <vector>
struct SpectrumData {
int board_id;
int channel_id;
double energy;
uint64_t timestamp;
};
AntiConformEnergySpectrumView::AntiConformEnergySpectrumView(QWidget* parent) AntiConformEnergySpectrumView::AntiConformEnergySpectrumView(QWidget* parent)
: MeasureAnalysisView(parent) : MeasureAnalysisView(parent)
{ {
@ -92,57 +85,37 @@ void AntiConformEnergySpectrumView::loadAndProcess()
return; return;
} }
std::vector<SpectrumData> rawData; io::CSVReader<5> in(QStrToSysPath(_data_filename));
io::CSVReader<4> in(QStrToSysPath(_data_filename));
in.read_header(io::ignore_extra_column, in.read_header(io::ignore_extra_column,
QString(QStringLiteral(u"时间窗口")).toStdString(),
QString(QStringLiteral(u"板卡号")).toStdString(), QString(QStringLiteral(u"板卡号")).toStdString(),
QString(QStringLiteral(u"通道号")).toStdString(), QString(QStringLiteral(u"通道号")).toStdString(),
QString(QStringLiteral(u"能量(KeV)")).toStdString(), QString(QStringLiteral(u"能量(KeV)")).toStdString(),
QString(QStringLiteral(u"时间计数")).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()) {
QMetaObject::invokeMethod(this, [this]() {
_busy_indicator->Stop();
}, Qt::QueuedConnection);
return;
}
const int STEP = 1; const int STEP = 1;
std::map<int, double> hist; std::map<int, double> hist;
for (const auto& spdt : rawData) { int time_win, board, channel;
int idx = static_cast<int>(spdt.energy) / STEP; 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; hist[idx] += 1.0;
} }
QVector<double> vx, vy; QVector<double> vx, vy;
for (const auto& pair : hist) { for (const auto& pair : hist) {
vx.push_back(pair.first * STEP); vx.push_back(pair.first * STEP);
vy.push_back(pair.second); vy.push_back(pair.second);
} }
if (vx.isEmpty()) { if (vx.isEmpty()) {
QMetaObject::invokeMethod(this, [this]() { QMetaObject::invokeMethod(this, [this]() {
_busy_indicator->Stop(); _busy_indicator->Stop();
}, Qt::QueuedConnection); }, Qt::QueuedConnection);
return; return;
} }
double dmaxx = *std::max_element(vx.begin(), vx.end()); double dmaxx = *std::max_element(vx.begin(), vx.end());
double dmaxy = *std::max_element(vy.begin(), vy.end()); double dmaxy = *std::max_element(vy.begin(), vy.end());
QMetaObject::invokeMethod(this, [this, vx, vy, dmaxx, dmaxy]() { QMetaObject::invokeMethod(this, [this, vx, vy, dmaxx, dmaxy]() {
_curve->setSamples(vx, vy); _curve->setSamples(vx, vy);
_plot->SetAxisInitRange(QwtPlot::xBottom, 0.0f, dmaxx); _plot->SetAxisInitRange(QwtPlot::xBottom, 0.0f, dmaxx);

View File

@ -861,6 +861,15 @@ void MeasureAnalysisProjectModelList::onChannelAddressCountProcessFinished(bool
this->SetNodeStatus(adrr_count_spec_item, status, status_ok); this->SetNodeStatus(adrr_count_spec_item, status, status_ok);
} }
pro_model->SaveProjectModel(); pro_model->SaveProjectModel();
if ( !pro_model->GetEnergyScaleFilename().isEmpty() ) {
auto apply_erergy_scale_fit_task = new DataProcessWorkPool::EnergyScaleParticleDataTask;
apply_erergy_scale_fit_task->SetFinishedNotifier(this, "onEnergyScaleParticleDataFinished", project_name);
apply_erergy_scale_fit_task->StartTask();
auto energy_count_process_task = new DataProcessWorkPool::EnergyCountProcessTask;
energy_count_process_task->SetFinishedNotifier(this, "onEnergyCountProcessFinished", project_name);
energy_count_process_task->StartTask();
}
} }
} }
@ -962,7 +971,24 @@ void MeasureAnalysisProjectModelList::onCoincidenceProcessFinished(bool ok, cons
return; return;
if (this->_project_models.contains(project_name)) { if (this->_project_models.contains(project_name)) {
auto pro_model = this->_project_models[project_name]; auto pro_model = this->_project_models[project_name];
// auto& node_map = this->_project_node_items[project_name];
// const QString& item_name = QStringLiteral(u"符合事件时间分析[%1ns]").arg(conform_time_win);;
// if (node_map.contains(item_name)) {
// auto item = node_map[item_name];
// this->SetNodeStatus(item, status, status_ok);
// }
pro_model->SaveProjectModel(); pro_model->SaveProjectModel();
if ( !pro_model->GetEnergyScaleFilename().isEmpty() ) {
auto coincidence_process_task = new DataProcessWorkPool::EnergyScaleCoincidenceDataTask;
coincidence_process_task->SetFinishedNotifier(this, "onEnergyScaleCoincidenceDataFinished", project_name);
coincidence_process_task->StartTask();
auto anti_coincidence_process_task = new DataProcessWorkPool::EnergyScaleaAntiCoincidenceDataTask;
anti_coincidence_process_task->SetFinishedNotifier(this, "onEnergyScaleAntiCoincidenceDataFinished", project_name);
anti_coincidence_process_task->StartTask();
}
} }
} }
@ -1007,18 +1033,28 @@ void MeasureAnalysisProjectModelList::onEnergyScaleCoincidenceDataFinished(bool
if (!conform_energy_data_filename_list.isEmpty()) { if (!conform_energy_data_filename_list.isEmpty()) {
item_name = QStringLiteral(u"符合能谱[%1ns]").arg(conform_time_win); item_name = QStringLiteral(u"符合能谱[%1ns]").arg(conform_time_win);
if (node_map.contains(item_name)) { if (node_map.contains(item_name)) {
auto energy_total_count_spec_item = node_map[item_name]; auto item = node_map[item_name];
this->SetNodeStatus(energy_total_count_spec_item, status, status_ok); this->SetNodeStatus(item, status, status_ok);
}
item_name = QStringLiteral(u"符合事件时间分析[%1ns]").arg(conform_time_win);;
if (node_map.contains(item_name)) {
auto item = node_map[item_name];
this->SetNodeStatus(item, status, status_ok);
}
item_name = QStringLiteral(u"符合事件时间分析[%1ns]").arg(conform_time_win);;
if (node_map.contains(item_name)) {
auto item = node_map[item_name];
this->SetNodeStatus(item, status, status_ok);
} }
item_name = QStringLiteral(u"二维符合能谱[%1ns]").arg(conform_time_win); item_name = QStringLiteral(u"二维符合能谱[%1ns]").arg(conform_time_win);
if (node_map.contains(item_name)) { if (node_map.contains(item_name)) {
auto energy_total_count_spec_item = node_map[item_name]; auto item = node_map[item_name];
this->SetNodeStatus(energy_total_count_spec_item, status, status_ok); this->SetNodeStatus(item, status, status_ok);
} }
item_name = QStringLiteral(u"三维符合能谱[%1ns]").arg(conform_time_win); item_name = QStringLiteral(u"三维符合能谱[%1ns]").arg(conform_time_win);
if (node_map.contains(item_name)) { if (node_map.contains(item_name)) {
auto energy_total_count_spec_item = node_map[item_name]; auto item = node_map[item_name];
this->SetNodeStatus(energy_total_count_spec_item, status, status_ok); this->SetNodeStatus(item, status, status_ok);
} }
} }
} }
@ -1037,14 +1073,41 @@ void MeasureAnalysisProjectModelList::onEnergyScaleAntiCoincidenceDataFinished(b
auto pro_model = this->_project_models[project_name]; auto pro_model = this->_project_models[project_name];
auto& node_map = this->_project_node_items[project_name]; auto& node_map = this->_project_node_items[project_name];
const auto& anti_conform_energy_data = pro_model->GetAntiConformEnergyData(); const auto& anti_conform_energy_data = pro_model->GetAntiConformEnergyData();
bool status_ok = false;
QString status = QStringLiteral(u"无效");
if ( anti_conform_energy_data.size() ) {
status_ok = true;
status = QStringLiteral(u"有效");
}
QString item_name = QStringLiteral(u"反符合粒子能量数据");
QStandardItem* anti_conform_energy_data_group_item = nullptr;
if (node_map.contains(item_name)) {
anti_conform_energy_data_group_item = node_map[item_name];
this->SetNodeStatus(anti_conform_energy_data_group_item, status, status_ok);
}
for (const auto& time_win : anti_conform_energy_data.keys()) { for (const auto& time_win : anti_conform_energy_data.keys()) {
bool status_ok = false; status_ok = false;
QString status = QStringLiteral(u"无效"); status = QStringLiteral(u"无效");
const QString& data_filename = anti_conform_energy_data.value(time_win); const QString& data_filename = anti_conform_energy_data.value(time_win);
if ( (!data_filename.isEmpty()) && QFile::exists(data_filename) ) { if ( (!data_filename.isEmpty()) && QFile::exists(data_filename) ) {
status_ok = true; status_ok = true;
status = QStringLiteral(u"有效"); status = QStringLiteral(u"有效");
} }
if (anti_conform_energy_data_group_item) {
QString item_name = QStringLiteral(u"反符合能谱数据[%1ns]").arg(time_win);
if (node_map.contains(item_name)) {
auto anti_conform_erergy_spec_item = node_map[item_name];
this->SetNodeStatus(anti_conform_erergy_spec_item, status, status_ok);
} else {
const QVariant& analys_type = QVariant::fromValue(AnalysisType::AntiCoincidenceParticleEnergyData);
QStandardItem* node_item = AddChildNode(anti_conform_energy_data_group_item, item_name, status, analys_type, true, status_ok);
node_item->setData(project_name, ProjectName);
QVariant conform_info(time_win);
node_item->setData(conform_info, ConformInfo);
node_map[item_name] = node_item;
}
}
QString item_name = QStringLiteral(u"反符合能谱[%1ns]").arg(time_win); QString item_name = QStringLiteral(u"反符合能谱[%1ns]").arg(time_win);
if (node_map.contains(item_name)) { if (node_map.contains(item_name)) {
auto anti_conform_erergy_spec_item = node_map[item_name]; auto anti_conform_erergy_spec_item = node_map[item_name];
@ -1181,7 +1244,7 @@ void MeasureAnalysisProjectModelList::intiProjectNodeStruce(MeasureAnalysisProje
int order = it.key(); int order = it.key();
status_ok = !it.value().isEmpty(); status_ok = !it.value().isEmpty();
status = status_ok ? QStringLiteral(u"有效") : QStringLiteral(u"无效"); status = status_ok ? QStringLiteral(u"有效") : QStringLiteral(u"无效");
QString item_name = QStringLiteral(u"%1个粒子符合[%2ns]").arg(order).arg(conform_time_win); QString item_name = QStringLiteral(u"%1个粒子符合能谱[%2ns]").arg(order).arg(conform_time_win);
const QVariant& analys_type = QVariant::fromValue(AnalysisType::CoincidenceParticleEnergyData); const QVariant& analys_type = QVariant::fromValue(AnalysisType::CoincidenceParticleEnergyData);
QStandardItem* node_item = AddChildNode(conform_energy_data_group_item, item_name, status, analys_type, true, status_ok); QStandardItem* node_item = AddChildNode(conform_energy_data_group_item, item_name, status, analys_type, true, status_ok);
node_item->setData(project_name, ProjectName); node_item->setData(project_name, ProjectName);
@ -1191,6 +1254,28 @@ void MeasureAnalysisProjectModelList::intiProjectNodeStruce(MeasureAnalysisProje
} }
} }
status_ok = !pro_model->GetAntiConformEnergyData(conform_time_win).isEmpty();
status = status_ok ? QStringLiteral(u"有效") : QStringLiteral(u"无效");
item_name = QStringLiteral(u"反符合粒子能量数据");
analys_type = QVariant::fromValue(AnalysisType::None);
QStandardItem* anti_conform_energy_data_group_item = AddChildNode(analysis_data_item, item_name, status, analys_type, true, status_ok);
anti_conform_energy_data_group_item->setData(project_name, ProjectName);
node_map[item_name] = anti_conform_energy_data_group_item;
auto time_win_anit_confirm_file_name_set = pro_model->GetAntiConformEnergyData();
for (int conform_time_win : time_win_anit_confirm_file_name_set.keys()) {
const auto& anti_conform_energy_data_filename = pro_model->GetAntiConformEnergyData(conform_time_win);
status_ok = !anti_conform_energy_data_filename.isEmpty();
status = status_ok ? QStringLiteral(u"有效") : QStringLiteral(u"无效");
QString item_name = QStringLiteral(u"反符合能谱数据[%1ns]").arg(conform_time_win);
const QVariant& analys_type = QVariant::fromValue(AnalysisType::AntiCoincidenceParticleEnergyData);
QStandardItem* node_item = AddChildNode(anti_conform_energy_data_group_item, item_name, status, analys_type, true, status_ok);
node_item->setData(project_name, ProjectName);
QVariant conform_info(conform_time_win);
node_item->setData(conform_info, ConformInfo);
node_map[item_name] = node_item;
}
// 交互分析 // 交互分析
item_name = QStringLiteral(u"交互分析"); item_name = QStringLiteral(u"交互分析");
QStandardItem* interactive_analysis_item = AddChildNode(project_item, item_name, QString(), QVariant(), true, true); QStandardItem* interactive_analysis_item = AddChildNode(project_item, item_name, QString(), QVariant(), true, true);
@ -1257,7 +1342,7 @@ void MeasureAnalysisProjectModelList::intiProjectNodeStruce(MeasureAnalysisProje
status_ok = !pro_model->GetTimeWinConformEnergyDataFilenameList(conform_time_win).isEmpty(); status_ok = !pro_model->GetTimeWinConformEnergyDataFilenameList(conform_time_win).isEmpty();
status = status_ok ? QStringLiteral(u"有效") : QStringLiteral(u"无效"); status = status_ok ? QStringLiteral(u"有效") : QStringLiteral(u"无效");
analys_type = QVariant::fromValue(AnalysisType::CoincidenceEventTimeView); analys_type = QVariant::fromValue(AnalysisType::CoincidenceEventTimeView);
item_name = QStringLiteral(u"符合事件时间分析"); item_name = QStringLiteral(u"符合事件时间分析[%1ns]").arg(conform_time_win);
node_item = AddChildNode(interactive_analysis_item, item_name, status, analys_type, true, status_ok); node_item = AddChildNode(interactive_analysis_item, item_name, status, analys_type, true, status_ok);
node_item->setData(project_name, ProjectName); node_item->setData(project_name, ProjectName);
node_map[item_name] = node_item; node_map[item_name] = node_item;

View File

@ -155,6 +155,18 @@ void MeasureAnalysisTreeView::onNodeDoubleClicked(const QModelIndex& index)
} }
} }
} break; } break;
case AnalysisType::AntiCoincidenceParticleEnergyData: {
QVariant conform_info_v = _model->GetNodeUserData(item, ProjectList::ConformInfo);
if (conform_info_v.isValid()) {
int conform_time_win = conform_info_v.toInt();
MeasureAnalysisProjectModel* project_model = _model->GetProjectModel(project_name);
if (project_model) {
auto file_name = project_model->GetAntiConformEnergyData(conform_time_win);
const QString& data_name = QStringLiteral(u"反符合粒子能量数据[%1ns]").arg(conform_time_win);
data_files_set[data_name] = QString(file_name);
}
}
} break;
case AnalysisType::CoincidenceParticleEnergyData: { case AnalysisType::CoincidenceParticleEnergyData: {
QVariant conform_info_v = _model->GetNodeUserData(item, ProjectList::ConformInfo); QVariant conform_info_v = _model->GetNodeUserData(item, ProjectList::ConformInfo);
if (conform_info_v.isValid()) { if (conform_info_v.isValid()) {

View File

@ -59,6 +59,10 @@ MeasureAnalysisView* MeasureAnalysisView::NewAnalyzeView(AnalysisType view_type)
new_view = new MeasureAnalysisDataTableView; new_view = new MeasureAnalysisDataTableView;
new_view->setDeleteOnClose(true); new_view->setDeleteOnClose(true);
} break; } break;
case AnalysisType::AntiCoincidenceParticleEnergyData: {
new_view = new MeasureAnalysisDataTableView;
new_view->setDeleteOnClose(true);
} break;
case AnalysisType::AddressCountSpectrumView: { case AnalysisType::AddressCountSpectrumView: {
new_view = new ParticleCountPlotView; new_view = new ParticleCountPlotView;
new_view->setDeleteOnClose(false); new_view->setDeleteOnClose(false);