1、添加反符合能谱;2、修改部分BUG

This commit is contained in:
徐海 2026-05-09 15:00:14 +08:00
parent 664b115aaa
commit 1c0e8569e5
13 changed files with 438 additions and 27 deletions

View File

@ -0,0 +1,158 @@
#include "AntiConformEnergySpectrumView.h"
#include <QVBoxLayout>
#include <QwtPlotCurve>
#include <QwtPlotCanvas>
#include <QwtText>
#include "CustomQwtPlot.h"
#include <GlobalDefine.h>
#include "csv.h"
#include <QFileInfo>
#include <QThread>
#include "BusyIndicator.h"
#include <map>
#include <vector>
#include <algorithm>
#include <cstdint>
#include <QPen>
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<QwtPlotCanvas*>(_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<QString, QVariant> &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<SpectrumData> 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<int, double> hist;
for (const auto& spdt : rawData) {
int idx = static_cast<int>(spdt.energy) / STEP;
hist[idx] += 1.0;
}
QVector<double> 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();
}
}

View File

@ -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<QString, QVariant>& 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

View File

@ -106,9 +106,6 @@ private:
}; };
QColor getDistinctColorForManyCurves(int curve_index); QColor getDistinctColorForManyCurves(int curve_index);
#endif // CUSTOMQWTPLOT_H #endif // CUSTOMQWTPLOT_H

View File

@ -178,6 +178,7 @@ void SortDataByTimestamp(std::vector<SpectrumData>& data)
bool ProcessCoincidence( bool ProcessCoincidence(
std::vector<SpectrumData>& data, std::vector<SpectrumData>& data,
std::vector<CoincidenceEvent>& events, std::vector<CoincidenceEvent>& events,
std::vector<AntiCoincidenceEvent>& anti_coincidence_events,
unsigned int time_window, unsigned int time_window,
int min_order, int min_order,
int max_order int max_order
@ -187,8 +188,13 @@ bool ProcessCoincidence(
if (n < min_order) { if (n < min_order) {
return false; return false;
} }
if (min_order < 2 || max_order < min_order)
return false;
std::vector<bool> is_used(n, false);
// 使用滑动窗口寻找符合事件 // 使用滑动窗口寻找符合事件
for (int i = 0; i < n; ++i) { for (int i = 0; i < n; ++i) {
if (is_used[i])
continue;
std::vector<SpectrumData> current_coincidence; std::vector<SpectrumData> current_coincidence;
current_coincidence.push_back(data[i]); current_coincidence.push_back(data[i]);
// 寻找时间窗口内的其他事件 // 寻找时间窗口内的其他事件
@ -206,6 +212,10 @@ bool ProcessCoincidence(
// 保存符合条件的事件 // 保存符合条件的事件
int coincidence_order = current_coincidence.size(); int coincidence_order = current_coincidence.size();
if (coincidence_order >= min_order && coincidence_order <= max_order) { if (coincidence_order >= min_order && coincidence_order <= max_order) {
// 标记这些事件已被使用
for (int k = 0; k < coincidence_order; ++k) {
is_used[i + k] = true;
}
CoincidenceEvent result; CoincidenceEvent result;
result.coincidence_order = coincidence_order; result.coincidence_order = coincidence_order;
result.events = current_coincidence; result.events = current_coincidence;
@ -213,6 +223,31 @@ bool ProcessCoincidence(
events.push_back(result); 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; return true;
} }

View File

@ -28,6 +28,11 @@ namespace F2t9Order {
std::vector<SpectrumData> events; // 符合的事件集合 std::vector<SpectrumData> events; // 符合的事件集合
unsigned int time_window; // 使用的时间窗口(秒) unsigned int time_window; // 使用的时间窗口(秒)
}; };
// 反符合事件结构体(只包含未参与任何符合的独立事件)
struct AntiCoincidenceEvent {
SpectrumData event; // 反符合单事件
unsigned int time_window; // 时间窗口
};
// 读取CSV数据文件 // 读取CSV数据文件
std::vector<SpectrumData> ReadCsv(const std::string& filename); std::vector<SpectrumData> ReadCsv(const std::string& filename);
@ -39,6 +44,7 @@ namespace F2t9Order {
bool ProcessCoincidence( bool ProcessCoincidence(
std::vector<SpectrumData> &data, std::vector<SpectrumData> &data,
std::vector<CoincidenceEvent> &events, std::vector<CoincidenceEvent> &events,
std::vector<AntiCoincidenceEvent>& anti_coincidence_events,
unsigned int time_window, // 时间窗口(纳秒) unsigned int time_window, // 时间窗口(纳秒)
int min_order = 2, // 最小符合次数 int min_order = 2, // 最小符合次数
int max_order = 9 // 最大符合次数 int max_order = 9 // 最大符合次数

View File

@ -466,6 +466,7 @@ bool CoincidenceEventAnalysisTask::processTask()
if (particle_data_filename.isEmpty()) { if (particle_data_filename.isEmpty()) {
return false; return false;
} }
std::string time_win_str = QString(QStringLiteral(u"时间窗口")).toStdString();
std::string event_id_str = QString(QStringLiteral(u"事件ID")).toStdString(); std::string event_id_str = QString(QStringLiteral(u"事件ID")).toStdString();
std::string board_id_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 channel_id_str = QString(QStringLiteral(u"通道号")).toStdString();
@ -490,8 +491,9 @@ bool CoincidenceEventAnalysisTask::processTask()
spec_data_item.timestamp)) { spec_data_item.timestamp)) {
spec_data.push_back(spec_data_item); spec_data.push_back(spec_data_item);
} }
std::vector<CoincidenceEvent> events; std::vector<CoincidenceEvent> coincidence_events;
if (!ProcessCoincidence(spec_data, events, project_model->GetConformTimeWin())) { std::vector<AntiCoincidenceEvent> anti_coincidence_events;
if (!ProcessCoincidence(spec_data, coincidence_events, anti_coincidence_events, project_model->GetConformTimeWin())) {
LOG_WARN(QStringLiteral(u"粒子符合数据处理异常!")); LOG_WARN(QStringLiteral(u"粒子符合数据处理异常!"));
} }
const QString& coincidence_data_dir_name = 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); const QString& coincidence_data_dir_path = project_dir.filePath(coincidence_data_dir_name);
QMap<int, std::shared_ptr<std::ofstream> > coincidence_data_out_stream_map; QMap<int, std::shared_ptr<std::ofstream> > coincidence_data_out_stream_map;
unsigned long long event_id = 0; unsigned long long event_id = 0;
for (const CoincidenceEvent& event : events) { for (const CoincidenceEvent& event : coincidence_events) {
++ event_id; ++ 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)); 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) ) { 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); 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) { } catch (const std::exception& e) {
const QString& e_what = QString::fromUtf8(e.what()); const QString& e_what = QString::fromUtf8(e.what());
LOG_WARN(QStringLiteral(u"粒子符合数据处理异常:%1").arg(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); conformParticleDataEnergyScale(time_win, coincidence_order, conform_particle_data_filename);
} }
} }
const QString& info = QStringLiteral(u"符合能谱数据处理完成."); const QString& info = QStringLiteral(u"符合能谱数据处理完成.");
LOG_INFO(info); LOG_INFO(info);
return true; 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;
}

View File

@ -143,6 +143,12 @@ namespace DataProcessWorkPool
private: private:
virtual bool processTask() override; virtual bool processTask() override;
}; };
class EnergyScaleaAntiCoincidenceDataTask : public DataProcessTask
{
private:
virtual bool processTask() override;
};
} }
#endif // DATAPROCESSWORKPOOL_H #endif // DATAPROCESSWORKPOOL_H

View File

@ -10,7 +10,7 @@
// 转换Qt字符串路径为系统编码的C字符串解决中文路径问题 // 转换Qt字符串路径为系统编码的C字符串解决中文路径问题
static const char* QStrToSysPath(const QString& qstr_path) static const char* QStrToSysPath(const QString& qstr_path)
{ {
static std::string sys_path; // 静态变量避免内存释放 std::string sys_path; // 静态变量避免内存释放
#ifdef Q_OS_WIN #ifdef Q_OS_WIN
// Windows转为GBK编码 // Windows转为GBK编码
QTextCodec* gbkCodec = QTextCodec::codecForName("GBK"); QTextCodec* gbkCodec = QTextCodec::codecForName("GBK");

View File

@ -113,6 +113,16 @@ void MeasureAnalysisProjectModel::SetTimeWinConformEnergyData(uint time_win, uin
this->_time_win_conform_energy_data[time_win][conform_particle_count] = filename; 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) 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; this->_analysis_custom_data_set[analysis_type][data_item_name] = data_filename;
@ -259,6 +269,26 @@ const QMap<uint, QString> MeasureAnalysisProjectModel::GetTimeWinConformEnergyDa
return conform_energy_data; return conform_energy_data;
} }
const QMap<uint, QString> &MeasureAnalysisProjectModel::GetAntiConformParticleData()
{
return _anti_conform_particle_data;
}
const QString &MeasureAnalysisProjectModel::GetAntiConformParticleData(uint time_win)
{
return _anti_conform_particle_data.value(time_win);
}
const QMap<uint, QString> &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) 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); 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; 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; return true;
} }
@ -473,6 +513,18 @@ bool MeasureAnalysisProjectModel::SaveProjectModel()
} }
project_json_obj_map["TimeWinConformEnergyData"] = time_win_conform_energy_data; 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文件 // 将项目模型保存到json文件
QJsonDocument json_doc = QJsonDocument::fromVariant(project_json_obj_map); QJsonDocument json_doc = QJsonDocument::fromVariant(project_json_obj_map);
QFile json_file(this->_project_filename); QFile json_file(this->_project_filename);
@ -743,6 +795,10 @@ void MeasureAnalysisProjectModelList::ApplyEnergyScale(const QString &project_na
auto coincidence_process_task = new DataProcessWorkPool::EnergyScaleCoincidenceDataTask; auto coincidence_process_task = new DataProcessWorkPool::EnergyScaleCoincidenceDataTask;
coincidence_process_task->SetFinishedNotifier(this, "onEnergyScaleCoincidenceDataFinished", project_name); coincidence_process_task->SetFinishedNotifier(this, "onEnergyScaleCoincidenceDataFinished", project_name);
coincidence_process_task->StartTask(); 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]; auto energy_total_count_spec_item = node_map[item_name];
this->SetNodeStatus(energy_total_count_spec_item, status, status_ok); 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); 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 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) void MeasureAnalysisProjectModelList::intiProjectNodeStruce(MeasureAnalysisProjectModel* pro_model)
{ {
if (!pro_model) { if (!pro_model) {

View File

@ -39,6 +39,8 @@ public:
void SetParticleEnergyDataFilename(const QString& filename); void SetParticleEnergyDataFilename(const QString& filename);
void SetTimeWinConformParticleData(uint time_win, uint conform_particle_count, 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 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); void SetAnalysisCustomData(AnalysisType analysis_type, const QString& data_item_name, const QString& data_filename);
const QString& GetProjectDir() const; const QString& GetProjectDir() const;
@ -63,6 +65,10 @@ public:
const QMap<uint, QString> GetTimeWinConformParticleDataFilenameList(uint time_win) const; const QMap<uint, QString> GetTimeWinConformParticleDataFilenameList(uint time_win) const;
const QMap<uint, QMap<uint, QString> > GetConformParticleEnergyDataFilenameList() const; const QMap<uint, QMap<uint, QString> > GetConformParticleEnergyDataFilenameList() const;
const QMap<uint, QString> GetTimeWinConformEnergyDataFilenameList(uint time_win) const; const QMap<uint, QString> GetTimeWinConformEnergyDataFilenameList(uint time_win) const;
const QMap<uint, QString>& GetAntiConformParticleData();
const QString& GetAntiConformParticleData(uint time_win);
const QMap<uint, QString>& GetAntiConformEnergyData();
const QString& GetAntiConformEnergyData(uint time_win);
const QString GetAnalysisCustomData(AnalysisType analysis_type, const QString& data_item_name); const QString GetAnalysisCustomData(AnalysisType analysis_type, const QString& data_item_name);
void SetDeviceGuid(const QString& device_guid); void SetDeviceGuid(const QString& device_guid);
@ -96,6 +102,9 @@ private:
QString _particle_energy_data_filename; QString _particle_energy_data_filename;
QMap<uint, QMap<uint, QString> > _time_win_conform_particle_data; QMap<uint, QMap<uint, QString> > _time_win_conform_particle_data;
QMap<uint, QMap<uint, QString> > _time_win_conform_energy_data; QMap<uint, QMap<uint, QString> > _time_win_conform_energy_data;
QMap<uint, QString> _anti_conform_particle_data;
QMap<uint, QString> _anti_conform_energy_data;
QMap<AnalysisType, QMap<QString, QString> > _analysis_custom_data_set; QMap<AnalysisType, QMap<QString, QString> > _analysis_custom_data_set;
QString _device_guid; QString _device_guid;
@ -160,6 +169,7 @@ private slots:
void onEnergyCountProcessFinished(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 onCoincidenceProcessFinished(bool ok, const QString& project_name, const QVariant& data);
void onEnergyScaleCoincidenceDataFinished(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: signals:
void removedProjectModel(const QString& project_name); void removedProjectModel(const QString& project_name);

View File

@ -269,6 +269,13 @@ void MeasureAnalysisTreeView::onNodeDoubleClicked(const QModelIndex& index)
} }
} }
} break; } 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: default:
break; break;
} }

View File

@ -10,6 +10,7 @@
#include "ParticleTimeDifferenceView.h" #include "ParticleTimeDifferenceView.h"
#include "TwoDSpectralCompliance.h" #include "TwoDSpectralCompliance.h"
#include "ConformToTheEnergySpectrum.h" #include "ConformToTheEnergySpectrum.h"
#include "AntiConformEnergySpectrumView.h"
#include <QMap> #include <QMap>
MeasureAnalysisView* MeasureAnalysisView::NewAnalyzeView(AnalysisType view_type) MeasureAnalysisView* MeasureAnalysisView::NewAnalyzeView(AnalysisType view_type)
@ -101,8 +102,8 @@ MeasureAnalysisView* MeasureAnalysisView::NewAnalyzeView(AnalysisType view_type)
new_view->setDeleteOnClose(false); new_view->setDeleteOnClose(false);
} break; } break;
case AnalysisType::AntiCoincidenceSpectrumView: { case AnalysisType::AntiCoincidenceSpectrumView: {
// new_view = new MeasureAnalysisDataTableView; new_view = new AntiConformEnergySpectrumView;
// new_view->setDeleteOnClose(false); new_view->setDeleteOnClose(false);
} break; } break;
default: default:
break; break;

View File

@ -8,7 +8,6 @@ msvc {
QMAKE_CXXFLAGS += /utf-8 QMAKE_CXXFLAGS += /utf-8
} }
include($${PWD}/../Common.pri) include($${PWD}/../Common.pri)
include($${PROJECT_DIR}/3rdlib/QsLog/QsLog.pri) include($${PROJECT_DIR}/3rdlib/QsLog/QsLog.pri)
include($${PROJECT_DIR}/3rdlib/QtAdvancedDockingSystem/ads.pri) include($${PROJECT_DIR}/3rdlib/QtAdvancedDockingSystem/ads.pri)
@ -38,8 +37,8 @@ INCLUDEPATH += \
$${PWD}/DeviceParameterConfig \ $${PWD}/DeviceParameterConfig \
$${PWD}/2DSpectralCompliance \ $${PWD}/2DSpectralCompliance \
$${PWD}/ConformToTheEnergySpectrum \ $${PWD}/ConformToTheEnergySpectrum \
$${PWD}/NuclideLib $${PWD}/NuclideLib \
$${PWD}/AntiConformEnergySpectrumView
DEPENDPATH += \ DEPENDPATH += \
$${PWD}/BusyIndicator \ $${PWD}/BusyIndicator \
@ -57,11 +56,8 @@ DEPENDPATH += \
$${PWD}/DeviceParameterConfig \ $${PWD}/DeviceParameterConfig \
$${PWD}/2DSpectralCompliance \ $${PWD}/2DSpectralCompliance \
$${PWD}/ConformToTheEnergySpectrum \ $${PWD}/ConformToTheEnergySpectrum \
$${PWD}/NuclideLib $${PWD}/NuclideLib \
$${PWD}/AntiConformEnergySpectrumView
SOURCES += \ SOURCES += \
2DSpectralCompliance/TwoDSpectralCompliance.cpp \ 2DSpectralCompliance/TwoDSpectralCompliance.cpp \
@ -104,6 +100,7 @@ SOURCES += \
EnergyCountPeakFitView/EnergyCountPeakFitView.cpp \ EnergyCountPeakFitView/EnergyCountPeakFitView.cpp \
ConformToTheEnergySpectrum/ConformToTheEnergySpectrum.cpp \ ConformToTheEnergySpectrum/ConformToTheEnergySpectrum.cpp \
NuclideLib/NuclideLib.cpp \ NuclideLib/NuclideLib.cpp \
AntiConformEnergySpectrumView/AntiConformEnergySpectrumView.cpp \
main.cpp main.cpp
HEADERS += \ HEADERS += \
@ -149,10 +146,8 @@ HEADERS += \
ThreeDimensionalConformityAnalysisView/ThreeDDisplay.h \ ThreeDimensionalConformityAnalysisView/ThreeDDisplay.h \
EnergyCountPeakFitView/EnergyCountPeakFitView.h \ EnergyCountPeakFitView/EnergyCountPeakFitView.h \
ConformToTheEnergySpectrum/ConformToTheEnergySpectrum.h \ ConformToTheEnergySpectrum/ConformToTheEnergySpectrum.h \
NuclideLib/NuclideLib.h NuclideLib/NuclideLib.h \
AntiConformEnergySpectrumView/AntiConformEnergySpectrumView.h
FORMS += \ FORMS += \
2DSpectralCompliance/TwoDSpectralCompliance.ui \ 2DSpectralCompliance/TwoDSpectralCompliance.ui \
@ -172,7 +167,6 @@ FORMS += \
ThreeDimensionalConformityAnalysisView/ConformityAnalysis.ui \ ThreeDimensionalConformityAnalysisView/ConformityAnalysis.ui \
NuclideLib/NuclideLib.ui NuclideLib/NuclideLib.ui
DEFINES += ENABLE_DEBUG DEFINES += ENABLE_DEBUG
contains(DEFINES, ENABLE_DEBUG) { contains(DEFINES, ENABLE_DEBUG) {
CONFIG += console CONFIG += console