diff --git a/src/AntiConformEnergySpectrumView/AntiConformEnergySpectrumView.cpp b/src/AntiConformEnergySpectrumView/AntiConformEnergySpectrumView.cpp new file mode 100644 index 0000000..21696bd --- /dev/null +++ b/src/AntiConformEnergySpectrumView/AntiConformEnergySpectrumView.cpp @@ -0,0 +1,158 @@ +#include "AntiConformEnergySpectrumView.h" +#include +#include +#include +#include +#include "CustomQwtPlot.h" +#include +#include "csv.h" +#include +#include +#include "BusyIndicator.h" +#include +#include +#include +#include +#include +struct SpectrumData +{ + int board_id; + int channel_id; + double energy; + uint64_t timestamp; +}; + + +AntiConformEnergySpectrumView::AntiConformEnergySpectrumView(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(_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); +} + +AntiConformEnergySpectrumView::~AntiConformEnergySpectrumView() +{ +} + +void AntiConformEnergySpectrumView::InitViewWorkspace(const QString &project_name) +{ + Q_UNUSED(project_name); +} + +void AntiConformEnergySpectrumView::SetAnalyzeDataFilename(const QMap &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(); + } +} + + +void AntiConformEnergySpectrumView::loadAndProcess() +{ + auto functionToRun = [this]() { + if (_data_filename.isEmpty()) return; + + _busy_indicator->Start(); + + std::vector 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 int STEP = 1; + std::map hist; + + for (const auto& spdt : rawData) { + int idx = static_cast(spdt.energy) / STEP; + hist[idx] += 1.0; + } + + QVector 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 AntiConformEnergySpectrumView::showEvent(QShowEvent *e) +{ + Q_UNUSED(e); + if (_busy_indicator) { + _busy_indicator->setGeometry(this->rect()); + this->update(); + } +} + + diff --git a/src/AntiConformEnergySpectrumView/AntiConformEnergySpectrumView.h b/src/AntiConformEnergySpectrumView/AntiConformEnergySpectrumView.h new file mode 100644 index 0000000..80d1b57 --- /dev/null +++ b/src/AntiConformEnergySpectrumView/AntiConformEnergySpectrumView.h @@ -0,0 +1,34 @@ +#ifndef ANTICONFORMENERGYSPECTRUMVIEW_H +#define ANTICONFORMENERGYSPECTRUMVIEW_H + +#include "MeasureAnalysisView.h" + +class CustomQwtPlot; +class QwtPlotCurve; +class BusyIndicator; + +class AntiConformEnergySpectrumView : public MeasureAnalysisView +{ + Q_OBJECT +public: + explicit AntiConformEnergySpectrumView(QWidget *parent = nullptr); + virtual ~AntiConformEnergySpectrumView(); + virtual void InitViewWorkspace(const QString& project_name) override final; + virtual void SetAnalyzeDataFilename(const QMap& 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 // ANTICONFORMENERGYSPECTRUMVIEW_H + + diff --git a/src/CustomQwtPlot.h b/src/CustomQwtPlot.h index 0e59954..46e1650 100644 --- a/src/CustomQwtPlot.h +++ b/src/CustomQwtPlot.h @@ -106,9 +106,6 @@ private: }; - - - QColor getDistinctColorForManyCurves(int curve_index); #endif // CUSTOMQWTPLOT_H diff --git a/src/DataCalcProcess/CoincidenceSpectrumProcess.cpp b/src/DataCalcProcess/CoincidenceSpectrumProcess.cpp index b90051c..8dd87ee 100644 --- a/src/DataCalcProcess/CoincidenceSpectrumProcess.cpp +++ b/src/DataCalcProcess/CoincidenceSpectrumProcess.cpp @@ -178,6 +178,7 @@ void SortDataByTimestamp(std::vector& data) bool ProcessCoincidence( std::vector& data, std::vector& events, + std::vector& anti_coincidence_events, unsigned int time_window, int min_order, int max_order @@ -187,8 +188,13 @@ bool ProcessCoincidence( if (n < min_order) { return false; } + if (min_order < 2 || max_order < min_order) + return false; + std::vector is_used(n, false); // 使用滑动窗口寻找符合事件 for (int i = 0; i < n; ++i) { + if (is_used[i]) + continue; std::vector current_coincidence; current_coincidence.push_back(data[i]); // 寻找时间窗口内的其他事件 @@ -206,6 +212,10 @@ bool ProcessCoincidence( // 保存符合条件的事件 int coincidence_order = current_coincidence.size(); if (coincidence_order >= min_order && coincidence_order <= max_order) { + // 标记这些事件已被使用 + for (int k = 0; k < coincidence_order; ++k) { + is_used[i + k] = true; + } CoincidenceEvent result; result.coincidence_order = coincidence_order; result.events = current_coincidence; @@ -213,6 +223,31 @@ bool ProcessCoincidence( events.push_back(result); } } + + for (int i = 0; i < n; ++i) { + if (is_used[i]) + continue; + bool is_anti = true; + // 检查前向时间窗口内是否有其他事件 + if (i > 0) { + unsigned long long diff_prev = data[i].timestamp - data[i-1].timestamp; + if (diff_prev <= time_window) + is_anti = false; + } + // 检查后向时间窗口内是否有其他事件 + if (i < n-1 && is_anti) { + unsigned long long diff_next = data[i+1].timestamp - data[i].timestamp; + if (diff_next <= time_window) + is_anti = false; + } + // 满足反符合条件 + if (is_anti) { + AntiCoincidenceEvent res; + res.event = data[i]; + res.time_window = time_window; + anti_coincidence_events.push_back(res); + } + } return true; } diff --git a/src/DataCalcProcess/CoincidenceSpectrumProcess.h b/src/DataCalcProcess/CoincidenceSpectrumProcess.h index fafa651..f172e70 100644 --- a/src/DataCalcProcess/CoincidenceSpectrumProcess.h +++ b/src/DataCalcProcess/CoincidenceSpectrumProcess.h @@ -28,6 +28,11 @@ namespace F2t9Order { std::vector events; // 符合的事件集合 unsigned int time_window; // 使用的时间窗口(秒) }; + // 反符合事件结构体(只包含未参与任何符合的独立事件) + struct AntiCoincidenceEvent { + SpectrumData event; // 反符合单事件 + unsigned int time_window; // 时间窗口 + }; // 读取CSV数据文件 std::vector ReadCsv(const std::string& filename); @@ -39,6 +44,7 @@ namespace F2t9Order { bool ProcessCoincidence( std::vector &data, std::vector &events, + std::vector& anti_coincidence_events, unsigned int time_window, // 时间窗口(纳秒) int min_order = 2, // 最小符合次数 int max_order = 9 // 最大符合次数 diff --git a/src/DataProcessWorkPool.cpp b/src/DataProcessWorkPool.cpp index d7bbb85..18238af 100644 --- a/src/DataProcessWorkPool.cpp +++ b/src/DataProcessWorkPool.cpp @@ -466,6 +466,7 @@ bool CoincidenceEventAnalysisTask::processTask() if (particle_data_filename.isEmpty()) { return false; } + std::string time_win_str = QString(QStringLiteral(u"时间窗口")).toStdString(); std::string event_id_str = QString(QStringLiteral(u"事件ID")).toStdString(); std::string board_id_str = QString(QStringLiteral(u"板卡号")).toStdString(); std::string channel_id_str = QString(QStringLiteral(u"通道号")).toStdString(); @@ -490,8 +491,9 @@ bool CoincidenceEventAnalysisTask::processTask() spec_data_item.timestamp)) { spec_data.push_back(spec_data_item); } - std::vector events; - if (!ProcessCoincidence(spec_data, events, project_model->GetConformTimeWin())) { + std::vector coincidence_events; + std::vector anti_coincidence_events; + if (!ProcessCoincidence(spec_data, coincidence_events, anti_coincidence_events, project_model->GetConformTimeWin())) { LOG_WARN(QStringLiteral(u"粒子符合数据处理异常!")); } const QString& coincidence_data_dir_name = QStringLiteral(u"粒子符合数据"); @@ -500,7 +502,7 @@ bool CoincidenceEventAnalysisTask::processTask() const QString& coincidence_data_dir_path = project_dir.filePath(coincidence_data_dir_name); QMap > coincidence_data_out_stream_map; unsigned long long event_id = 0; - for (const CoincidenceEvent& event : events) { + for (const CoincidenceEvent& event : coincidence_events) { ++ event_id; 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) ) { @@ -514,6 +516,13 @@ bool CoincidenceEventAnalysisTask::processTask() } project_model->SetTimeWinConformParticleData(project_model->GetConformTimeWin(), event.coincidence_order, event_data_filename); } + const QString& anti_event_data_filename = QDir(coincidence_data_dir_path).filePath(QStringLiteral(u"反符合事件[未刻度].csv")); + std::ofstream anti_event_data_out_stream(QStrToSysPath(anti_event_data_filename)); + anti_event_data_out_stream << time_win_str << "," << board_id_str << "," << channel_id_str << "," << addr_str << "," << time_str << std::endl; + for (const AntiCoincidenceEvent& anti_event : anti_coincidence_events) { + anti_event_data_out_stream << anti_event.time_window << "," << anti_event.event.board_id << "," << anti_event.event.channel_id << "," << anti_event.event.energy << "," << anti_event.event.timestamp << std::endl; + } + project_model->SetAntiConformParticleData(project_model->GetConformTimeWin(), anti_event_data_filename); } catch (const std::exception& e) { const QString& e_what = QString::fromUtf8(e.what()); LOG_WARN(QStringLiteral(u"粒子符合数据处理异常:%1").arg(e_what)); @@ -931,7 +940,83 @@ bool EnergyScaleCoincidenceDataTask::processTask() conformParticleDataEnergyScale(time_win, coincidence_order, conform_particle_data_filename); } } + const QString& info = QStringLiteral(u"符合能谱数据处理完成."); LOG_INFO(info); return true; } + +bool EnergyScaleaAntiCoincidenceDataTask::processTask() +{ + const QString& project_name = GetProjectName(); + MeasureAnalysisProjectModel* project_model = ProjectList::Instance()->GetProjectModel(project_name); + if (project_model == nullptr) { + return false; + } + EnergyScaleDataModel energy_scale_data_model(project_model->GetEnergyScaleFilename()); + if (!energy_scale_data_model.LoadData()) { + return false; + } + 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 time_win_str = QString(QStringLiteral(u"时间窗口")).toStdString(); + 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(); + + const auto& anti_conform_particle_data = project_model->GetAntiConformParticleData(); + for (const auto& time_win : anti_conform_particle_data.keys()) { + const auto&anti_conform_particle_data_filename = anti_conform_particle_data.value(time_win); + try { + io::CSVReader< + 5, + io::trim_chars<' ', '\t'>, + io::double_quote_escape<',', '"'>, + io::throw_on_overflow, + io::empty_line_comment> + reader(QStrToSysPath(anti_conform_particle_data_filename)); + reader.read_header(io::ignore_extra_column, time_win_str, board_id_str, channel_id_str, addr_str, time_str); + + const QString& anti_coincidence_energy_data_filename = QDir(coincidence_data_dir_path).filePath(QStringLiteral(u"反符合粒子事件.csv")); + std::ofstream out_stream(QStrToSysPath(anti_coincidence_energy_data_filename)); + out_stream << time_win_str << "," << board_id_str << "," << channel_id_str << "," << energy_str << "," << time_str << "\n" ; + using namespace CoincidenceSpectrum::F2t9Order; + unsigned int time_window; + SpectrumData data_item; + while (reader.read_row( + time_window, + 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 << time_window << "," << 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(); + project_model->SetAntiConformEnergyData(time_win, anti_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; + } + } + + const QString& info = QStringLiteral(u"反符合能谱数据处理完成."); + LOG_INFO(info); + return true; +} diff --git a/src/DataProcessWorkPool.h b/src/DataProcessWorkPool.h index e2e6bd5..a5bfb03 100644 --- a/src/DataProcessWorkPool.h +++ b/src/DataProcessWorkPool.h @@ -143,6 +143,12 @@ namespace DataProcessWorkPool private: virtual bool processTask() override; }; + + class EnergyScaleaAntiCoincidenceDataTask : public DataProcessTask + { + private: + virtual bool processTask() override; + }; } #endif // DATAPROCESSWORKPOOL_H diff --git a/src/GlobalDefine.h b/src/GlobalDefine.h index 955a506..f3d699a 100644 --- a/src/GlobalDefine.h +++ b/src/GlobalDefine.h @@ -10,7 +10,7 @@ // 转换Qt字符串路径为系统编码的C字符串(解决中文路径问题) static const char* QStrToSysPath(const QString& qstr_path) { - static std::string sys_path; // 静态变量避免内存释放 + std::string sys_path; // 静态变量避免内存释放 #ifdef Q_OS_WIN // Windows:转为GBK编码 QTextCodec* gbkCodec = QTextCodec::codecForName("GBK"); diff --git a/src/MeasureAnalysisProjectModel.cpp b/src/MeasureAnalysisProjectModel.cpp index 91d5686..36164a1 100644 --- a/src/MeasureAnalysisProjectModel.cpp +++ b/src/MeasureAnalysisProjectModel.cpp @@ -113,6 +113,16 @@ void MeasureAnalysisProjectModel::SetTimeWinConformEnergyData(uint time_win, uin this->_time_win_conform_energy_data[time_win][conform_particle_count] = filename; } +void MeasureAnalysisProjectModel::SetAntiConformParticleData(uint time_win, const QString &filename) +{ + this->_anti_conform_particle_data[time_win] = filename; +} + +void MeasureAnalysisProjectModel::SetAntiConformEnergyData(uint time_win, const QString &filename) +{ + this->_anti_conform_energy_data[time_win] = filename; +} + void MeasureAnalysisProjectModel::SetAnalysisCustomData(AnalysisType analysis_type, const QString &data_item_name, const QString &data_filename) { this->_analysis_custom_data_set[analysis_type][data_item_name] = data_filename; @@ -259,6 +269,26 @@ const QMap MeasureAnalysisProjectModel::GetTimeWinConformEnergyDa return conform_energy_data; } +const QMap &MeasureAnalysisProjectModel::GetAntiConformParticleData() +{ + return _anti_conform_particle_data; +} + +const QString &MeasureAnalysisProjectModel::GetAntiConformParticleData(uint time_win) +{ + return _anti_conform_particle_data.value(time_win); +} + +const QMap &MeasureAnalysisProjectModel::GetAntiConformEnergyData() +{ + return _anti_conform_energy_data; +} + +const QString &MeasureAnalysisProjectModel::GetAntiConformEnergyData(uint time_win) +{ + return _anti_conform_energy_data.value(time_win); +} + const QString MeasureAnalysisProjectModel::GetAnalysisCustomData(AnalysisType analysis_type, const QString &data_item_name) { return this->_analysis_custom_data_set.value(analysis_type).value(data_item_name); @@ -403,6 +433,16 @@ bool MeasureAnalysisProjectModel::LoadProjectModel(const QString& project_filena this->_time_win_conform_energy_data[time_win] = conform_energy_data; } + const auto& anti_conform_particle_data = model_data["AntiConformParticleData"].toMap(); + for (auto it = anti_conform_particle_data.constBegin(); it!=anti_conform_particle_data.constEnd(); ++it) { + this->_anti_conform_particle_data[it.key().toUInt()] = ProjectAbsFilename(it.value().toString()); + } + + const auto& anti_conform_energy_data = model_data["AntiConformEnergyData"].toMap(); + for (auto it = anti_conform_energy_data.constBegin(); it!=anti_conform_energy_data.constEnd(); ++it) { + this->_anti_conform_energy_data[it.key().toUInt()] = ProjectAbsFilename(it.value().toString()); + } + return true; } @@ -473,6 +513,18 @@ bool MeasureAnalysisProjectModel::SaveProjectModel() } project_json_obj_map["TimeWinConformEnergyData"] = time_win_conform_energy_data; + QVariantMap anti_conform_particle_data; + for (auto it = this->_anti_conform_particle_data.constBegin(); it != this->_anti_conform_particle_data.constEnd(); ++it) { + anti_conform_particle_data[QString::number(it.key())] = ProjectRelativeFilename(it.value()); + } + project_json_obj_map["AntiConformParticleData"] = anti_conform_particle_data; + + QVariantMap anti_conform_energy_data; + for (auto it = this->_anti_conform_energy_data.constBegin(); it != this->_anti_conform_energy_data.constEnd(); ++it) { + anti_conform_energy_data[QString::number(it.key())] = ProjectRelativeFilename(it.value()); + } + project_json_obj_map["AntiConformEnergyData"] = anti_conform_energy_data; + // 将项目模型保存到json文件 QJsonDocument json_doc = QJsonDocument::fromVariant(project_json_obj_map); QFile json_file(this->_project_filename); @@ -743,6 +795,10 @@ void MeasureAnalysisProjectModelList::ApplyEnergyScale(const QString &project_na 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(); } } } @@ -954,11 +1010,6 @@ void MeasureAnalysisProjectModelList::onEnergyScaleCoincidenceDataFinished(bool auto energy_total_count_spec_item = node_map[item_name]; this->SetNodeStatus(energy_total_count_spec_item, status, status_ok); } - 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"二维符合能谱[%1ns]").arg(conform_time_win); if (node_map.contains(item_name)) { auto energy_total_count_spec_item = node_map[item_name]; @@ -977,6 +1028,33 @@ void MeasureAnalysisProjectModelList::onEnergyScaleCoincidenceDataFinished(bool } } +void MeasureAnalysisProjectModelList::onEnergyScaleAntiCoincidenceDataFinished(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]; + auto& node_map = this->_project_node_items[project_name]; + const auto& anti_conform_energy_data = pro_model->GetAntiConformEnergyData(); + for (const auto& time_win : anti_conform_energy_data.keys()) { + bool status_ok = false; + QString status = QStringLiteral(u"无效"); + const QString& data_filename = anti_conform_energy_data.value(time_win); + if ( (!data_filename.isEmpty()) && QFile::exists(data_filename) ) { + status_ok = true; + status = QStringLiteral(u"有效"); + } + 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); + } + } + pro_model->SaveProjectModel(); + } +} + void MeasureAnalysisProjectModelList::intiProjectNodeStruce(MeasureAnalysisProjectModel* pro_model) { if (!pro_model) { diff --git a/src/MeasureAnalysisProjectModel.h b/src/MeasureAnalysisProjectModel.h index 317c8c1..5a2d845 100644 --- a/src/MeasureAnalysisProjectModel.h +++ b/src/MeasureAnalysisProjectModel.h @@ -39,6 +39,8 @@ public: void SetParticleEnergyDataFilename(const QString& filename); void SetTimeWinConformParticleData(uint time_win, uint conform_particle_count, const QString& filename); void SetTimeWinConformEnergyData(uint time_win, uint conform_particle_count, const QString& filename); + void SetAntiConformParticleData(uint time_win, const QString& filename); + void SetAntiConformEnergyData(uint time_win, const QString& filename); void SetAnalysisCustomData(AnalysisType analysis_type, const QString& data_item_name, const QString& data_filename); const QString& GetProjectDir() const; @@ -63,6 +65,10 @@ public: const QMap GetTimeWinConformParticleDataFilenameList(uint time_win) const; const QMap > GetConformParticleEnergyDataFilenameList() const; const QMap GetTimeWinConformEnergyDataFilenameList(uint time_win) const; + const QMap& GetAntiConformParticleData(); + const QString& GetAntiConformParticleData(uint time_win); + const QMap& GetAntiConformEnergyData(); + const QString& GetAntiConformEnergyData(uint time_win); const QString GetAnalysisCustomData(AnalysisType analysis_type, const QString& data_item_name); void SetDeviceGuid(const QString& device_guid); @@ -96,6 +102,9 @@ private: QString _particle_energy_data_filename; QMap > _time_win_conform_particle_data; QMap > _time_win_conform_energy_data; + QMap _anti_conform_particle_data; + QMap _anti_conform_energy_data; + QMap > _analysis_custom_data_set; QString _device_guid; @@ -160,6 +169,7 @@ private slots: 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); + void onEnergyScaleAntiCoincidenceDataFinished(bool ok, const QString& project_name, const QVariant& data); signals: void removedProjectModel(const QString& project_name); diff --git a/src/MeasureAnalysisTreeView.cpp b/src/MeasureAnalysisTreeView.cpp index e554378..460de7f 100644 --- a/src/MeasureAnalysisTreeView.cpp +++ b/src/MeasureAnalysisTreeView.cpp @@ -269,6 +269,13 @@ void MeasureAnalysisTreeView::onNodeDoubleClicked(const QModelIndex& index) } } } break; + case AnalysisType::AntiCoincidenceSpectrumView: { + MeasureAnalysisProjectModel* project_model = _model->GetProjectModel(project_name); + if (project_model) { + auto file_name = project_model->GetAntiConformEnergyData(project_model->GetConformTimeWin()); + data_files_set[QStringLiteral(u"反符合粒子数据")] = file_name; + } + } break; default: break; } diff --git a/src/MeasureAnalysisView.cpp b/src/MeasureAnalysisView.cpp index 66708cd..de1c907 100644 --- a/src/MeasureAnalysisView.cpp +++ b/src/MeasureAnalysisView.cpp @@ -10,6 +10,7 @@ #include "ParticleTimeDifferenceView.h" #include "TwoDSpectralCompliance.h" #include "ConformToTheEnergySpectrum.h" +#include "AntiConformEnergySpectrumView.h" #include MeasureAnalysisView* MeasureAnalysisView::NewAnalyzeView(AnalysisType view_type) @@ -101,8 +102,8 @@ MeasureAnalysisView* MeasureAnalysisView::NewAnalyzeView(AnalysisType view_type) new_view->setDeleteOnClose(false); } break; case AnalysisType::AntiCoincidenceSpectrumView: { - // new_view = new MeasureAnalysisDataTableView; - // new_view->setDeleteOnClose(false); + new_view = new AntiConformEnergySpectrumView; + new_view->setDeleteOnClose(false); } break; default: break; diff --git a/src/src.pro b/src/src.pro index da43669..5a06ce5 100644 --- a/src/src.pro +++ b/src/src.pro @@ -8,7 +8,6 @@ msvc { QMAKE_CXXFLAGS += /utf-8 } - include($${PWD}/../Common.pri) include($${PROJECT_DIR}/3rdlib/QsLog/QsLog.pri) include($${PROJECT_DIR}/3rdlib/QtAdvancedDockingSystem/ads.pri) @@ -38,8 +37,8 @@ INCLUDEPATH += \ $${PWD}/DeviceParameterConfig \ $${PWD}/2DSpectralCompliance \ $${PWD}/ConformToTheEnergySpectrum \ - $${PWD}/NuclideLib - + $${PWD}/NuclideLib \ + $${PWD}/AntiConformEnergySpectrumView DEPENDPATH += \ $${PWD}/BusyIndicator \ @@ -57,11 +56,8 @@ DEPENDPATH += \ $${PWD}/DeviceParameterConfig \ $${PWD}/2DSpectralCompliance \ $${PWD}/ConformToTheEnergySpectrum \ - $${PWD}/NuclideLib - - - - + $${PWD}/NuclideLib \ + $${PWD}/AntiConformEnergySpectrumView SOURCES += \ 2DSpectralCompliance/TwoDSpectralCompliance.cpp \ @@ -104,6 +100,7 @@ SOURCES += \ EnergyCountPeakFitView/EnergyCountPeakFitView.cpp \ ConformToTheEnergySpectrum/ConformToTheEnergySpectrum.cpp \ NuclideLib/NuclideLib.cpp \ + AntiConformEnergySpectrumView/AntiConformEnergySpectrumView.cpp \ main.cpp HEADERS += \ @@ -149,10 +146,8 @@ HEADERS += \ ThreeDimensionalConformityAnalysisView/ThreeDDisplay.h \ EnergyCountPeakFitView/EnergyCountPeakFitView.h \ ConformToTheEnergySpectrum/ConformToTheEnergySpectrum.h \ - NuclideLib/NuclideLib.h - - - + NuclideLib/NuclideLib.h \ + AntiConformEnergySpectrumView/AntiConformEnergySpectrumView.h FORMS += \ 2DSpectralCompliance/TwoDSpectralCompliance.ui \ @@ -172,7 +167,6 @@ FORMS += \ ThreeDimensionalConformityAnalysisView/ConformityAnalysis.ui \ NuclideLib/NuclideLib.ui - DEFINES += ENABLE_DEBUG contains(DEFINES, ENABLE_DEBUG) { CONFIG += console