添加能量计数数据生成

This commit is contained in:
徐海 2026-03-21 00:26:34 +08:00
parent 2c38e2414a
commit 558a3256e0
10 changed files with 109 additions and 31 deletions

View File

@ -12,7 +12,7 @@ arma::vec EnergyEfficiencyFit::SemiEmpiricalFit(const arma::vec &E, const arma::
{ {
// 输入数据有效性检查 // 输入数据有效性检查
if (E.n_elem != eps.n_elem) { if (E.n_elem != eps.n_elem) {
throw(string("错误:能量数据和效率数据长度不匹配")); throw(string("错误:能量数据和效率数据长度不匹配!"));
} }
if (E.n_elem <= order) { if (E.n_elem <= order) {
stringstream ss_error; stringstream ss_error;
@ -22,7 +22,7 @@ arma::vec EnergyEfficiencyFit::SemiEmpiricalFit(const arma::vec &E, const arma::
} }
if (order < 0) { if (order < 0) {
stringstream ss_error; stringstream ss_error;
ss_error << "错误:多项式阶数不能为负数"; ss_error << "错误:多项式阶数不能为负数!";
throw(ss_error.str()); throw(ss_error.str());
} }

View File

@ -237,7 +237,7 @@ double EfficiencyExperimentalCalc(int N, double A, double P, double t)
double EnergyEfficiency(double E, const vec &coeffs) double EnergyEfficiency(double E, const vec &coeffs)
{ {
if (E <= 0) { if (E <= 0) {
throw std::string("能量数据必须为正数"); throw std::string("能量数据必须为正数!");
} }
double tmp_value = 0.0f; double tmp_value = 0.0f;

View File

@ -234,7 +234,7 @@ bool EveryChannelParticleCountDataTask::processEveryChannelParticleData()
try { try {
// 统计每个通道的粒子计数(相同板卡号通道号相同道址) // 统计每个通道的粒子计数(相同板卡号通道号相同道址)
QMap<uint, QMap<uint, uint>> channel_address_counts; // 通道号 -> 地址 -> 计数 QMap<uint, QMap<uint, unsigned long long>> channel_address_counts; // 通道号 -> 地址 -> 计数
// 统计所有通道的粒子计数(不同板卡号通道号相同道址) // 统计所有通道的粒子计数(不同板卡号通道号相同道址)
// QMap<uint, uint> all_channel_address_counts; // 地址 -> 计数 // QMap<uint, uint> all_channel_address_counts; // 地址 -> 计数
@ -263,7 +263,7 @@ bool EveryChannelParticleCountDataTask::processEveryChannelParticleData()
// 统计每个通道的粒子计数 // 统计每个通道的粒子计数
if (!channel_address_counts.contains(channel_num)) { if (!channel_address_counts.contains(channel_num)) {
channel_address_counts[channel_num] = QMap<uint, uint>(); channel_address_counts[channel_num] = QMap<uint, unsigned long long>();
} }
channel_address_counts[channel_num][address]++; channel_address_counts[channel_num][address]++;
@ -289,12 +289,12 @@ bool EveryChannelParticleCountDataTask::processEveryChannelParticleData()
// 批量写入数据 // 批量写入数据
for (auto channel_it = channel_address_counts.begin(); channel_it != channel_address_counts.end(); ++channel_it) { for (auto channel_it = channel_address_counts.begin(); channel_it != channel_address_counts.end(); ++channel_it) {
uint channel_num = channel_it.key(); uint channel_num = channel_it.key();
const QMap<uint, uint>& address_counts = channel_it.value(); const QMap<uint, unsigned long long>& address_counts = channel_it.value();
auto out_stream = channel_file_streams[channel_num]; auto out_stream = channel_file_streams[channel_num];
for (auto address_it = address_counts.begin(); address_it != address_counts.end(); ++address_it) { for (auto address_it = address_counts.begin(); address_it != address_counts.end(); ++address_it) {
uint address = address_it.key(); uint address = address_it.key();
uint count = address_it.value(); unsigned long long count = address_it.value();
*out_stream << address << "," << count << std::endl; *out_stream << address << "," << count << std::endl;
} }
} }
@ -731,15 +731,20 @@ bool ChannelEnergyScaleFittingTask::processTask()
return true; return true;
} }
bool ApplyEnergyScaleTask::scaleParticleData(EnergyScaleDataModel& energy_scale_data_model, const QString& data_filename, const QString& out_filename) bool ApplyEnergyScaleTask::scaleParticleData(MeasureAnalysisProjectModel* project_model, EnergyScaleDataModel& energy_scale_data_model)
{ {
bool ok = true; bool ok = true;
const QString& all_channel_particle_data_filename = project_model->GetAllChannelParticleDataFilename();
if (all_channel_particle_data_filename.isEmpty()) {
return ok &= false;
}
const QString& energy_spectrum_filename = QDir(project_model->GetProjectDir()).filePath(QStringLiteral(u"能谱数据.csv"));
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();
std::string address_str = QString(QStringLiteral(u"道址")).toStdString(); std::string address_str = QString(QStringLiteral(u"道址")).toStdString();
std::string energy_str = QString(QStringLiteral(u"能量(KeV)")).toStdString(); std::string energy_str = QString(QStringLiteral(u"能量(KeV)")).toStdString();
std::string time_str = QString(QStringLiteral(u"时间计数")).toStdString(); std::string time_str = QString(QStringLiteral(u"时间计数")).toStdString();
std::ofstream out(QStrToSysPath(out_filename)); std::ofstream out(QStrToSysPath(energy_spectrum_filename));
out << board_id_str << "," << channel_id_str << "," << energy_str << "," << time_str<< "\n" ; out << board_id_str << "," << channel_id_str << "," << energy_str << "," << time_str<< "\n" ;
try { try {
io::CSVReader< io::CSVReader<
@ -748,7 +753,7 @@ bool ApplyEnergyScaleTask::scaleParticleData(EnergyScaleDataModel& energy_scale_
io::double_quote_escape<',', '"'>, io::double_quote_escape<',', '"'>,
io::throw_on_overflow, io::throw_on_overflow,
io::empty_line_comment> io::empty_line_comment>
reader(QStrToSysPath(data_filename)); reader(QStrToSysPath(all_channel_particle_data_filename));
reader.read_header(io::ignore_extra_column, board_id_str, channel_id_str, address_str, time_str); reader.read_header(io::ignore_extra_column, board_id_str, channel_id_str, address_str, time_str);
uint board_id; uint board_id;
uint channel_id; uint channel_id;
@ -764,14 +769,62 @@ bool ApplyEnergyScaleTask::scaleParticleData(EnergyScaleDataModel& energy_scale_
out.close(); out.close();
} catch (const std::exception& e) { } catch (const std::exception& e) {
out.close(); out.close();
std::remove(QStrToSysPath(out_filename)); std::remove(QStrToSysPath(energy_spectrum_filename));
ok &= false;
const QString& e_what = QString::fromStdString(e.what());
LOG_WARN(QStringLiteral(u"能谱数据异常:%1").arg(e_what));
} }
return ok; return ok;
} }
bool ApplyEnergyScaleTask::energyCountProcess() bool ApplyEnergyScaleTask::energyCountProcess(MeasureAnalysisProjectModel* project_model, EnergyScaleDataModel& energy_scale_data_model)
{ {
bool ok = true; bool ok = true;
const QMap<uint, QString>& ch_addr_count_filename_list = project_model->GetChannelAddressCountDataFilenameList();
if (ch_addr_count_filename_list.isEmpty()) {
LOG_WARN(QStringLiteral(u"能量计数统计需要的通道道址计数文件异常!"));
return ok &= false;
}
const QString& out_path = QDir(project_model->GetProjectDir()).filePath(QStringLiteral(u"能量计数"));
if ( !QDir(out_path).mkpath(out_path) ) {
LOG_WARN(QStringLiteral(u"创建能量计数数据目录\"%1\"异常!").arg(out_path));
return ok &= false;
}
QMap<uint, QString> every_ch_energy_count_filename_list;
for (const int& channel_num : ch_addr_count_filename_list.keys()) {
const QString& channel_name = QStringLiteral(u"通道%1").arg(channel_num);
const QString& data_filename = ch_addr_count_filename_list[channel_num];
std::string address_str = QString(QStringLiteral(u"道址")).toStdString();
std::string energy_str = QString(QStringLiteral(u"能量(KeV)")).toStdString();
std::string count_str = QString(QStringLiteral(u"计数")).toStdString();
const QString& out_filename = QDir(out_path).filePath(channel_name + ".csv");
std::ofstream out(QStrToSysPath(out_filename));
out << energy_str << "," << count_str << "\n" ;
try {
io::CSVReader<
2,
io::trim_chars<' ', '\t'>,
io::double_quote_escape<',', '"'>,
io::throw_on_overflow,
io::empty_line_comment>
reader(QStrToSysPath(data_filename));
reader.read_header(io::ignore_extra_column, address_str, count_str);
uint address;
unsigned long long count;
while (reader.read_row(address, count)) {
auto coeffs = energy_scale_data_model.GetEnergyFitResultCoeffs(channel_name);
double energy = GaussPolyCoe::Predict(coeffs, address);
out << energy << "," << count << "\n";
}
out.close();
every_ch_energy_count_filename_list[channel_num] = out_filename;
} catch (const std::exception& e) {
out.close();
std::remove(QStrToSysPath(out_filename));
const QString& e_what = QString::fromStdString(e.what());
LOG_WARN(QStringLiteral(u"%1能量计数异常:%2").arg(channel_name).arg(e_what));
}
}
return ok; return ok;
} }
@ -795,15 +848,10 @@ bool ApplyEnergyScaleTask::processTask()
if (!energy_scale_data_model.IsValid()) { if (!energy_scale_data_model.IsValid()) {
return false; return false;
} }
const QString& all_channel_particle_data_filename = project_model->GetAllChannelParticleDataFilename(); if (!scaleParticleData(project_model, energy_scale_data_model)) {
if (all_channel_particle_data_filename.isEmpty()) {
return false; return false;
} }
const QString& energy_spectrum_filename = QDir(project_model->GetProjectDir()).filePath(QStringLiteral(u"能谱数据.csv")); if (!energyCountProcess(project_model, energy_scale_data_model)) {
if (!scaleParticleData(energy_scale_data_model, all_channel_particle_data_filename, energy_spectrum_filename)) {
return false;
}
if (!energyCountProcess()) {
return false; return false;
} }
if (!coincidenceProcess()) { if (!coincidenceProcess()) {

View File

@ -9,6 +9,7 @@
#include <QVariant> #include <QVariant>
class EnergyScaleDataModel; class EnergyScaleDataModel;
class MeasureAnalysisProjectModel;
namespace DataProcessWorkPool namespace DataProcessWorkPool
{ {
@ -130,8 +131,8 @@ namespace DataProcessWorkPool
class ApplyEnergyScaleTask : public DataProcessTask class ApplyEnergyScaleTask : public DataProcessTask
{ {
private: private:
bool scaleParticleData(EnergyScaleDataModel &energy_scale_data_model, const QString& data_filename, const QString& out_filename); bool scaleParticleData(MeasureAnalysisProjectModel* project_model, EnergyScaleDataModel &energy_scale_data_model);
bool energyCountProcess(); bool energyCountProcess(MeasureAnalysisProjectModel* project_model, EnergyScaleDataModel& energy_scale_data_model);
bool coincidenceProcess(); bool coincidenceProcess();
virtual bool processTask() override; virtual bool processTask() override;
private: private:

View File

@ -62,6 +62,26 @@ bool EnergyScaleDataModel::IsValid()
return b_is_valid; return b_is_valid;
} }
void EnergyScaleDataModel::SetName(const QString &name)
{
_energy_scale_data_map["Name"] = name;
}
QString EnergyScaleDataModel::GetName()
{
return _energy_scale_data_map.value("Name", QString()).toString();
}
void EnergyScaleDataModel::SetDescription(const QString &description)
{
_energy_scale_data_map["Description"] = description;
}
QString EnergyScaleDataModel::GetDescription()
{
return _energy_scale_data_map.value("Description", QString()).toString();
}
void EnergyScaleDataModel::SetChannelEnergyScaleDataMap(const QString& channel_name, const QVariantMap& ch_energy_scale_data_map) void EnergyScaleDataModel::SetChannelEnergyScaleDataMap(const QString& channel_name, const QVariantMap& ch_energy_scale_data_map)
{ {
if (!ch_energy_scale_data_map.isEmpty()) { if (!ch_energy_scale_data_map.isEmpty()) {

View File

@ -17,6 +17,12 @@ public:
bool SaveData(); bool SaveData();
bool IsValid(); bool IsValid();
void SetName(const QString& name);
QString GetName();
void SetDescription(const QString& description);
QString GetDescription();
void SetChannelEnergyScaleDataMap(const QString& channel_name, const QVariantMap& ch_energy_scale_data_map); void SetChannelEnergyScaleDataMap(const QString& channel_name, const QVariantMap& ch_energy_scale_data_map);
QVariantMap GetChannelEnergyScaleDataMap(const QString& channel_name); QVariantMap GetChannelEnergyScaleDataMap(const QString& channel_name);

View File

@ -175,7 +175,7 @@ void MainWindow::initAction()
} }
QFileInfo file_info(filename); QFileInfo file_info(filename);
if (file_info.size() == 0) { if (file_info.size() == 0) {
QMessageBox::warning(this, QStringLiteral(u"警告"), QStringLiteral(u"选择的测量分析项目文件为空文件")); QMessageBox::warning(this, QStringLiteral(u"警告"), QStringLiteral(u"选择的测量分析项目文件为空文件!"));
return; return;
} }
MeasureAnalysisProjectModel* model = new MeasureAnalysisProjectModel; MeasureAnalysisProjectModel* model = new MeasureAnalysisProjectModel;
@ -192,7 +192,7 @@ void MainWindow::initAction()
const QString& info_text = QStringLiteral(u"保存测量分析项目\"%1\"完成.").arg(project_name); const QString& info_text = QStringLiteral(u"保存测量分析项目\"%1\"完成.").arg(project_name);
LOG_INFO(info_text); LOG_INFO(info_text);
} else { } else {
const QString& warn_text = QStringLiteral(u"保存测量分析项目\"%1\"失败").arg(project_name); const QString& warn_text = QStringLiteral(u"保存测量分析项目\"%1\"失败!").arg(project_name);
LOG_WARN(warn_text); LOG_WARN(warn_text);
} }
} }

View File

@ -361,7 +361,7 @@ void BatchEnergyScaleDialog::applyEnergyScaleFitResultData()
LOG_WARN(QStringLiteral(u"应用能量刻度异常,无法配置到测量分析[%1]!").arg(project_model->GetProjectName())); LOG_WARN(QStringLiteral(u"应用能量刻度异常,无法配置到测量分析[%1]!").arg(project_model->GetProjectName()));
} }
} else { } else {
QMessageBox::warning(this, QStringLiteral(u"警告"), QStringLiteral(u"不能应用非完整的能量刻度")); QMessageBox::warning(this, QStringLiteral(u"警告"), QStringLiteral(u"不能应用非完整的能量刻度!"));
} }
} }

View File

@ -212,8 +212,8 @@ void MeasureAnalysisParticleCountPlotView::loadDataFromFile(const QString& data_
reader.read_header(io::ignore_extra_column, address_str, count_str); reader.read_header(io::ignore_extra_column, address_str, count_str);
int address; int address;
int particle_count; unsigned long long particle_count;
QVector<float> x, y; QVector<double> x, y;
while (reader.read_row(address, particle_count)) { while (reader.read_row(address, particle_count)) {
x.push_back(address); x.push_back(address);

View File

@ -66,7 +66,7 @@ void NewMeasureAnalysisDlg::initialization()
} }
QFileInfo file_info(filename); QFileInfo file_info(filename);
if (file_info.size() == 0) { if (file_info.size() == 0) {
QMessageBox::warning(this, QStringLiteral(u"警告"), QStringLiteral(u"选择的粒子数据文件为空文件")); QMessageBox::warning(this, QStringLiteral(u"警告"), QStringLiteral(u"选择的粒子数据文件为空文件!"));
return; return;
} }
ui->lineEdit_filename->setText(file_info.fileName()); ui->lineEdit_filename->setText(file_info.fileName());
@ -179,7 +179,7 @@ void NewMeasureAnalysisDlg::on_btn_ok_clicked()
{ {
const QString& project_name = ui->lineEdit_name->text(); const QString& project_name = ui->lineEdit_name->text();
if (project_name.isEmpty()) { if (project_name.isEmpty()) {
QMessageBox::warning(this, QStringLiteral(u"警告"), QStringLiteral(u"请输入测量分析名称")); QMessageBox::warning(this, QStringLiteral(u"警告"), QStringLiteral(u"请输入测量分析名称!"));
return; return;
} }
QString projects_dir_path = QDir(qApp->applicationDirPath()).filePath("Projects"); QString projects_dir_path = QDir(qApp->applicationDirPath()).filePath("Projects");
@ -187,14 +187,17 @@ void NewMeasureAnalysisDlg::on_btn_ok_clicked()
QString project_dir_path = projects_dir.filePath(project_name); QString project_dir_path = projects_dir.filePath(project_name);
QDir project_dir(project_dir_path); QDir project_dir(project_dir_path);
if (project_dir.exists()) { if (project_dir.exists()) {
QMessageBox::warning(this, QStringLiteral(u"警告"), QStringLiteral(u"测量分析名称已存在,请重新输入!")); QMessageBox::warning(this, QStringLiteral(u"警告"), QStringLiteral(u"测量分析名称已存在,请重新输入!"));
return;
}
if ( !project_dir.mkpath(project_dir_path) ) {
QMessageBox::warning(this, QStringLiteral(u"警告"), QStringLiteral(u"创建测量分析项目工作目录失败:\n%1!").arg(project_dir_path));
return; return;
} }
project_dir.mkpath(project_dir_path);
if ( ui->checkBox_file_data->isChecked() ) { if ( ui->checkBox_file_data->isChecked() ) {
const QString& data_file_path = ui->lineEdit_filename->property("data_file_path").toString(); const QString& data_file_path = ui->lineEdit_filename->property("data_file_path").toString();
if (data_file_path.isEmpty()) { if (data_file_path.isEmpty()) {
QMessageBox::warning(this, QStringLiteral(u"警告"), QStringLiteral(u"请选择粒子数据文件")); QMessageBox::warning(this, QStringLiteral(u"警告"), QStringLiteral(u"请选择粒子数据文件!"));
return; return;
} }
auto separate_task = new DataProcessWorkPool::ParticleDataSortTask; auto separate_task = new DataProcessWorkPool::ParticleDataSortTask;