From 03d321f2f06f7badfb63355b60e0817c289a27d5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BE=90=E6=B5=B7?= Date: Thu, 26 Mar 2026 10:03:30 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BC=98=E5=8C=96=E7=A8=8B=E5=BA=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/DataCalcProcess/CoincidenceSpectrum.cpp | 18 +- .../CoincidenceSpectrumProcess.h | 7 +- src/DataProcessWorkPool.cpp | 254 +++++++++--------- src/DataProcessWorkPool.h | 15 +- src/MainWindow.cpp | 4 + src/MeasureAnalysisHistoryForm.ui | 41 --- src/MeasureAnalysisProjectModel.cpp | 190 ++++++++----- src/MeasureAnalysisProjectModel.h | 7 +- 8 files changed, 263 insertions(+), 273 deletions(-) diff --git a/src/DataCalcProcess/CoincidenceSpectrum.cpp b/src/DataCalcProcess/CoincidenceSpectrum.cpp index b721fc3..b90051c 100644 --- a/src/DataCalcProcess/CoincidenceSpectrum.cpp +++ b/src/DataCalcProcess/CoincidenceSpectrum.cpp @@ -1,4 +1,4 @@ -#include +#include #include #include "CoincidenceSpectrumProcess.h" @@ -175,21 +175,18 @@ void SortDataByTimestamp(std::vector& data) } // 2-9次能谱符合处理 -std::vector ProcessCoincidence( - const std::vector& data, +bool ProcessCoincidence( + std::vector& data, + std::vector& events, unsigned int time_window, int min_order, int max_order ) { - std::vector results; int n = data.size(); if (n < min_order) { - std::cerr << "错误:数据量不足,无法进行" << min_order << "次符合处理" << std::endl; - return results; + return false; } - std::cout << "开始进行" << min_order << "-" << max_order << "次能谱符合处理,时间窗口:" - << time_window << "ns" << std::endl; // 使用滑动窗口寻找符合事件 for (int i = 0; i < n; ++i) { std::vector current_coincidence; @@ -213,11 +210,10 @@ std::vector ProcessCoincidence( result.coincidence_order = coincidence_order; result.events = current_coincidence; result.time_window = time_window; - results.push_back(result); + events.push_back(result); } } - qDebug() << "符合处理完成,共找到 " << results.size() << " 个符合事件" ; - return results; + return true; } // 统计符合事件结果 diff --git a/src/DataCalcProcess/CoincidenceSpectrumProcess.h b/src/DataCalcProcess/CoincidenceSpectrumProcess.h index 0fbbbf1..fafa651 100644 --- a/src/DataCalcProcess/CoincidenceSpectrumProcess.h +++ b/src/DataCalcProcess/CoincidenceSpectrumProcess.h @@ -1,4 +1,4 @@ -#ifndef COINCIDENCESPECTRUMPROCESS_H +#ifndef COINCIDENCESPECTRUMPROCESS_H #define COINCIDENCESPECTRUMPROCESS_H #include @@ -36,8 +36,9 @@ namespace F2t9Order { void SortDataByTimestamp(std::vector& data); // 2-9次能谱符合处理 - std::vector ProcessCoincidence( - const std::vector& data, + bool ProcessCoincidence( + std::vector &data, + std::vector &events, unsigned int time_window, // 时间窗口(纳秒) int min_order = 2, // 最小符合次数 int max_order = 9 // 最大符合次数 diff --git a/src/DataProcessWorkPool.cpp b/src/DataProcessWorkPool.cpp index 13aebd4..f6bd67d 100644 --- a/src/DataProcessWorkPool.cpp +++ b/src/DataProcessWorkPool.cpp @@ -21,6 +21,7 @@ #include "DataCalcProcess/GaussPolyCoe.h" #include "DataCalcProcess/NolinearLeastSquaresCurveFit.h" #include "EnergyScaleDataModel.h" +#include "DataCalcProcess/CoincidenceSpectrumProcess.h" #include using namespace DataProcessWorkPool; @@ -102,97 +103,6 @@ bool ParticleDataTask::processTask() return processEveryChannelParticleData(); } -void EveryChannelParticleDataSeparateTask::SetResultDataDir(const QString& result_data_dir) -{ - this->_result_data_dir = result_data_dir; -} - -const QString& EveryChannelParticleDataSeparateTask::GetResultDataDir() const -{ - return this->_result_data_dir; -} - -bool EveryChannelParticleDataSeparateTask::IsValidSetWorkParameters() const -{ - return (!GetResultDataDir().isEmpty()) && ParticleDataTask::IsValidSetWorkParameters(); -} - -bool EveryChannelParticleDataSeparateTask::processEveryChannelParticleData() -{ - bool ret_ok = true; - const QString& result_data_output_dir_path = GetResultDataDir(); - QDir result_data_output_dir(result_data_output_dir_path); - result_data_output_dir.mkpath(result_data_output_dir_path); - - const QString& all_channel_particle_data_filename = GetAllChannelParticleDataFilename(); - QMap particle_data_filename_list; - - try { - QMap> ch_particle_data_of_list; - - std::string board_id_str = QString(QStringLiteral(u"板卡号")).toStdString(); - std::string channel_id_str = QString(QStringLiteral(u"通道号")).toStdString(); - std::string address_str = QString(QStringLiteral(u"道址")).toStdString(); - std::string time_str = QString(QStringLiteral(u"时间计数")).toStdString(); - - // 使用更灵活的方式处理CSV文件,忽略额外列 - io::CSVReader< - 4, - io::trim_chars<' ', '\t'>, - io::double_quote_escape<',', '"'>, - io::throw_on_overflow, - io::empty_line_comment> - reader(QStrToSysPath(all_channel_particle_data_filename)); - reader.read_header(io::ignore_extra_column, board_id_str, channel_id_str, address_str, time_str); - uint board_id; - uint channel_id; - uint address; - unsigned long long time; - while (reader.read_row(board_id, channel_id, address, time)) { - // 板卡和通道号计算,通道号 = 板卡号 * 4 + 通道号 - int channel_num = (board_id) * 4 + (channel_id + 1); - QString particle_data_filename = result_data_output_dir.filePath(QStringLiteral(u"通道%1粒子数据.csv").arg(channel_num)); - if (!particle_data_filename_list.contains(channel_num)) { - particle_data_filename_list.insert(channel_num, particle_data_filename); - } - if (!ch_particle_data_of_list.contains(channel_num)) { - std::shared_ptr out( - new std::ofstream(QStrToSysPath(particle_data_filename), std::ios::out | std::ios::app), - [](std::ofstream* p) { p->close(); }); - *out << QString(QStringLiteral(u"板卡号,通道号,道址,时间计数")).toStdString() << std::endl; - ch_particle_data_of_list.insert(channel_num, out); - } - auto ch_particle_data_of = ch_particle_data_of_list.value(channel_num); - *ch_particle_data_of << board_id << "," << channel_id << "," << address << "," << time << std::endl; - } - } catch (const std::runtime_error& e) { - const QString& e_what = QString::fromLatin1(e.what()); - QString error = QString(QStringLiteral(u"处理%1发生运行时异常:%2")).arg(all_channel_particle_data_filename).arg(e_what); - LOG_ERROR(error) - ret_ok = false; - } catch (const std::exception& e) { - const QString& e_what = QString::fromLatin1(e.what()); - QString error = QString(QStringLiteral(u"处理%1异常:%2")).arg(all_channel_particle_data_filename).arg(e_what); - LOG_ERROR(error) - ret_ok = false; - } catch (...) { - QString error = QString(QStringLiteral(u"处理%1未知异常.")).arg(all_channel_particle_data_filename); - LOG_ERROR(error) - ret_ok = false; - } - - const QString& project_name = GetProjectName(); - MeasureAnalysisProjectModel* project_model = ProjectList::Instance()->GetProjectModel(project_name); - if (project_model == nullptr) { - ret_ok = false; - } - for (auto it = particle_data_filename_list.begin(); it != particle_data_filename_list.end(); ++it) { - // project_model->SetChannelParticleDataFilename(it.key(), it.value()); - } - - return ret_ok; -} - void EveryChannelParticleCountDataTask::SetAllChannelCountResultDir(const QString& dir_path) { this->_all_ch_count_dir = dir_path; @@ -223,29 +133,20 @@ bool EveryChannelParticleCountDataTask::processEveryChannelParticleData() bool ret_ok = true; const QString& all_ch_count_dir = GetAllChannelCountResultDir(); const QString& every_ch_count_dir = GetEveryChannelCountResultDir(); - QDir all_ch_count_output_dir(all_ch_count_dir); all_ch_count_output_dir.mkpath(all_ch_count_dir); - QDir every_ch_count_output_dir(every_ch_count_dir); every_ch_count_output_dir.mkpath(every_ch_count_dir); - const QString& all_channel_particle_data_filename = GetAllChannelParticleDataFilename(); QMap particle_count_filename_list; - // QString all_channel_total_count_filename; try { // 统计每个通道的粒子计数(相同板卡号通道号相同道址) QMap> channel_address_counts; // 通道号 -> 地址 -> 计数 - - // 统计所有通道的粒子计数(不同板卡号通道号相同道址) - // QMap all_channel_address_counts; // 地址 -> 计数 - std::string board_id_str = QString(QStringLiteral(u"板卡号")).toStdString(); std::string channel_id_str = QString(QStringLiteral(u"通道号")).toStdString(); std::string address_str = QString(QStringLiteral(u"道址")).toStdString(); std::string time_str = QString(QStringLiteral(u"时间计数")).toStdString(); - // 使用更灵活的方式处理CSV文件,忽略额外列 io::CSVReader< 4, @@ -262,60 +163,36 @@ bool EveryChannelParticleCountDataTask::processEveryChannelParticleData() while (reader.read_row(board_id, channel_id, address, time)) { // 板卡和通道号计算,通道号 = 板卡号 * 4 + 通道号 int channel_num = (board_id) * 4 + (channel_id + 1); - // 统计每个通道的粒子计数 if (!channel_address_counts.contains(channel_num)) { channel_address_counts[channel_num] = QMap(); } channel_address_counts[channel_num][address]++; - - // 统计所有通道的粒子计数 - // all_channel_address_counts[address]++; } - // 写入每个通道的粒子计数数据(优化:使用一次打开文件,批量写入) QMap> channel_file_streams; - // 预创建所有通道的文件流 for (auto channel_it = channel_address_counts.begin(); channel_it != channel_address_counts.end(); ++channel_it) { uint channel_num = channel_it.key(); QString count_data_filename = every_ch_count_output_dir.filePath(QStringLiteral(u"通道%1粒子计数.csv").arg(channel_num)); particle_count_filename_list.insert(channel_num, count_data_filename); - // 创建文件流 - std::shared_ptr out(new std::ofstream( QStrToSysPath(count_data_filename))); + std::shared_ptr out(new std::ofstream(QStrToSysPath(count_data_filename))); channel_file_streams[channel_num] = out; *out << QString(QStringLiteral(u"道址")).toStdString() << "," << QString(QStringLiteral(u"计数")).toStdString() << std::endl; } - // 批量写入数据 for (auto channel_it = channel_address_counts.begin(); channel_it != channel_address_counts.end(); ++channel_it) { uint channel_num = channel_it.key(); const QMap& address_counts = channel_it.value(); auto out_stream = channel_file_streams[channel_num]; - for (auto address_it = address_counts.begin(); address_it != address_counts.end(); ++address_it) { uint address = address_it.key(); unsigned long long count = address_it.value(); *out_stream << address << "," << count << std::endl; } } - - // 文件流会在shared_ptr析构时自动关闭 channel_file_streams.clear(); - - // 写入所有通道的粒子计数数据 - // all_channel_total_count_filename = all_ch_count_output_dir.filePath("AllChannelParticleTotalCountData.csv"); - // std::ofstream all_channel_out(QStrToSysPath(all_channel_total_count_filename)); - // all_channel_out << QString(QStringLiteral(u"道址")).toStdString() << "," << QString(QStringLiteral(u"计数")).toStdString() << std::endl; - - // for (auto address_it = all_channel_address_counts.begin(); address_it != all_channel_address_counts.end(); ++address_it) { - // uint address = address_it.key(); - // uint count = address_it.value(); - // all_channel_out << address << "," << count << std::endl; - // } - // all_channel_out.close(); - } catch (const std::runtime_error& e) { const QString& e_what = QString::fromLatin1(e.what()); QString error = QStringLiteral(u"处理%1发生运行时异常:%2").arg(all_channel_particle_data_filename).arg(e_what); @@ -341,8 +218,6 @@ bool EveryChannelParticleCountDataTask::processEveryChannelParticleData() for (auto it = particle_count_filename_list.begin(); it != particle_count_filename_list.end(); ++it) { project_model->SetChannelAddressCountDataFilename(it.key(), it.value()); } - // 更新项目模型中的所有通道粒子总计数数据文件名 - // project_model->SetAllChannelParticleTotalCountDataFilename(all_channel_total_count_filename); } const QString& info = QStringLiteral(u"所有通道粒子计数处理完成."); LOG_INFO(info); @@ -479,9 +354,7 @@ void mergeChunks(const std::vector& chunks, const std::string& outp while (!min_heap.empty()) { CsvRow current = min_heap.top(); min_heap.pop(); - outFile << current.board_id << "," << current.channel_id << "," << current.address << "," << current.time << "\n"; - size_t chunk_index = current.chunk_index; if (chunk_readers[chunk_index]) { uint board_id; @@ -589,7 +462,61 @@ bool CoincidenceEventAnalysisTask::processTask() if (project_model == nullptr) { return false; } - const QString& info = QStringLiteral(u"粒子符合事件数据处理完成."); + const QString& particle_data_filename = project_model->GetAllChannelParticleDataFilename(); + if (particle_data_filename.isEmpty()) { + return false; + } + std::string board_id_str = QString(QStringLiteral(u"板卡号")).toStdString(); + std::string channel_id_str = QString(QStringLiteral(u"通道号")).toStdString(); + std::string addr_str = QString(QStringLiteral(u"道址")).toStdString(); + std::string time_str = QString(QStringLiteral(u"时间计数")).toStdString(); + try { + io::CSVReader< + 4, + io::trim_chars<' ', '\t'>, + io::double_quote_escape<',', '"'>, + io::throw_on_overflow, + io::empty_line_comment> + reader(QStrToSysPath(particle_data_filename)); + reader.read_header(io::ignore_extra_column, board_id_str, channel_id_str, addr_str, time_str); + using namespace CoincidenceSpectrum::F2t9Order; + std::vector spec_data; + SpectrumData spec_data_item; + while (reader.read_row( + spec_data_item.board_id, + spec_data_item.channel_id, + spec_data_item.energy, + spec_data_item.timestamp)) { + spec_data.push_back(spec_data_item); + } + std::vector events; + if (!ProcessCoincidence(spec_data, events, project_model->GetConformTimeWin())) { + LOG_WARN(QStringLiteral(u"粒子符合数据处理异常!")); + } + const QString& coincidence_data_dir_name = QStringLiteral(u"粒子符合数据"); + QDir project_dir(project_model->GetProjectDir()); + project_dir.mkpath(coincidence_data_dir_name); + const QString& coincidence_data_dir_path = project_dir.filePath(coincidence_data_dir_name); + QMap > coincidence_data_out_stream_map; + for (const CoincidenceEvent& event : events) { + const QString& event_data_filename = QDir(coincidence_data_dir_path).filePath(QStringLiteral(u"[%1ns]%2个粒子符合事件[未刻度].csv").arg(project_model->GetConformTimeWin()).arg(event.coincidence_order)); + if ( !coincidence_data_out_stream_map.contains(event.coincidence_order) ) { + std::shared_ptr out_stream(new std::ofstream(QStrToSysPath(event_data_filename))); + *out_stream << board_id_str << "," << channel_id_str << "," << addr_str << "," << time_str << std::endl; + coincidence_data_out_stream_map[event.coincidence_order] = out_stream; + } + std::shared_ptr out_stream = coincidence_data_out_stream_map[event.coincidence_order]; + for (const SpectrumData& data_item : event.events) { + *out_stream << data_item.board_id << "," << data_item.channel_id << "," << data_item.energy << "," << data_item.timestamp << std::endl; + } + project_model->SetTimeWinConformParticleData(project_model->GetConformTimeWin(), event.coincidence_order, event_data_filename); + } + } catch (const std::exception& e) { + const QString& e_what = QString::fromUtf8(e.what()); + LOG_WARN(QStringLiteral(u"粒子符合数据处理异常:%1").arg(e_what)); + return false; + } + const QString& info = QStringLiteral(u"粒子符合数据处理完成."); LOG_INFO(info); return true; } @@ -827,6 +754,7 @@ bool EnergyScaleParticleDataTask::processTask() } } out.close(); + project_model->SetParticleEnergyDataFilename(energy_spectrum_filename); } catch (const std::exception& e) { out.close(); std::remove(QStrToSysPath(energy_spectrum_filename)); @@ -919,7 +847,7 @@ bool EnergyCountProcessTask::processTask() return true; } -bool EnergyScaleCoincidenceEventDataTask::processTask() +bool EnergyScaleCoincidenceDataTask::processTask() { const QString& project_name = GetProjectName(); MeasureAnalysisProjectModel* project_model = ProjectList::Instance()->GetProjectModel(project_name); @@ -933,6 +861,70 @@ bool EnergyScaleCoincidenceEventDataTask::processTask() if (!energy_scale_data_model.IsValid()) { return false; } + const QString& coincidence_data_dir_name = QStringLiteral(u"符合能谱数据"); + QDir project_dir(project_model->GetProjectDir()); + project_dir.mkpath(coincidence_data_dir_name); + const QString& coincidence_data_dir_path = project_dir.filePath(coincidence_data_dir_name); + + std::string board_id_str = QString(QStringLiteral(u"板卡号")).toStdString(); + std::string channel_id_str = QString(QStringLiteral(u"通道号")).toStdString(); + std::string addr_str = QString(QStringLiteral(u"道址")).toStdString(); + std::string energy_str = QString(QStringLiteral(u"能量(KeV)")).toStdString(); + std::string time_str = QString(QStringLiteral(u"时间计数")).toStdString(); + + auto conformParticleDataEnergyScale = [&](int time_win, int coincidence_order, const QString& conform_particle_data_filename) -> bool { + try { + io::CSVReader< + 4, + io::trim_chars<' ', '\t'>, + io::double_quote_escape<',', '"'>, + io::throw_on_overflow, + io::empty_line_comment> + reader(QStrToSysPath(conform_particle_data_filename)); + reader.read_header(io::ignore_extra_column, board_id_str, channel_id_str, addr_str, time_str); + + const QString& data_name = QStringLiteral(u"[%1ns]%2个粒子符合事件.csv").arg(time_win).arg(coincidence_order); + const QString& coincidence_energy_data_filename = QDir(coincidence_data_dir_path).filePath(data_name); + std::ofstream out_stream(QStrToSysPath(coincidence_energy_data_filename)); + out_stream << board_id_str << "," << channel_id_str << "," << energy_str << "," << time_str << "\n" ; + + using namespace CoincidenceSpectrum::F2t9Order; + SpectrumData data_item; + while (reader.read_row( + data_item.board_id, + data_item.channel_id, + data_item.energy, + data_item.timestamp)) { + int channel_num = (data_item.board_id) * 4 + (data_item.channel_id + 1); + const QString& channel_name = QStringLiteral(u"通道%1").arg(channel_num); + auto coeffs = energy_scale_data_model.GetEnergyFitResultCoeffs(channel_name); + if (!coeffs.empty()) { + data_item.energy = GaussPolyCoe::Predict(coeffs, data_item.energy); + out_stream << data_item.board_id << "," << data_item.channel_id << "," << data_item.energy << "," << data_item.timestamp << "\n" ; + } else { + LOG_WARN(QStringLiteral(u"符合能谱数据处理异常:%1能量刻度拟合参数为空!").arg(channel_name)); + out_stream.close(); + QFile::remove(coincidence_energy_data_filename); + return false; + } + } + out_stream.close(); + project_model->SetTimeWinConformEnergyData(time_win, coincidence_order, coincidence_energy_data_filename); + } catch (const std::exception& e) { + const QString& e_what = QString::fromStdString(e.what()); + LOG_WARN(QStringLiteral(u"符合能谱数据处理异常:%1").arg(e_what)); + return false; + } + return true; + }; + const auto& conform_particle_data_filename_list = project_model->GetConformParticleDataFilenameList(); + for (const auto& time_win : conform_particle_data_filename_list.keys()) { + const auto& time_win_event_data_filename_list = conform_particle_data_filename_list.value(time_win); + for (const auto& coincidence_order : time_win_event_data_filename_list.keys()) { + const QString& conform_particle_data_filename = time_win_event_data_filename_list.value(coincidence_order); + conformParticleDataEnergyScale(time_win, coincidence_order, conform_particle_data_filename); + } + } const QString& info = QStringLiteral(u"符合能谱数据处理完成."); LOG_INFO(info); return true; diff --git a/src/DataProcessWorkPool.h b/src/DataProcessWorkPool.h index e0aadfd..e2e6bd5 100644 --- a/src/DataProcessWorkPool.h +++ b/src/DataProcessWorkPool.h @@ -55,19 +55,6 @@ namespace DataProcessWorkPool QString _all_channel_particle_data_filename; }; - class EveryChannelParticleDataSeparateTask : public ParticleDataTask - { - public: - void SetResultDataDir(const QString& result_data_dir); - const QString& GetResultDataDir() const; - - virtual bool IsValidSetWorkParameters() const; - private: - virtual bool processEveryChannelParticleData() override; - private: - QString _result_data_dir; - }; - class EveryChannelParticleCountDataTask : public ParticleDataTask { public: @@ -151,7 +138,7 @@ namespace DataProcessWorkPool virtual bool processTask() override; }; - class EnergyScaleCoincidenceEventDataTask : public DataProcessTask + class EnergyScaleCoincidenceDataTask : public DataProcessTask { private: virtual bool processTask() override; diff --git a/src/MainWindow.cpp b/src/MainWindow.cpp index 8c9f8ad..48b66f7 100644 --- a/src/MainWindow.cpp +++ b/src/MainWindow.cpp @@ -164,6 +164,10 @@ void MainWindow::initAction() count_task->SetEveryChannelCountResultDir(every_ch_count_dir); count_task->SetFinishedNotifier(project_list_model, "onChannelAddressCountProcessFinished", project_model->GetProjectName()); count_task->StartTask(); + + auto coincidence_process_task = new DataProcessWorkPool::CoincidenceEventAnalysisTask; + coincidence_process_task->SetFinishedNotifier(project_list_model, "onCoincidenceProcessFinished", project_model->GetProjectName()); + coincidence_process_task->StartTask(); } } }; diff --git a/src/MeasureAnalysisHistoryForm.ui b/src/MeasureAnalysisHistoryForm.ui index dabec64..6ac0c82 100644 --- a/src/MeasureAnalysisHistoryForm.ui +++ b/src/MeasureAnalysisHistoryForm.ui @@ -67,47 +67,6 @@ - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - 加载测量分析 - - - - - - - 导出测量分析数据 - - - - - - - 导入测量粒子数据 - - - - - - - 删除 - - - diff --git a/src/MeasureAnalysisProjectModel.cpp b/src/MeasureAnalysisProjectModel.cpp index e7d2041..1783bdf 100644 --- a/src/MeasureAnalysisProjectModel.cpp +++ b/src/MeasureAnalysisProjectModel.cpp @@ -231,6 +231,11 @@ const QString MeasureAnalysisProjectModel::GetParticleEnergyDataFilename() const return this->_particle_energy_data_filename; } +const QMap > MeasureAnalysisProjectModel::GetConformParticleDataFilenameList() const +{ + return this->_time_win_conform_particle_data; +} + const QMap MeasureAnalysisProjectModel::GetTimeWinConformParticleDataFilenameList(uint time_win) const { QMap conform_particle_data; @@ -256,52 +261,23 @@ const QString MeasureAnalysisProjectModel::GetAnalysisCustomData(AnalysisType an bool MeasureAnalysisProjectModel::LoadProjectModel(const QString& project_filename) { - this->_project_filename = project_filename; - // 从json文件加载项目模型 - QFile json_file(this->_project_filename); - if (!json_file.open(QIODevice::ReadOnly | QIODevice::Text)) { - return false; + QVariantMap model_data; + if (!project_filename.isEmpty()) { + this->_project_filename = project_filename; + QFileInfo project_fileinfo(project_filename); + this->_project_dir = project_fileinfo.absoluteDir().absolutePath(); + QFile json_file(this->_project_filename); + if (!json_file.open(QIODevice::ReadOnly | QIODevice::Text)) { + return false; + } + QJsonDocument json_doc = QJsonDocument::fromJson(json_file.readAll()); + json_file.close(); + if (json_doc.isNull()) + return false; + if (!json_doc.isObject()) + return false; + model_data = json_doc.object().toVariantMap(); } - QJsonDocument json_doc = QJsonDocument::fromJson(json_file.readAll()); - json_file.close(); - if (json_doc.isNull()) { - return false; - } - if (!json_doc.isObject()) { - return false; - } - QJsonObject json_obj = json_doc.object(); - if (!json_obj.contains("ProjectName")) { - return false; - } - this->_project_name = json_obj["ProjectName"].toString(); - if (!json_obj.contains("SpectrumType")) { - return false; - } - this->_spec_type = (SpectrumType)json_obj["SpectrumType"].toInt(); - if (!json_obj.contains("IsStandardSource")) { - return false; - } - this->_is_std_source = json_obj["IsStandardSource"].toBool(); - if (!json_obj.contains("DescriptionInfo")) { - return false; - } - this->_description_info = json_obj["DescriptionInfo"].toString(); - if (!json_obj.contains("MeasurePresetTime")) { - return false; - } - this->_measure_preset_time = json_obj["MeasurePresetTime"].toInt(); - if (!json_obj.contains("IsMeasureComplete")) { - return false; - } - this->_is_measure_complete = json_obj["IsMeasureComplete"].toBool(); - if (!json_obj.contains("ConformTimeWin")) { - return false; - } - this->_conform_time_win = json_obj["ConformTimeWin"].toInt(); - - QFileInfo project_fileinfo(project_filename); - this->_project_dir = project_fileinfo.absoluteDir().absolutePath(); auto ProjectAbsFilename = [this](const QString& project_relative_filename){ QString project_abs_filename; @@ -315,34 +291,73 @@ bool MeasureAnalysisProjectModel::LoadProjectModel(const QString& project_filena } return project_abs_filename; }; + if (!model_data.contains("ProjectName")) + return false; + this->_project_name = model_data["ProjectName"].toString(); + if (!model_data.contains("SpectrumType")) + return false; + this->_spec_type = SpectrumType(model_data["SpectrumType"].toInt()); + if (!model_data.contains("IsStandardSource")) + return false; + this->_is_std_source = model_data["IsStandardSource"].toBool(); + if (!model_data.contains("DescriptionInfo")) + return false; + this->_description_info = model_data["DescriptionInfo"].toString(); + if (!model_data.contains("MeasurePresetTime")) + return false; + this->_measure_preset_time = model_data["MeasurePresetTime"].toInt(); + if (!model_data.contains("IsMeasureComplete")) + return false; + this->_is_measure_complete = model_data["IsMeasureComplete"].toBool(); + if (!model_data.contains("ConformTimeWin")) + return false; + this->_conform_time_win = model_data["ConformTimeWin"].toInt(); - this->_measure_device_params_cfg_filename = ProjectAbsFilename(json_obj["MeasureDeviceParamsCfgFilename"].toString()); - this->_energy_scale_filename = ProjectAbsFilename(json_obj["EnergyScaleFilename"].toString()); - this->_efficiency_scale_filename = ProjectAbsFilename(json_obj["EfficiencyScaleFilename"].toString()); - this->_all_channel_particle_data_filename = ProjectAbsFilename(json_obj["AllChannelParticleDataFilename"].toString()); - const auto& address_count_data_filename_list = json_obj["ChannelAddressCountDataFilenameList"].toObject().toVariantMap(); + this->_measure_device_params_cfg_filename = ProjectAbsFilename(model_data["MeasureDeviceParamsCfgFilename"].toString()); + this->_energy_scale_filename = ProjectAbsFilename(model_data["EnergyScaleFilename"].toString()); + this->_efficiency_scale_filename = ProjectAbsFilename(model_data["EfficiencyScaleFilename"].toString()); + this->_all_channel_particle_data_filename = ProjectAbsFilename(model_data["AllChannelParticleDataFilename"].toString()); + + const auto& address_count_data_filename_list = model_data["ChannelAddressCountDataFilenameList"].toMap(); for (auto it = address_count_data_filename_list.constBegin(); it!=address_count_data_filename_list.constEnd(); ++it) { uint channel_num = it.key().toUInt(); this->_channel_address_count_data_filename_list[channel_num] = ProjectAbsFilename(it.value().toString()); } - const auto& energy_count_data_filename_list = json_obj["ChannelEnergyCountDataFilenameList"].toObject().toVariantMap(); + + const auto& energy_count_data_filename_list = model_data["ChannelEnergyCountDataFilenameList"].toMap(); for (auto it = energy_count_data_filename_list.constBegin(); it!=energy_count_data_filename_list.constEnd(); ++it) { uint channel_num = it.key().toUInt(); this->_channel_energy_count_data_filename_list[channel_num] = ProjectAbsFilename(it.value().toString()); } - this->_all_channel_energy_total_count_data_filename = ProjectAbsFilename(json_obj["AllChannelEnergyTotalCountDataFilename"].toString()); - this->_particle_energy_data_filename = ProjectAbsFilename(json_obj["ParticleEnergyDataFilename"].toString()); - const auto& time_win_conform_particle_data = json_obj["TimeWinConformParticleData"].toObject().toVariantMap(); - for (auto it = time_win_conform_particle_data.constBegin(); it!=time_win_conform_particle_data.constEnd(); ++it) { - uint time_win = it.key().toUInt(); + + this->_all_channel_energy_total_count_data_filename = ProjectAbsFilename(model_data["AllChannelEnergyTotalCountDataFilename"].toString()); + + this->_particle_energy_data_filename = ProjectAbsFilename(model_data["ParticleEnergyDataFilename"].toString()); + + const auto& time_win_conform_particle_data = model_data["TimeWinConformParticleData"].toMap(); + for (auto it1 = time_win_conform_particle_data.constBegin(); it1!=time_win_conform_particle_data.constEnd(); ++it1) { + uint time_win = it1.key().toUInt(); QMap conform_particle_data; - // const auto& conform_particle_data_list = it.value().toObject().toVariantMap(); - // for (auto it2 = conform_particle_data_list.constBegin(); it2!=conform_particle_data_list.constEnd(); ++it2) { - // uint particle_count = it2.key().toUInt(); - // conform_particle_data[particle_count] = ProjectAbsFilename(it2.value().toString()); - // } + const auto& conform_particle_data_list = it1.value().toMap(); + for (auto it2 = conform_particle_data_list.constBegin(); it2!=conform_particle_data_list.constEnd(); ++it2) { + uint particle_count = it2.key().toUInt(); + conform_particle_data[particle_count] = ProjectAbsFilename(it2.value().toString()); + } this->_time_win_conform_particle_data[time_win] = conform_particle_data; } + + const auto& time_win_conform_energy_data = model_data["TimeWinConformEnergyData"].toMap(); + for (auto it1 = time_win_conform_energy_data.constBegin(); it1!=time_win_conform_energy_data.constEnd(); ++it1) { + uint time_win = it1.key().toUInt(); + QMap conform_energy_data; + const auto& conform_energy_data_list = it1.value().toMap(); + for (auto it2 = conform_energy_data_list.constBegin(); it2!=conform_energy_data_list.constEnd(); ++it2) { + uint particle_count = it2.key().toUInt(); + conform_energy_data[particle_count] = ProjectAbsFilename(it2.value().toString()); + } + this->_time_win_conform_energy_data[time_win] = conform_energy_data; + } + return true; } @@ -378,28 +393,41 @@ bool MeasureAnalysisProjectModel::SaveProjectModel() project_json_obj_map["EnergyScaleFilename"] = ProjectRelativeFilename(this->_energy_scale_filename); project_json_obj_map["EfficiencyScaleFilename"] = ProjectRelativeFilename(this->_efficiency_scale_filename); project_json_obj_map["AllChannelParticleDataFilename"] = ProjectRelativeFilename(this->_all_channel_particle_data_filename); + project_json_obj_map["ParticleEnergyDataFilename"] = ProjectRelativeFilename(this->_particle_energy_data_filename); + QVariantMap channel_address_count_data_filename_list; for (auto it = this->_channel_address_count_data_filename_list.constBegin(); it != this->_channel_address_count_data_filename_list.constEnd(); ++it) { channel_address_count_data_filename_list[QString::number(it.key())] = ProjectRelativeFilename(it.value()); } project_json_obj_map["ChannelAddressCountDataFilenameList"] = channel_address_count_data_filename_list; + QVariantMap channel_energy_count_data_filename_list; for (auto it = this->_channel_energy_count_data_filename_list.constBegin(); it != this->_channel_energy_count_data_filename_list.constEnd(); ++it) { channel_energy_count_data_filename_list[QString::number(it.key())] = ProjectRelativeFilename(it.value()); } project_json_obj_map["ChannelEnergyCountDataFilenameList"] = channel_energy_count_data_filename_list; project_json_obj_map["AllChannelEnergyTotalCountDataFilename"] = ProjectRelativeFilename(this->_all_channel_energy_total_count_data_filename); + QVariantMap time_win_conform_particle_data; - for (auto it = this->_time_win_conform_particle_data.constBegin(); it != this->_time_win_conform_particle_data.constEnd(); ++it) { + for (auto it1 = this->_time_win_conform_particle_data.constBegin(); it1 != this->_time_win_conform_particle_data.constEnd(); ++it1) { QVariantMap conform_particle_data; - for (auto it2 = it.value().constBegin(); it2 != it.value().constEnd(); ++it2) { + for (auto it2 = it1.value().constBegin(); it2 != it1.value().constEnd(); ++it2) { conform_particle_data[QString::number(it2.key())] = ProjectRelativeFilename(it2.value()); } - time_win_conform_particle_data[QString::number(it.key())] = conform_particle_data; + time_win_conform_particle_data[QString::number(it1.key())] = conform_particle_data; } - project_json_obj_map["ParticleEnergyDataFilename"] = ProjectRelativeFilename(this->_particle_energy_data_filename); project_json_obj_map["TimeWinConformParticleData"] = time_win_conform_particle_data; + QVariantMap time_win_conform_energy_data; + for (auto it1 = this->_time_win_conform_energy_data.constBegin(); it1 != this->_time_win_conform_energy_data.constEnd(); ++it1) { + QVariantMap conform_energy_data; + for (auto it2 = it1.value().constBegin(); it2 != it1.value().constEnd(); ++it2) { + conform_energy_data[QString::number(it2.key())] = ProjectRelativeFilename(it2.value()); + } + time_win_conform_energy_data[QString::number(it1.key())] = conform_energy_data; + } + project_json_obj_map["TimeWinConformEnergyData"] = time_win_conform_energy_data; + // 将项目模型保存到json文件 QJsonDocument json_doc = QJsonDocument::fromVariant(project_json_obj_map); QFile json_file(this->_project_filename); @@ -661,9 +689,14 @@ void MeasureAnalysisProjectModelList::ApplyEnergyScale(const QString &project_na 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(); + + auto coincidence_process_task = new DataProcessWorkPool::EnergyScaleCoincidenceDataTask; + coincidence_process_task->SetFinishedNotifier(this, "onEnergyScaleCoincidenceDataFinished", project_name); + coincidence_process_task->StartTask(); } } } @@ -720,6 +753,11 @@ void MeasureAnalysisProjectModelList::onEnergyScaleParticleDataFinished(bool ok, if (!particle_energy_data_filename.isEmpty()) { status_ok = true; status = QStringLiteral(u"有效"); + const QString& particle_energy_item_name = QStringLiteral(u"粒子能量数据"); + if (node_map.contains(particle_energy_item_name)) { + auto energy_total_count_spec_item = node_map[particle_energy_item_name]; + this->SetNodeStatus(energy_total_count_spec_item, status, status_ok); + } const QString& count_rate_analysis_item_name = QStringLiteral(u"计数率分析"); if (node_map.contains(count_rate_analysis_item_name)) { auto energy_total_count_spec_item = node_map[count_rate_analysis_item_name]; @@ -793,6 +831,17 @@ void MeasureAnalysisProjectModelList::onEnergyCountProcessFinished(bool ok, cons } void MeasureAnalysisProjectModelList::onCoincidenceProcessFinished(bool ok, const QString &project_name, const QVariant &data) +{ + Q_UNUSED(data); + if ( !ok ) + return; + if (this->_project_models.contains(project_name)) { + auto pro_model = this->_project_models[project_name]; + pro_model->SaveProjectModel(); + } +} + +void MeasureAnalysisProjectModelList::onEnergyScaleCoincidenceDataFinished(bool ok, const QString &project_name, const QVariant &data) { Q_UNUSED(data); if ( !ok ) @@ -807,7 +856,12 @@ void MeasureAnalysisProjectModelList::onCoincidenceProcessFinished(bool ok, cons if (!Conform_energy_data_filename_list.isEmpty()) { status_ok = true; status = QStringLiteral(u"有效"); - QString item_name = QStringLiteral(u"符合事件时间分析"); + QString item_name = QStringLiteral(u"符合粒子能量数据[%1ns]").arg(conform_time_win); + if (node_map.contains(item_name)) { + auto energy_total_count_spec_item = node_map[item_name]; + this->SetNodeStatus(energy_total_count_spec_item, status, status_ok); + } + item_name = QStringLiteral(u"符合事件时间分析"); if (node_map.contains(item_name)) { auto energy_total_count_item = node_map[item_name]; this->SetNodeStatus(energy_total_count_item, status, status_ok); @@ -945,10 +999,10 @@ void MeasureAnalysisProjectModelList::intiProjectNodeStruce(MeasureAnalysisProje } uint conform_time_win = pro_model->GetConformTimeWin(); - state_ok = !pro_model->GetTimeWinConformParticleDataFilenameList(conform_time_win).isEmpty(); + state_ok = !pro_model->GetTimeWinConformEnergyDataFilenameList(conform_time_win).isEmpty(); status = state_ok ? QStringLiteral(u"有效") : QStringLiteral(u"无效"); analys_type = QVariant::fromValue(AnalysisType::CoincidenceParticleEnergyData); - item_name = QStringLiteral(u"符合粒子数据[%1ns]").arg(conform_time_win); + item_name = QStringLiteral(u"符合粒子能量数据[%1ns]").arg(conform_time_win); node_item = AddChildNode(analysis_data_item, item_name, status, analys_type, true, state_ok); node_item->setData(project_name, ProjectName); node_map[item_name] = node_item; diff --git a/src/MeasureAnalysisProjectModel.h b/src/MeasureAnalysisProjectModel.h index dffbf8d..816960e 100644 --- a/src/MeasureAnalysisProjectModel.h +++ b/src/MeasureAnalysisProjectModel.h @@ -33,9 +33,7 @@ public: void SetEnergyScaleFilename(const QString& filename); void SetEfficiencyScaleFilename(const QString& filename); void SetAllChannelParticleDataFilename(const QString& filename); - // void SetChannelParticleDataFilename(uint channel, const QString& filename); void SetChannelAddressCountDataFilename(uint channel, const QString& filename); - // void SetAllChannelParticleTotalCountDataFilename(const QString& filename); void SetChannelEnergyCountDataFilename(uint channel, const QString& filename); void SetAllChannelEnergyTotalCountDataFilename(const QString& filename); void SetParticleEnergyDataFilename(const QString& filename); @@ -55,15 +53,13 @@ public: const QString& GetEnergyScaleFilename() const; const QString& GetEfficiencyScaleFilename() const; const QString& GetAllChannelParticleDataFilename() const; - // const QMap& GetChannelParticleDataFilenameList() const; - // const QString& GetChannelParticleDataFilename(uint channel) const; const QMap& GetChannelAddressCountDataFilenameList() const; const QString GetChannelAddressCountDataFilename(uint channel) const; - // const QString& GetAllChannelParticleTotalCountDataFilename() const; const QMap& GetChannelEnergyCountDataFilenameList() const; const QString GetChannelEnergyCountDataFilename(uint channel) const; const QString& GetAllChannelEnergyTotalCountDataFilename() const; const QString GetParticleEnergyDataFilename() const; + const QMap > GetConformParticleDataFilenameList() const; const QMap GetTimeWinConformParticleDataFilenameList(uint time_win) const; const QMap GetTimeWinConformEnergyDataFilenameList(uint time_win) const; const QString GetAnalysisCustomData(AnalysisType analysis_type, const QString& data_item_name); @@ -146,6 +142,7 @@ private slots: void onEnergyScaleParticleDataFinished(bool ok, const QString& project_name, const QVariant& data); void onEnergyCountProcessFinished(bool ok, const QString& project_name, const QVariant& data); void onCoincidenceProcessFinished(bool ok, const QString& project_name, const QVariant& data); + void onEnergyScaleCoincidenceDataFinished(bool ok, const QString& project_name, const QVariant& data); private: void intiProjectNodeStruce(MeasureAnalysisProjectModel *pro_model);