对峰拟合分析进行修改,新增核素库新增核素信息,新增射线信息,修改核素信息,修改射线信息

This commit is contained in:
anxinglong 2026-05-09 16:50:34 +08:00
parent a27195899a
commit 36f9f7ad32
22 changed files with 2084 additions and 388 deletions

Binary file not shown.

View File

@ -22,6 +22,9 @@
#include <QLineEdit>
#include <QMouseEvent>
#include <QSet>
#include "BusyIndicator.h"
#include <QThread>
class HeatMapColorMap : public QwtLinearColorMap
{
public:
@ -45,6 +48,8 @@ TwoDSpectralCompliance::TwoDSpectralCompliance(QWidget *parent) :
layout->addWidget(this->_plot);
setupPlot();
createFloatingInfoWidget();
_busy_indicator = new BusyIndicator(this);
}
TwoDSpectralCompliance::~TwoDSpectralCompliance()
@ -64,10 +69,15 @@ void TwoDSpectralCompliance::SetAnalyzeDataFilename(const QMap<QString, QVariant
QString csvFile = data_files_set.first().toString();
if (csvFile.isEmpty())
return;
auto functionToRun = [this, csvFile](){
_busy_indicator->Start();
readCsv(csvFile);
generateSurfaceData();
updateSpectrogram();
_busy_indicator->Stop();
};
QThread* load_data_thread = QThread::create(functionToRun);
load_data_thread->start();
}
@ -432,3 +442,12 @@ bool TwoDSpectralCompliance::eventFilter(QObject *obj, QEvent *event)
}
return QWidget::eventFilter(obj, event);
}
void TwoDSpectralCompliance::showEvent(QShowEvent *e)
{
Q_UNUSED(e);
if (_busy_indicator) {
_busy_indicator->setGeometry(this->rect());
this->update();
}
}

View File

@ -11,6 +11,7 @@ class QwtPlotSpectrogram;
class QPushButton;
class QLineEdit;
class ScatterPlotItem;
class BusyIndicator;
namespace Ui {
class TwoDSpectralCompliance;
}
@ -34,6 +35,7 @@ public:
protected:
void resizeEvent(QResizeEvent *event) override;
bool eventFilter(QObject *obj, QEvent *event) override;
virtual void showEvent(QShowEvent* e) override final;
private:
void setupPlot();
@ -80,6 +82,8 @@ private:
QPoint m_dragPosition;
bool m_dragging = false;
BusyIndicator* _busy_indicator = nullptr;
};
#endif // TWODSPECTRALCOMPLIANCE_H

View File

@ -15,6 +15,8 @@
#include <QDebug>
#include <GlobalDefine.h>
#include "csv.h"
#include <QThread>
#include "BusyIndicator.h"
CountRateAnalysisView::CountRateAnalysisView(QWidget *parent) :
MeasureAnalysisView(parent),
@ -24,6 +26,7 @@ CountRateAnalysisView::CountRateAnalysisView(QWidget *parent) :
this->setViewType(PlotFrame);
InitUi();
_busy_indicator = new BusyIndicator(this);
}
@ -36,13 +39,28 @@ void CountRateAnalysisView::InitViewWorkspace(const QString &project_name)
{
}
void CountRateAnalysisView::SetAnalyzeDataFilename(const QMap<QString, QVariant> &data_files_set)
{
if(!data_files_set.isEmpty())
{
m_AllData = getParticleInjectTimeData(data_files_set.first().toString());
setData(m_AllData);
auto functionToRun = [this,data_files_set]
{
_busy_indicator->Start();
m_AllData = getParticleInjectTimeData(data_files_set.first().toString());
setData(m_AllData);
_busy_indicator->Stop();
};
QThread* load_data_thread = QThread::create(functionToRun);
load_data_thread->start();
}
}
void CountRateAnalysisView::showEvent(QShowEvent *e)
{
Q_UNUSED(e);
if (_busy_indicator) {
_busy_indicator->setGeometry(this->rect());
this->update();
}
}
@ -119,7 +137,6 @@ QVector<ParticleInjectTime> CountRateAnalysisView::getParticleInjectTimeData(QSt
rec.dTime = time_count;
records.append(rec);
}
return records;
return records;
}

View File

@ -7,6 +7,8 @@
#include "MeasureAnalysisView.h"
class CustomQwtPlot;
class BusyIndicator;
namespace Ui {
class CountRateAnalysisView;
@ -23,6 +25,8 @@ public:
virtual void InitViewWorkspace(const QString& project_name) override final;
virtual void SetAnalyzeDataFilename(const QMap<QString, QVariant>& data_files_set);
protected:
virtual void showEvent(QShowEvent* e) override final;
void setData(QVector<ParticleInjectTime> data);
//获取数据
@ -33,8 +37,10 @@ private:
private:
Ui::CountRateAnalysisView *ui;
BusyIndicator* _busy_indicator = nullptr;
CustomQwtPlot *plot;
QVector<ParticleInjectTime> m_AllData;//存储的所有的粒子入射时间数据
};
#endif //COUNTRATEANALYSIS_H

File diff suppressed because it is too large Load Diff

View File

@ -27,22 +27,45 @@ struct PeakFitResult
double baseline; // 常数项 C
double sigmoidH; // Sigmoid 项高度 H
double sigmoidW; // Sigmoid 项宽度 W
};
struct PeakFitHistoryItem {
QDateTime timestamp; // 时间戳
double center; // 峰中心能量 (keV)
double fwhm; // 半高宽
double area; // 峰面积
double amplitude; // 幅度 A
double sigma; // 标准差 delt
double sigmoidH; // H
double sigmoidW; // W
double baseline; // C
double xMin; // 拟合曲线显示范围左边界
double xMax; // 拟合曲线显示范围右边界
};
QJsonObject toJson() const;
static PeakFitHistoryItem fromJson(const QJsonObject& obj);
struct FitCurveData {
double amplitude; // 峰幅度
double sigma; // 高斯sigma
double sigmoidH; // Sigmoid高度
double sigmoidW; // Sigmoid宽度
double baseline; // 本底
double center; // 峰中心
double xMin; // 曲线X范围最小值
double xMax; // 曲线X范围最大值
QRectF selectionRect; //关联的框选区域
double fwhm; // 半高宽
double area; // 峰面积
};
struct PeakFitHistoryItem {
QDateTime timestamp;
QList<FitCurveData> curveList; //存储多条曲线
QJsonObject toJson() const;
static PeakFitHistoryItem fromJson(const QJsonObject& obj);
};
struct CurrentFitRecord {
PeakFitResult result; // 拟合结果
arma::vec params; // 完整拟合参数
double xMin; // X范围最小值
double xMax; // X范围最大值
int historyIndex; // 对应_fitHistoryList中的索引-1表示未保存
CurrentFitRecord() : historyIndex(-1) {} // 构造函数初始化
};
struct DisplayedCurveRef {
int historyIndex; // 对应 _fitHistoryList 的索引
int curveIndex; // 对应 curveList 的索引
int curveStartIndex; //对应 _fitCurves 中的起始索引一条历史曲线对应2条Qwt曲线拟合+本底)
int rectIndex; //对应 _selectionRectItems 中的索引
};
class PlotRectItem; // 前向声明
@ -51,6 +74,7 @@ class CustomQwtPlot;
class CustomQwtPlotXaxisSelector;
class QwtPlotPicker;
class QwtPlotCurve;
class BusyIndicator;
class EnergyCountPeakFitView : public MeasureAnalysisView
{
@ -72,16 +96,21 @@ private:
void saveHistoryToFile();
void saveCurrentFitToHistory(); // 保存当前拟合结果
void displayFitFromHistory(const PeakFitHistoryItem& item); // 显示历史拟合曲线
//处理鼠标悬停检测
void updateHoverState(const QPoint& mousePos);
//显示选中的曲线
void displaySelectedCurves(const QList<FitCurveData>& curves, const QList<DisplayedCurveRef>& refs);
private slots:
void onActionCurveShowSetting();
void onActionPlotConfigure();
void clearAllSelectionRects();
void clearFitCurves(); // 清除所有拟合曲线
// [NEW] 新增菜单槽函数
void onActionSaveCurrentFit();
void onActionShowFitHistory();
void onActionSaveCurrentFit();
void onActionShowFitHistory();
void onActionDeleteHoveredRect();
//重新拟合当前悬停的框选区域
void onActionRefitCurrentRect();
protected:
bool eventFilter(QObject* watched, QEvent* event) override; // 事件过滤器
@ -92,9 +121,12 @@ private:
void addSelectionRect(const QRectF& plotRect);
void fadeSelectionRectBorders();
QList<PeakFitResult> performPeakFitting(const QVector<double>& x, const QVector<double>& y, const arma::vec* userP0 = nullptr);
QList<PeakFitResult> performPeakFitting(const QVector<double>& x, const QVector<double>& y/*, const arma::vec* userP0 = nullptr*/);
// 根据拟合参数生成曲线
QwtPlotCurve* createFitCurve(const PeakFitResult& result, double xMin, double xMax, const QString& name);
QList<QwtPlotCurve*> createFitCurve(const PeakFitResult& result, arma::vec xVec);
private:
CustomQwtPlot* _plot = nullptr;
QMenu* _menu = nullptr;
@ -112,8 +144,7 @@ private:
QList<QwtPlotCurve*> _fitCurves;
// [NEW] 历史记录相关成员
QList<PeakFitHistoryItem> _fitHistoryList;
QString _historyFilePath;
// [NEW] 最近一次拟合结果(用于手动保存)
@ -123,6 +154,14 @@ private:
bool _hasLastFit = false;
QString _workspace;
//存储当前所有拟合结果(用于多曲线管理)
QList<CurrentFitRecord> _currentFitRecords;
//历史记录列表
QList<PeakFitHistoryItem> _fitHistoryList;
//当前悬停的框选区域
PlotRectItem* _hoveredRectItem = nullptr;
QList<DisplayedCurveRef> _displayedHistoryCurves;
};
#endif // ENERGYCOUNTPEAKFITVIEW_H

View File

@ -2,23 +2,63 @@
#include <QPainter>
#include <QwtScaleMap>
PlotRectItem::PlotRectItem(const QString &title)
: QwtPlotItem() {
: QwtPlotItem(), m_isHovered(false), m_hasPeakData(false)
,m_selectionType(""), m_selectionIndex(-1)
{
setTitle(title);
setZ(1000);
m_pen = QPen(Qt::red, 2, Qt::SolidLine);
// 初始化普通状态画笔红色虚线线宽2
m_normalPen = QPen(Qt::red, 2, Qt::DashLine);
// 初始化悬停状态画笔红色实线线宽2
m_hoverPen = QPen(Qt::red, 2, Qt::SolidLine);
m_brush = QBrush(QColor(255, 0, 0, 30));
}
void PlotRectItem::setRect(const QRectF &rect) {
m_rect = rect;
itemChanged(); // 触发重绘
}
void PlotRectItem::setPen(const QPen &pen) {
m_pen = pen;
m_normalPen = pen;
// 同步悬停画笔的颜色和宽度,仅改变线型
m_hoverPen = pen;
m_hoverPen.setStyle(Qt::SolidLine);
itemChanged();
}
void PlotRectItem::setBrush(const QBrush &brush) {
m_brush = brush;
itemChanged();
}
//设置悬停状态
void PlotRectItem::setHovered(bool hovered) {
if (m_isHovered != hovered) {
m_isHovered = hovered;
itemChanged(); // 触发重绘
}
}
//获取悬停状态
bool PlotRectItem::isHovered() const {
return m_isHovered;
}
//获取矩形区域
QRectF PlotRectItem::rect() const {
return m_rect;
}
void PlotRectItem::setPeakData(double center, double fwhm, double area, double baseline)
{
m_hasPeakData = true;
m_peakCenter = center;
m_fwhm = fwhm;
m_peakArea = area;
m_baseline = baseline;
itemChanged(); // 触发重绘
}
void PlotRectItem::draw(QPainter *painter,
@ -31,10 +71,45 @@ void PlotRectItem::draw(QPainter *painter,
const QRect rect(QPoint(x1, y1), QPoint(x2, y2));
painter->save();
painter->setPen(m_pen);
// 根据悬停状态选择画笔
painter->setPen(m_isHovered ? m_hoverPen : m_normalPen);
painter->setBrush(m_brush);
painter->drawRect(rect);
painter->restore();
if (m_hasPeakData) {
painter->save();
painter->setRenderHint(QPainter::TextAntialiasing);
// 构建文本内容
QString text = QString("峰位: %1 keV\n"
"FWHM: %2\n"
"面积: %3\n"
"本底: %4")
.arg(m_peakCenter, 0, 'f', 2)
.arg(m_fwhm, 0, 'f', 2)
.arg(m_peakArea, 0, 'f', 2)
.arg(m_baseline, 0, 'f', 2);
// 计算文本位置:矩形右上角 + 偏移量
QPoint textPos(x2 + 10, y2);
// 绘制半透明背景框(增强可读性)
QFont font = painter->font();
font.setPointSize(9); // 稍微小一点
painter->setFont(font);
QFontMetrics fm(font);
QRect textRect = fm.boundingRect(QRect(0, 0, 1, 1), Qt::AlignLeft, text);
textRect.moveTopLeft(textPos);
textRect.adjust(-5, -3, 5, 3); // 增加边距
painter->fillRect(textRect, QColor(255, 255, 255, 220)); // 白底微透
painter->setPen(Qt::black);
painter->drawText(textRect, Qt::AlignLeft, text);
painter->restore();
}
}
QRectF PlotRectItem::boundingRect() const {

View File

@ -13,16 +13,42 @@ public:
void setPen(const QPen &pen);
void setBrush(const QBrush &brush);
//设置/获取悬停状态
void setHovered(bool hovered);
bool isHovered() const;
//获取当前矩形区域(用于碰撞检测)
QRectF rect() const;
//设置要显示的峰拟合数据
void setPeakData(double center, double fwhm, double area, double baseline);
void setSelectionType(const QString& type) { m_selectionType = type; }
QString selectionType() const { return m_selectionType; }
void setSelectionIndex(int index) { m_selectionIndex = index; }
int selectionIndex() const { return m_selectionIndex; }
virtual void draw(QPainter *painter,
const QwtScaleMap &xMap, const QwtScaleMap &yMap,
const QRectF &canvasRect) const override;
virtual QRectF boundingRect() const override;
private:
QRectF m_rect;
QPen m_pen;
QPen m_normalPen; //普通状态画笔(虚线)
QPen m_hoverPen; //悬停状态画笔(实线)
QBrush m_brush;
bool m_isHovered; //悬停状态标志
bool m_hasPeakData;
double m_peakCenter;
double m_fwhm;
double m_peakArea;
double m_baseline;
QString m_selectionType; // "current" 或 "history"
int m_selectionIndex; // 对应的索引
};
#endif // PLOTRECTITEM_H

View File

@ -0,0 +1,101 @@
#include "NuclideEditDialog.h"
NuclideEditDialog::NuclideEditDialog(bool isEdit, const QStringList& nuclideData, QWidget *parent)
: QDialog(parent), m_isEdit(isEdit)
{
// 编辑模式下提取ID和已有数据
if (isEdit && !nuclideData.isEmpty()) {
m_id = nuclideData[0]; // 第一个元素是ID
}
initUI();
// 编辑模式:填充已有数据(字段顺序不变,仅数据库字段名修改)
if (isEdit && nuclideData.size() >= 6) {
m_leName->setText(nuclideData[1]);
m_leHalfLife->setText(nuclideData[2]);
m_leHalfLifeUnc->setText(nuclideData[3]);
m_leParentNuclide->setText(nuclideData[4]);
m_leChildNuclide->setText(nuclideData[5]);
}
}
void NuclideEditDialog::initUI()
{
setWindowTitle(m_isEdit ? "编辑核素信息" : "添加核素信息");
setFixedSize(400, 220); // 稍微增加高度适配新校验提示
// 表单布局(控件名称不变,仅数据库映射修改)
QFormLayout *formLayout = new QFormLayout(this);
m_leName = new QLineEdit(this);
m_leHalfLife = new QLineEdit(this);
m_leHalfLifeUnc = new QLineEdit(this);
m_leParentNuclide = new QLineEdit(this);
m_leChildNuclide = new QLineEdit(this);
// 设置表单项(标签不变,用户界面无感知)
formLayout->addRow("核素名称", m_leName);
formLayout->addRow("半衰期", m_leHalfLife);
formLayout->addRow("半衰期不确定度", m_leHalfLifeUnc);
formLayout->addRow("母体核素名称", m_leParentNuclide);
formLayout->addRow("子体核素名称", m_leChildNuclide);
// 按钮盒
QDialogButtonBox *btnBox = new QDialogButtonBox(
QDialogButtonBox::Ok | QDialogButtonBox::Cancel,
Qt::Horizontal, this);
formLayout->addRow(btnBox);
// 信号连接
connect(btnBox, &QDialogButtonBox::accepted, this, [this]() {
if (validateInput()) {
accept();
}
});
connect(btnBox, &QDialogButtonBox::rejected, this, &QDialog::reject);
}
bool NuclideEditDialog::validateInput()
{
// 必填项校验
if (m_leName->text().trimmed().isEmpty()) {
QMessageBox::warning(this, "输入错误", "核素名称不能为空!");
return false;
}
if (m_leHalfLife->text().trimmed().isEmpty()) {
QMessageBox::warning(this, "输入错误", "半衰期不能为空!");
return false;
}
if (m_leHalfLifeUnc->text().trimmed().isEmpty()) {
QMessageBox::warning(this, "输入错误", "半衰期不确定度不能为空!");
return false;
}
bool ok;
// 半衰期校验保留原逻辑TEXT类型可存储带单位的字符串
m_leHalfLife->text().toDouble(&ok);
if (!ok) {
QMessageBox::warning(this, "输入错误", "半衰期必须为数字可带单位如12.5d");
return false;
}
m_leHalfLifeUnc->text().toDouble(&ok);
if (!ok) {
QMessageBox::warning(this, "输入错误", "半衰期不确定度必须为有效数字!");
return false;
}
return true;
}
QStringList NuclideEditDialog::getNuclideData() const
{
QStringList data;
if (m_isEdit) {
data << m_id; // 编辑模式返回ID
}
data << m_leName->text().trimmed()
<< m_leHalfLife->text().trimmed()
<< m_leHalfLifeUnc->text().trimmed()
<< m_leParentNuclide->text().trimmed()
<< m_leChildNuclide->text().trimmed();
return data;
}

View File

@ -0,0 +1,35 @@
#ifndef NUCLIDEEDITDIALOG_H
#define NUCLIDEEDITDIALOG_H
#include <QDialog>
#include <QLineEdit>
#include <QFormLayout>
#include <QDialogButtonBox>
#include <QMessageBox>
class NuclideEditDialog : public QDialog
{
Q_OBJECT
public:
// 构造函数isEdit=true为编辑模式传入已有数据false为添加模式
explicit NuclideEditDialog(bool isEdit = false, const QStringList& nuclideData = {}, QWidget *parent = nullptr);
~NuclideEditDialog() = default;
// 获取用户输入的核素数据编辑模式ID+5个字段添加模式5个字段
QStringList getNuclideData() const;
private:
void initUI(); // 初始化界面
bool validateInput(); // 输入校验(新增半衰期不确定度的数字校验)
QLineEdit *m_leName; // 核素名称对应NUCLIDE_NAME
QLineEdit *m_leHalfLife; // 半衰期对应HALF_LIFE
QLineEdit *m_leHalfLifeUnc; // 半衰期不确定度对应HALF_LIFE_UNCERTAINTY
QLineEdit *m_leParentNuclide; // 母体核素名称对应PARENT_NUCLIDE_NAME
QLineEdit *m_leChildNuclide; // 子体核素名称对应CHILD_NUCLIDE_NAME
bool m_isEdit; // 是否为编辑模式
QString m_id; // 编辑模式下的核素ID
};
#endif // NUCLIDEEDITDIALOG_H

View File

@ -7,7 +7,9 @@
#include <QStyleOptionButton>
#include <QMouseEvent>
#include <QApplication>
#include <QDebug>
#include <QDateTime>
#include "NuclideRayListDialog.h"
ButtonDelegate::ButtonDelegate(QObject *parent) : QStyledItemDelegate(parent) {}
void ButtonDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
@ -62,10 +64,20 @@ NuclideLibManage::NuclideLibManage(QWidget *parent) :
ui->tableView->setSelectionBehavior(QAbstractItemView::SelectRows);
ui->tableView->setFocusPolicy(Qt::NoFocus);
QString dbPath = QCoreApplication::applicationDirPath() + "/nuclideLib.db"; // 绝对路径(推荐)
qDebug()<<dbPath;
bool dbOpened = SqliteManager::instance().openDatabase(dbPath);
if (!dbOpened) {
QMessageBox::critical(this, "数据库错误", "打开数据库失败:" + SqliteManager::instance().lastError());
return;
}
// 设置委托
m_delegate = new ButtonDelegate(this);
ui->tableView->setItemDelegateForColumn(7, m_delegate);
connect(m_delegate, &ButtonDelegate::buttonClicked, this, &NuclideLibManage::onButtonClicked);
loadNuclideData();
}
NuclideLibManage::~NuclideLibManage()
@ -75,45 +87,42 @@ NuclideLibManage::~NuclideLibManage()
void NuclideLibManage::loadNuclideData()
{
QString sql = "SELECT ID, NAME, HALF_LIFE, HALF_LIFE_UNC, PARENT_NUCLIDE, CHILD_NUCLIDE FROM tbl_nuclide_library;";
QString sql = "SELECT ID, NUCLIDE_NAME, HALF_LIFE, HALF_LIFE_UNCERTAINTY, PARENT_NUCLIDE_NAME, CHILD_NUCLIDE_NAME FROM nuclideLib;";
auto rows = SqliteManager::instance().selectRows(sql);
m_listNuclide.clear();
m_model->setRowCount(0);
int row = 0;
for (const auto& rec : rows) {
QStringList item;
item << rec["ID"].toString()
<< rec["NAME"].toString()
<< rec["NUCLIDE_NAME"].toString()
<< rec["HALF_LIFE"].toString()
<< rec["HALF_LIFE_UNC"].toString()
<< rec["PARENT_NUCLIDE"].toString()
<< rec["CHILD_NUCLIDE"].toString();
<< rec["HALF_LIFE_UNCERTAINTY"].toString() // 对应新字段名
<< rec["PARENT_NUCLIDE_NAME"].toString() // 对应新字段名
<< rec["CHILD_NUCLIDE_NAME"].toString(); // 对应新字段名
m_listNuclide.append(item);
// 插入模型行
// 插入模型行(界面显示逻辑不变)
QList<QStandardItem*> rowItems;
// 第0列ID隐藏
QStandardItem *idItem = new QStandardItem(item[0]);
idItem->setTextAlignment(Qt::AlignCenter);
idItem->setFlags(idItem->flags() & ~Qt::ItemIsEditable);
rowItems << idItem;
// 第1列序号行号+1
QStandardItem *seqItem = new QStandardItem(QString::number(row + 1));
seqItem->setTextAlignment(Qt::AlignCenter);
seqItem->setFlags(seqItem->flags() & ~Qt::ItemIsEditable);
rowItems << seqItem;
// 第2~6列核素名称、半衰期等
for (int col = 1; col <= 5; ++col) { // item的下标1~5对应NAME到CHILD_NUCLIDE
for (int col = 1; col <= 5; ++col) {
QStandardItem *dataItem = new QStandardItem(item[col]);
dataItem->setTextAlignment(Qt::AlignCenter);
dataItem->setFlags(dataItem->flags() & ~Qt::ItemIsEditable);
rowItems << dataItem;
}
// 第7列操作列存储空字符串委托负责绘制按钮
// 第7列操作列
QStandardItem *opItem = new QStandardItem("");
opItem->setFlags(opItem->flags() & ~Qt::ItemIsEditable);
rowItems << opItem;
@ -134,7 +143,27 @@ QStringList NuclideLibManage::getNuclideData(const QString &id)
void NuclideLibManage::on_pushButton_add_clicked()
{
loadNuclideData(); // 刷新数据
NuclideEditDialog dlg(false, {}, this);
if (dlg.exec() == QDialog::Accepted) {
QStringList data = dlg.getNuclideData();
if (data.size() < 5) return;
QMap<QString, QVariant> fieldValues;
fieldValues["NUCLIDE_NAME"] = data[0];
fieldValues["HALF_LIFE"] = data[1];
fieldValues["HALF_LIFE_UNCERTAINTY"] = data[2].toDouble(); // 显式转换为REAL类型
fieldValues["PARENT_NUCLIDE_NAME"] = data[3];
fieldValues["CHILD_NUCLIDE_NAME"] = data[4];
fieldValues["CREATE_TIME"] = QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss");
qint64 newId = SqliteManager::instance().insertRow("nuclideLib", fieldValues);
if (newId > 0) {
QMessageBox::information(this, "成功", "核素添加成功!");
loadNuclideData();
} else {
QMessageBox::warning(this, "失败", "添加失败:" + SqliteManager::instance().lastError());
}
}
}
void NuclideLibManage::on_pushButton_edit_clicked()
@ -144,10 +173,40 @@ void NuclideLibManage::on_pushButton_edit_clicked()
QMessageBox::information(this, "提示", "请先选择要修改的核素行!");
return;
}
int row = selected.first().row();
QString id = m_model->index(row, 0).data().toString(); // 隐藏的ID列
QString id = m_model->index(row, 0).data().toString();
QStringList data = getNuclideData(id);
if (data.isEmpty()) return;
NuclideEditDialog dlg(true, data, this);
if (dlg.exec() == QDialog::Accepted) {
QStringList newData = dlg.getNuclideData();
if (newData.size() < 6) return;
QMap<QString, QVariant> fieldValues;
fieldValues["NUCLIDE_NAME"] = newData[1];
fieldValues["HALF_LIFE"] = newData[2];
fieldValues["HALF_LIFE_UNCERTAINTY"] = newData[3].toDouble(); // 显式转换为REAL类型
fieldValues["PARENT_NUCLIDE_NAME"] = newData[4];
fieldValues["CHILD_NUCLIDE_NAME"] = newData[5];
int affectedRows = SqliteManager::instance().updateRow(
"nuclideLib",
fieldValues,
"ID = ?",
{newData[0]}
);
if (affectedRows > 0) {
QMessageBox::information(this, "成功", "核素修改成功!");
loadNuclideData();
} else if (affectedRows == 0) {
QMessageBox::information(this, "提示", "未修改任何数据!");
} else {
QMessageBox::warning(this, "失败", "修改失败:" + SqliteManager::instance().lastError());
}
}
}
void NuclideLibManage::on_pushButton_del_clicked()
@ -157,6 +216,7 @@ void NuclideLibManage::on_pushButton_del_clicked()
QMessageBox::information(this, "提示", "请先选择要删除的核素行!");
return;
}
int row = selected.first().row();
QString id = m_model->index(row, 0).data().toString();
@ -166,7 +226,7 @@ void NuclideLibManage::on_pushButton_del_clicked()
box.button(QMessageBox::No)->setText("取消");
if (box.exec() != QMessageBox::Yes) return;
bool ok = SqliteManager::instance().deleteRow("tbl_nuclide_library", "ID = ?", {id});
bool ok = SqliteManager::instance().deleteRow("nuclideLib", "ID = ?", {id});
if (ok) {
loadNuclideData();
} else {
@ -178,4 +238,10 @@ void NuclideLibManage::onButtonClicked(const QModelIndex &index)
{
int row = index.row();
QString nuclideId = m_model->index(row, 0).data().toString();
QString nuclideName = m_model->index(row, 2).data().toString();
// 打开射线信息管理对话框
NuclideRayListDialog dlg(nuclideId, nuclideName, this);
dlg.exec();
}

View File

@ -6,6 +6,7 @@
#include <QVector>
#include <QStyledItemDelegate>
#include <QStandardItemModel>
#include "NuclideEditDialog.h"
namespace Ui {
class NuclideLibManage;

View File

@ -0,0 +1,133 @@
#include "NuclideRayDialog.h"
NuclideRayDialog::NuclideRayDialog(bool isEdit, const QStringList& rayData, QWidget *parent)
: QDialog(parent), m_isEdit(isEdit)
{
// 编辑模式下提取ID和已有数据
if (isEdit && !rayData.isEmpty()) {
m_id = rayData[0]; // 第一个元素是ID
}
initUI();
// 编辑模式:填充已有数据
if (isEdit && rayData.size() >= 8) {
m_cmbRayType->setCurrentText(rayData[1]);
m_leRayMev->setText(rayData[2]);
m_leRayMevUnc->setText(rayData[3]);
m_leBranchRatio->setText(rayData[4]);
m_leBranchRatioUnc->setText(rayData[5]);
m_cmbMainRayIdent->setCurrentText(rayData[6]);
m_leJiahePeak->setText(rayData[7]);
}
}
void NuclideRayDialog::initUI()
{
setWindowTitle(m_isEdit ? "编辑射线信息" : "添加射线信息");
setFixedSize(450, 300);
QFormLayout *formLayout = new QFormLayout(this);
// 射线类型下拉框(常用核素射线类型)
m_cmbRayType = new QComboBox(this);
m_cmbRayType->addItems({"γ", "β⁻", "β⁺", "α", "X射线", "中子", "电子俘获"});
formLayout->addRow("射线类型", m_cmbRayType);
m_leRayMev = new QLineEdit(this);
m_leRayMev->setPlaceholderText("例如1.332 MeV");
formLayout->addRow("射线能量", m_leRayMev);
m_leRayMevUnc = new QLineEdit(this);
m_leRayMevUnc->setPlaceholderText("例如0.001 MeV");
formLayout->addRow("能量不确定度", m_leRayMevUnc);
m_leBranchRatio = new QLineEdit(this);
m_leBranchRatio->setPlaceholderText("例如0.9998");
formLayout->addRow("分支比", m_leBranchRatio);
m_leBranchRatioUnc = new QLineEdit(this);
m_leBranchRatioUnc->setPlaceholderText("例如0.0001");
formLayout->addRow("分支比不确定度", m_leBranchRatioUnc);
// 主射线标识下拉框
m_cmbMainRayIdent = new QComboBox(this);
m_cmbMainRayIdent->addItems({"", ""});
formLayout->addRow("是否为主射线", m_cmbMainRayIdent);
m_leJiahePeak = new QLineEdit(this);
m_leJiahePeak->setPlaceholderText("无则留空");
formLayout->addRow("加和峰", m_leJiahePeak);
// 按钮盒
QDialogButtonBox *btnBox = new QDialogButtonBox(
QDialogButtonBox::Ok | QDialogButtonBox::Cancel,
Qt::Horizontal, this);
formLayout->addRow(btnBox);
// 信号连接
connect(btnBox, &QDialogButtonBox::accepted, this, [this]() {
if (validateInput()) {
accept();
}
});
connect(btnBox, &QDialogButtonBox::rejected, this, &QDialog::reject);
}
bool NuclideRayDialog::validateInput()
{
// 必填项校验
if (m_leRayMev->text().trimmed().isEmpty()) {
QMessageBox::warning(this, "输入错误", "射线能量不能为空!");
return false;
}
if (m_leRayMevUnc->text().trimmed().isEmpty()) {
QMessageBox::warning(this, "输入错误", "能量不确定度不能为空!");
return false;
}
if (m_leBranchRatioUnc->text().trimmed().isEmpty()) {
QMessageBox::warning(this, "输入错误", "分支比不确定度不能为空!");
return false;
}
// 数字格式校验(允许带单位)
bool ok;
// 提取数字部分进行校验
QString mevText = m_leRayMev->text().trimmed().replace(QRegExp("[^0-9.]"), "");
mevText.toDouble(&ok);
if (!ok) {
QMessageBox::warning(this, "输入错误", "射线能量必须为有效数字!");
return false;
}
QString mevUncText = m_leRayMevUnc->text().trimmed().replace(QRegExp("[^0-9.]"), "");
mevUncText.toDouble(&ok);
if (!ok) {
QMessageBox::warning(this, "输入错误", "能量不确定度必须为有效数字!");
return false;
}
QString ratioUncText = m_leBranchRatioUnc->text().trimmed().replace(QRegExp("[^0-9.]"), "");
ratioUncText.toDouble(&ok);
if (!ok) {
QMessageBox::warning(this, "输入错误", "分支比不确定度必须为有效数字!");
return false;
}
return true;
}
QStringList NuclideRayDialog::getRayData() const
{
QStringList data;
if (m_isEdit) {
data << m_id; // 编辑模式返回ID
}
data << m_cmbRayType->currentText().trimmed()
<< m_leRayMev->text().trimmed()
<< m_leRayMevUnc->text().trimmed()
<< m_leBranchRatio->text().trimmed()
<< m_leBranchRatioUnc->text().trimmed()
<< m_cmbMainRayIdent->currentText().trimmed()
<< m_leJiahePeak->text().trimmed();
return data;
}

View File

@ -0,0 +1,37 @@
#ifndef NUCLIDERAYDIALOG_H
#define NUCLIDERAYDIALOG_H
#include <QDialog>
#include <QLineEdit>
#include <QComboBox>
#include <QFormLayout>
#include <QDialogButtonBox>
#include <QMessageBox>
class NuclideRayDialog : public QDialog
{
Q_OBJECT
public:
explicit NuclideRayDialog(bool isEdit = false, const QStringList& rayData = {}, QWidget *parent = nullptr);
~NuclideRayDialog() = default;
QStringList getRayData() const;
private:
void initUI(); // 初始化界面
bool validateInput(); // 输入校验
QComboBox *m_cmbRayType; // 射线类型(下拉选择)
QLineEdit *m_leRayMev; // 射线能量
QLineEdit *m_leRayMevUnc; // 能量不确定度
QLineEdit *m_leBranchRatio; // 分支比
QLineEdit *m_leBranchRatioUnc; // 分支比不确定度
QComboBox *m_cmbMainRayIdent; // 主射线标识
QLineEdit *m_leJiahePeak; // 加和峰
bool m_isEdit; // 是否为编辑模式
QString m_id; // 编辑模式下的射线ID
};
#endif // NUCLIDERAYDIALOG_H

View File

@ -0,0 +1,248 @@
#include "NuclideRayListDialog.h"
#include <QTableView>
RayButtonDelegate::RayButtonDelegate(QObject *parent) : QStyledItemDelegate(parent) {}
void RayButtonDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
if (index.column() == 8) { // 第8列是操作列
// 绘制编辑按钮
QStyleOptionButton editBtn;
editBtn.rect = QRect(option.rect.x(), option.rect.y() + 2, 60, option.rect.height() - 4);
editBtn.text = "编辑";
editBtn.state = QStyle::State_Enabled;
if (option.state & QStyle::State_MouseOver)
editBtn.state |= QStyle::State_MouseOver;
QApplication::style()->drawControl(QStyle::CE_PushButton, &editBtn, painter);
// 绘制删除按钮
QStyleOptionButton delBtn;
delBtn.rect = QRect(option.rect.x() + 70, option.rect.y() + 2, 60, option.rect.height() - 4);
delBtn.text = "删除";
delBtn.state = QStyle::State_Enabled;
if (option.state & QStyle::State_MouseOver)
delBtn.state |= QStyle::State_MouseOver;
QApplication::style()->drawControl(QStyle::CE_PushButton, &delBtn, painter);
} else {
QStyledItemDelegate::paint(painter, option, index);
}
}
bool RayButtonDelegate::editorEvent(QEvent *event, QAbstractItemModel *model, const QStyleOptionViewItem &option, const QModelIndex &index)
{
if (index.column() == 8 && event->type() == QEvent::MouseButtonRelease) {
QMouseEvent *mouseEvent = static_cast<QMouseEvent*>(event);
QRect editRect = QRect(option.rect.x(), option.rect.y() + 2, 60, option.rect.height() - 4);
QRect delRect = QRect(option.rect.x() + 70, option.rect.y() + 2, 60, option.rect.height() - 4);
if (editRect.contains(mouseEvent->pos())) {
emit editButtonClicked(index);
return true;
} else if (delRect.contains(mouseEvent->pos())) {
emit deleteButtonClicked(index);
return true;
}
}
return QStyledItemDelegate::editorEvent(event, model, option, index);
}
NuclideRayListDialog::NuclideRayListDialog(const QString& nuclideId, const QString& nuclideName, QWidget *parent)
: QDialog(parent), m_nuclideId(nuclideId), m_nuclideName(nuclideName)
{
initUI();
loadRayData();
}
void NuclideRayListDialog::initUI()
{
setWindowTitle(QString("%1 - 射线信息管理").arg(m_nuclideName));
setFixedSize(900, 500);
QVBoxLayout *mainLayout = new QVBoxLayout(this);
// 添加按钮
QPushButton *btnAdd = new QPushButton("添加射线", this);
connect(btnAdd, &QPushButton::clicked, this, &NuclideRayListDialog::onAddRayClicked);
mainLayout->addWidget(btnAdd, 0, Qt::AlignRight);
// 射线列表
m_model = new QStandardItemModel(0, 9, this);
m_model->setHorizontalHeaderLabels({
"ID", "射线类型", "能量(MeV)", "能量不确定度", "分支比",
"分支比不确定度", "主射线", "加和峰", "操作"
});
QTableView *tableView = new QTableView(this);
tableView->setModel(m_model);
tableView->setColumnHidden(0, true); // 隐藏ID列
tableView->setColumnWidth(1, 80); // 射线类型
tableView->setColumnWidth(2, 120); // 能量
tableView->setColumnWidth(3, 120); // 能量不确定度
tableView->setColumnWidth(4, 100); // 分支比
tableView->setColumnWidth(5, 120); // 分支比不确定度
tableView->setColumnWidth(6, 80); // 主射线
tableView->setColumnWidth(7, 100); // 加和峰
tableView->setColumnWidth(8, 150); // 操作列
tableView->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch);
tableView->setAlternatingRowColors(true);
tableView->setSelectionBehavior(QAbstractItemView::SelectRows);
tableView->setFocusPolicy(Qt::NoFocus);
// 设置委托
m_delegate = new RayButtonDelegate(this);
tableView->setItemDelegateForColumn(8, m_delegate);
connect(m_delegate, &RayButtonDelegate::editButtonClicked, this, &NuclideRayListDialog::onEditRayClicked);
connect(m_delegate, &RayButtonDelegate::deleteButtonClicked, this, &NuclideRayListDialog::onDeleteRayClicked);
mainLayout->addWidget(tableView);
// 关闭按钮
QPushButton *btnClose = new QPushButton("关闭", this);
connect(btnClose, &QPushButton::clicked, this, &QDialog::accept);
mainLayout->addWidget(btnClose, 0, Qt::AlignRight);
}
void NuclideRayListDialog::loadRayData()
{
// 查询当前核素的所有射线信息
QString sql = "SELECT ID, RAY_TYPE, RAY_MEV, RAY_MEV_UNCERTAINTY, RAY_BRANCH_RATIO, "
"RAY_BRANCH_RATIO_UNCERTAINTY, MAIN_RAY_IDENT, JIAHE_PEAK "
"FROM nuclideRayInfo WHERE NUCLIDE_ID = ?;";
auto rows = SqliteManager::instance().selectRows(sql, {m_nuclideId});
m_listRay.clear();
m_model->setRowCount(0);
int row = 0;
for (const auto& rec : rows) {
QStringList item;
item << rec["ID"].toString()
<< rec["RAY_TYPE"].toString()
<< rec["RAY_MEV"].toString()
<< rec["RAY_MEV_UNCERTAINTY"].toString()
<< rec["RAY_BRANCH_RATIO"].toString()
<< rec["RAY_BRANCH_RATIO_UNCERTAINTY"].toString()
<< rec["MAIN_RAY_IDENT"].toString()
<< rec["JIAHE_PEAK"].toString();
m_listRay.append(item);
// 插入模型行
QList<QStandardItem*> rowItems;
// 第0列ID隐藏
QStandardItem *idItem = new QStandardItem(item[0]);
idItem->setTextAlignment(Qt::AlignCenter);
idItem->setFlags(idItem->flags() & ~Qt::ItemIsEditable);
rowItems << idItem;
// 第1~7列射线数据
for (int col = 1; col <= 7; ++col) {
QStandardItem *dataItem = new QStandardItem(item[col]);
dataItem->setTextAlignment(Qt::AlignCenter);
dataItem->setFlags(dataItem->flags() & ~Qt::ItemIsEditable);
rowItems << dataItem;
}
// 第8列操作列
QStandardItem *opItem = new QStandardItem("");
opItem->setFlags(opItem->flags() & ~Qt::ItemIsEditable);
rowItems << opItem;
m_model->appendRow(rowItems);
++row;
}
}
QStringList NuclideRayListDialog::getRayData(const QString &id)
{
for (const auto& item : m_listRay) {
if (item.at(0) == id)
return item;
}
return QStringList();
}
void NuclideRayListDialog::onAddRayClicked()
{
NuclideRayDialog dlg(false, {}, this);
if (dlg.exec() == QDialog::Accepted) {
QStringList data = dlg.getRayData();
if (data.size() < 7) return;
QMap<QString, QVariant> fieldValues;
fieldValues["NUCLIDE_ID"] = m_nuclideId.toInt();
fieldValues["RAY_TYPE"] = data[0];
fieldValues["RAY_MEV"] = data[1];
fieldValues["RAY_MEV_UNCERTAINTY"] = data[2];
fieldValues["RAY_BRANCH_RATIO"] = data[3];
fieldValues["RAY_BRANCH_RATIO_UNCERTAINTY"] = data[4];
fieldValues["MAIN_RAY_IDENT"] = data[5];
fieldValues["JIAHE_PEAK"] = data[6];
fieldValues["CREATE_TIME"] = QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss");
qint64 newId = SqliteManager::instance().insertRow("nuclideRayInfo", fieldValues);
if (newId > 0) {
QMessageBox::information(this, "成功", "射线信息添加成功!");
loadRayData(); // 刷新列表
} else {
QMessageBox::warning(this, "失败", "添加失败:" + SqliteManager::instance().lastError());
}
}
}
void NuclideRayListDialog::onEditRayClicked(const QModelIndex &index)
{
int row = index.row();
QString id = m_model->index(row, 0).data().toString();
QStringList data = getRayData(id);
if (data.isEmpty()) return;
NuclideRayDialog dlg(true, data, this);
if (dlg.exec() == QDialog::Accepted) {
QStringList newData = dlg.getRayData();
if (newData.size() < 8) return;
QMap<QString, QVariant> fieldValues;
fieldValues["RAY_TYPE"] = newData[1];
fieldValues["RAY_MEV"] = newData[2];
fieldValues["RAY_MEV_UNCERTAINTY"] = newData[3];
fieldValues["RAY_BRANCH_RATIO"] = newData[4];
fieldValues["RAY_BRANCH_RATIO_UNCERTAINTY"] = newData[5];
fieldValues["MAIN_RAY_IDENT"] = newData[6];
fieldValues["JIAHE_PEAK"] = newData[7];
int affectedRows = SqliteManager::instance().updateRow(
"nuclideRayInfo",
fieldValues,
"ID = ?",
{newData[0]}
);
if (affectedRows > 0) {
QMessageBox::information(this, "成功", "射线信息修改成功!");
loadRayData();
} else if (affectedRows == 0) {
QMessageBox::information(this, "提示", "未修改任何数据!");
} else {
QMessageBox::warning(this, "失败", "修改失败:" + SqliteManager::instance().lastError());
}
}
}
void NuclideRayListDialog::onDeleteRayClicked(const QModelIndex &index)
{
int row = index.row();
QString id = m_model->index(row, 0).data().toString();
QMessageBox box(QMessageBox::Question, "提示", "确定删除该射线信息吗?",
QMessageBox::Yes | QMessageBox::No, this);
box.button(QMessageBox::Yes)->setText("确认");
box.button(QMessageBox::No)->setText("取消");
if (box.exec() != QMessageBox::Yes) return;
bool ok = SqliteManager::instance().deleteRow("nuclideRayInfo", "ID = ?", {id});
if (ok) {
loadRayData();
} else {
QMessageBox::warning(this, "错误", "删除失败:" + SqliteManager::instance().lastError());
}
}

View File

@ -0,0 +1,57 @@
#ifndef NUCLIDERAYLISTDIALOG_H
#define NUCLIDERAYLISTDIALOG_H
#include <QDialog>
#include <QStandardItemModel>
#include <QStyledItemDelegate>
#include <QPushButton>
#include <QHBoxLayout>
#include <QVBoxLayout>
#include <QHeaderView>
#include <QMessageBox>
#include <QPainter>
#include <QStyleOptionButton>
#include <QMouseEvent>
#include <QApplication>
#include <QDateTime>
#include "sqlitemanager.h"
#include "NuclideRayDialog.h"
// 射线列表操作按钮委托
class RayButtonDelegate : public QStyledItemDelegate
{
Q_OBJECT
public:
explicit RayButtonDelegate(QObject *parent = nullptr);
void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const override;
bool editorEvent(QEvent *event, QAbstractItemModel *model, const QStyleOptionViewItem &option, const QModelIndex &index) override;
signals:
void editButtonClicked(const QModelIndex &index) const;
void deleteButtonClicked(const QModelIndex &index) const;
};
class NuclideRayListDialog : public QDialog
{
Q_OBJECT
public:
explicit NuclideRayListDialog(const QString& nuclideId, const QString& nuclideName, QWidget *parent = nullptr);
~NuclideRayListDialog() = default;
private slots:
void onAddRayClicked(); // 添加射线
void onEditRayClicked(const QModelIndex &index); // 编辑射线
void onDeleteRayClicked(const QModelIndex &index); // 删除射线
private:
void initUI(); // 初始化界面
void loadRayData(); // 加载当前核素的射线数据
QStringList getRayData(const QString &id); // 获取指定ID的射线数据
QString m_nuclideId; // 当前核素ID
QString m_nuclideName; // 当前核素名称
QStandardItemModel *m_model; // 射线列表模型
RayButtonDelegate *m_delegate;// 按钮委托
QVector<QStringList> m_listRay; // 缓存射线数据
};
#endif // NUCLIDERAYLISTDIALOG_H

View File

@ -30,7 +30,9 @@ void ConformityAnalysis::SetAnalyzeDataFilename(const QMap<QString, QVariant> &d
{
QStringList ch_count_data_name = data_files_set.keys();
int conformCount = ui->comboBox->currentIndex() + 2;
for (const QString& ch_count_data_name : ch_count_data_name) {
for (const QString& ch_count_data_name : ch_count_data_name)
{
if(conformCount == ch_count_data_name.toInt())
{
setCsvFile(data_files_set[ch_count_data_name].toString());
@ -96,6 +98,8 @@ void ConformityAnalysis::slot_ClickedBoard(int board,int channel)
ui->widget->setWidgetData(board,channel,m_boardChannel[board - 1][channel - 1],data.size());
}
void ConformityAnalysis::handleBoard()
{
for(auto spetruData:_spectrumDataList)

View File

@ -6,15 +6,17 @@
#include "ParticleDataStatistics.h"
#include "ThreeDDisplay.h"
#include "csv.h"
#include "CoincidenceSpectrumProcess.h"
#include "MeasureAnalysisView.h"
#include <QVector>
using namespace CoincidenceSpectrum;
//using namespace CoincidenceSpectrum;
namespace Ui {
class ConformityAnalysis;
}
typedef struct particleCoincidenceEvent
{
int eventId;//事件ID
@ -24,6 +26,13 @@ typedef struct particleCoincidenceEvent
qulonglong timeCounter;//时间计数
}PARTICLECOINCIDENCEEVENT;
//// 用于存储三维数据
//typedef struct SurfacePoint {
// float primaryEnergy; // 初级粒子能量
// float secondaryEnergySum; // 次级粒子能量和
// int count; // 符合事件计数
//}SURFACEPOINT;
class ConformityAnalysis : public MeasureAnalysisView
{
Q_OBJECT
@ -50,7 +59,6 @@ public:
private slots:
void slot_InitialState();
void slot_ClickedBoard(int board,int channel);
private:
//处理板卡信息
void handleBoard();
@ -76,7 +84,7 @@ private:
QString m_fileName;
std::vector<F2t9Order::CoincidenceEvent> m_CoincidenceEventVector;//所有的能谱符合处理
// std::vector<F2t9Order::CoincidenceEvent> m_CoincidenceEventVector;//所有的能谱符合处理
int m_boardChannel[MAX_BOARD][MAX_CHANNEL];

View File

@ -3,14 +3,35 @@
#include <QWidget>
#include "DetectorStatusSummary.h"
#include "CoincidenceSpectrumProcess.h"
//#include "CoincidenceSpectrumProcess.h"
#include <QMap>
using namespace CoincidenceSpectrum;
//using namespace CoincidenceSpectrum;
namespace Ui {
class ParticleDataStatistics;
}
// 二次符合事件处理
namespace F2t9Order {
// 能谱数据结构
struct SpectrumData {
int board_id; // 板卡号
int channel_id; // 通道号
double energy; // 能量
unsigned long long timestamp; // 时间戳(纳秒)
};
// 符合事件结果结构
struct CoincidenceEvent {
int coincidence_order; // 符合次数2-9
std::vector<SpectrumData> events; // 符合的事件集合
unsigned int time_window; // 使用的时间窗口(秒)
};
}
// 定义板卡和通道的最大数量
static constexpr int MAX_BOARD = 8;
static constexpr int MAX_CHANNEL = 4;
class ParticleDataStatistics : public QWidget
{
Q_OBJECT

View File

@ -5,15 +5,15 @@
#include <QtDataVisualization>
#include <QLabel>
#include "CoincidenceSpectrumProcess.h"
//#include "CoincidenceSpectrumProcess.h"
using namespace QtDataVisualization;
//// 用于存储三维数据
//typedef struct SurfacePoint {
// float primaryEnergy; // 初级粒子能量
// float secondaryEnergySum; // 次级粒子能量和
// int count; // 符合事件计数
//}SURFACEPOINT;
// 用于存储三维数据
typedef struct SurfacePoint {
float primaryEnergy; // 初级粒子能量
float secondaryEnergySum; // 次级粒子能量和
int count; // 符合事件计数
}SURFACEPOINT;
namespace Ui {
class ThreeDDisplay;

View File

@ -84,6 +84,9 @@ SOURCES += \
MeasureAnalysisHistoryForm/MeasureAnalysisHistoryForm.cpp \
MeasureDeviceParamsConfigView/DeviceParamsTableForm.cpp \
MeasureDeviceParamsConfigView/MeasureDeviceParamsConfigView.cpp \
NuclideLib/NuclideEditDialog.cpp \
NuclideLib/NuclideRayDialog.cpp \
NuclideLib/NuclideRayListDialog.cpp \
NuclideLib/sqlitemanager.cpp \
ParticleCountPlotView/BatchEnergyScaleDialog.cpp \
ParticleCountPlotView/FindPeaksResultDialog.cpp \
@ -132,6 +135,9 @@ HEADERS += \
MeasureAnalysisHistoryForm/MeasureAnalysisHistoryForm.h \
MeasureDeviceParamsConfigView/DeviceParamsTableForm.h \
MeasureDeviceParamsConfigView/MeasureDeviceParamsConfigView.h \
NuclideLib/NuclideEditDialog.h \
NuclideLib/NuclideRayDialog.h \
NuclideLib/NuclideRayListDialog.h \
NuclideLib/sqlitemanager.h \
ParticleCountPlotView/BatchEnergyScaleDialog.h \
ParticleCountPlotView/FindPeaksResultDialog.h \