优化粒子排序

This commit is contained in:
徐海 2026-03-24 10:30:26 +08:00
parent 558a3256e0
commit adbca70bda
9 changed files with 188 additions and 57 deletions

View File

@ -19,7 +19,7 @@ enum class AnalysisType {
CountingRateView, // 计数率视图
EnergyPeakFitView, // 能量峰拟合视图
NuclideAnalysisView, // 核分析视图
ParticleInTimeView, // 粒子时间视图
ParticleInTimeView, // 粒子射入时间视图
ParticleTimeDiffView, // 粒子时间差视图
CoincidenceEventTimeView, // 符合事件时间视图
CoincidenceParticleEnergySpectrumView, // 符合粒子能量谱视图

View File

@ -14,6 +14,8 @@
#include <QVariant>
#include <QFuture>
#include <QtConcurrent>
#include <QProcess>
#include <QProcessEnvironment>
#include "DataCalcProcess/MathModelDefine.h"
#include "DataCalcProcess/FindPeaksBySvd.h"
#include "DataCalcProcess/GaussPolyCoe.h"
@ -536,17 +538,62 @@ bool ParticleDataSortTask::processEveryChannelParticleData()
} catch (const std::exception& e) {
const QString& e_what = QString::fromLatin1(e.what());
QString error = QString(QStringLiteral(u"处理%1异常:%2")).arg(all_channel_particle_data_filename).arg(e_what);
LOG_ERROR(error)
LOG_ERROR(error);
ret_ok = false;
} catch (...) {
QString error = QString(QStringLiteral(u"处理%1未知异常.")).arg(all_channel_particle_data_filename);
LOG_ERROR(error)
LOG_ERROR(error);
ret_ok = false;
}
this->updateTaskResultData(QVariant(sorted_output_filename));
return ret_ok;
}
bool ParticleDataSortByMinimysTask::processEveryChannelParticleData()
{
bool ret_ok = true;
const QString& sorted_result_dir = GetSortedResultDir();
QDir sorted_result_output_dir(sorted_result_dir);
sorted_result_output_dir.mkpath(sorted_result_dir);
const QString& data_filename = GetAllChannelParticleDataFilename();
QString output_filename = sorted_result_output_dir.filePath(QStringLiteral(u"粒子数据.csv"));
QString minimsys = QDir(qApp->applicationDirPath()).filePath(QString("minimsys"));
QString bash = QDir(minimsys).filePath(QString("bash"));
QString head = QDir(minimsys).filePath(QString("head"));
QString tail = QDir(minimsys).filePath(QString("tail"));
QString sort = QDir(minimsys).filePath(QString("sort"));
QString cmd = QString("(%1 -n 1 %4 && %2 -n +2 %4 | %3 -t ',' -k4 -n --parallel=8 -S 4G) > %5").arg(head).arg(tail).arg(sort).arg(data_filename).arg(output_filename);
QProcess proc;
QProcessEnvironment env = QProcessEnvironment::systemEnvironment();
env.clear();
env.insert("PATH", minimsys);
proc.setProcessEnvironment(env);
proc.setWorkingDirectory(minimsys);
proc.start(bash, { "-c", cmd });
proc.waitForFinished(-1);
if (proc.exitCode() != 0) {
QString process_error = QString(proc.readAllStandardError());
QString error = QStringLiteral(u"处理%1异常:%2").arg(data_filename).arg(process_error);
LOG_ERROR(error);
ret_ok = false;
}
this->updateTaskResultData(QVariant(output_filename));
return ret_ok;
}
bool CoincidenceEventAnalysisTask::processTask()
{
const QString& project_name = GetProjectName();
MeasureAnalysisProjectModel* project_model = ProjectList::Instance()->GetProjectModel(project_name);
if (project_model == nullptr) {
return false;
}
const QString& info = QStringLiteral(u"粒子符合事件数据处理完成.");
LOG_INFO(info);
return true;
}
void AutoFindPeaksTask::SetAnalysisType(AnalysisType analysis_type)
{
this->_analysis_type = analysis_type;
@ -731,12 +778,23 @@ bool ChannelEnergyScaleFittingTask::processTask()
return true;
}
bool ApplyEnergyScaleTask::scaleParticleData(MeasureAnalysisProjectModel* project_model, EnergyScaleDataModel& energy_scale_data_model)
bool EnergyScaleParticleDataTask::processTask()
{
bool ok = true;
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& all_channel_particle_data_filename = project_model->GetAllChannelParticleDataFilename();
if (all_channel_particle_data_filename.isEmpty()) {
return ok &= false;
return false;
}
const QString& energy_spectrum_filename = QDir(project_model->GetProjectDir()).filePath(QStringLiteral(u"能谱数据.csv"));
std::string board_id_str = QString(QStringLiteral(u"板卡号")).toStdString();
@ -763,35 +821,49 @@ bool ApplyEnergyScaleTask::scaleParticleData(MeasureAnalysisProjectModel* projec
int channel_num = (board_id) * 4 + (channel_id + 1);
const QString& channel_name = QStringLiteral(u"通道%1").arg(channel_num);
auto coeffs = energy_scale_data_model.GetEnergyFitResultCoeffs(channel_name);
double energy = GaussPolyCoe::Predict(coeffs, address);
out << board_id << "," << channel_id << "," << energy << "," << time << "\n";
if (!coeffs.empty()) {
double energy = GaussPolyCoe::Predict(coeffs, address);
out << board_id << "," << channel_id << "," << energy << "," << time << "\n";
}
}
out.close();
} catch (const std::exception& e) {
out.close();
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 false;
}
return ok;
const QString& info = QStringLiteral(u"能谱数据处理完成.");
LOG_INFO(info);
return true;
}
bool ApplyEnergyScaleTask::energyCountProcess(MeasureAnalysisProjectModel* project_model, EnergyScaleDataModel& energy_scale_data_model)
bool EnergyCountProcessTask::processTask()
{
bool ok = true;
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 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;
return 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;
return false;
}
QMap<uint, QString> every_ch_energy_count_filename_list;
for (const int& channel_num : ch_addr_count_filename_list.keys()) {
for (const uint& 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();
@ -813,11 +885,13 @@ bool ApplyEnergyScaleTask::energyCountProcess(MeasureAnalysisProjectModel* proje
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";
if (!coeffs.empty()) {
double energy = GaussPolyCoe::Predict(coeffs, address);
out << energy << "," << count << "\n";
}
}
out.close();
every_ch_energy_count_filename_list[channel_num] = out_filename;
project_model->SetChannelEnergyCountDataFilename(channel_num, out_filename);
} catch (const std::exception& e) {
out.close();
std::remove(QStrToSysPath(out_filename));
@ -825,16 +899,12 @@ bool ApplyEnergyScaleTask::energyCountProcess(MeasureAnalysisProjectModel* proje
LOG_WARN(QStringLiteral(u"%1能量计数异常:%2").arg(channel_name).arg(e_what));
}
}
return ok;
const QString& info = QStringLiteral(u"能量计数处理完成.");
LOG_INFO(info);
return true;
}
bool ApplyEnergyScaleTask::coincidenceProcess()
{
bool ok = true;
return ok;
}
bool ApplyEnergyScaleTask::processTask()
bool EnergyScaleCoincidenceEventDataTask::processTask()
{
const QString& project_name = GetProjectName();
MeasureAnalysisProjectModel* project_model = ProjectList::Instance()->GetProjectModel(project_name);
@ -848,16 +918,8 @@ bool ApplyEnergyScaleTask::processTask()
if (!energy_scale_data_model.IsValid()) {
return false;
}
if (!scaleParticleData(project_model, energy_scale_data_model)) {
return false;
}
if (!energyCountProcess(project_model, energy_scale_data_model)) {
return false;
}
if (!coincidenceProcess()) {
return false;
}
const QString& info = QStringLiteral(u"应用能量刻度完成.");
const QString& info = QStringLiteral(u"符合能谱数据处理完成.");
LOG_INFO(info);
return true;
}

View File

@ -97,6 +97,17 @@ namespace DataProcessWorkPool
QString _sorted_result_dir;
};
class ParticleDataSortByMinimysTask : public ParticleDataSortTask
{
virtual bool processEveryChannelParticleData() override;
};
class CoincidenceEventAnalysisTask : public DataProcessTask
{
private:
virtual bool processTask() override;
};
class AutoFindPeaksTask : public DataProcessTask {
public:
void SetAnalysisType(AnalysisType analysis_type);
@ -128,15 +139,22 @@ namespace DataProcessWorkPool
QMap<QString, int> _fit_degree_map;
};
class ApplyEnergyScaleTask : public DataProcessTask
class EnergyScaleParticleDataTask : public DataProcessTask
{
private:
bool scaleParticleData(MeasureAnalysisProjectModel* project_model, EnergyScaleDataModel &energy_scale_data_model);
bool energyCountProcess(MeasureAnalysisProjectModel* project_model, EnergyScaleDataModel& energy_scale_data_model);
bool coincidenceProcess();
virtual bool processTask() override;
};
class EnergyCountProcessTask : public DataProcessTask
{
private:
QString _project_name;
virtual bool processTask() override;
};
class EnergyScaleCoincidenceEventDataTask : public DataProcessTask
{
private:
virtual bool processTask() override;
};
}

View File

@ -243,10 +243,13 @@ void MainWindow::initAction()
for (auto it = dock_widget_list.constBegin(); it != dock_widget_list.constEnd(); ++it) {
CDockWidget* dock_widget = *it;
if (dock_widget) {
if ( dock_widget->widget() == view ) {
dock_widget->toggleView();
dock_widget->raise();
view_exist = true;
MeasureAnalysisView* dock_view = dynamic_cast<MeasureAnalysisView*>(dock_widget->widget());
if ( dock_view ) {
if (dock_view->GetViewName() == view->GetViewName()) {
dock_widget->toggleView();
dock_widget->raise();
view_exist = true;
}
}
}
}
@ -265,6 +268,10 @@ void MainWindow::initAction()
}
auto central_area = _dock_manager->centralWidget()->dockAreaWidget();
_dock_manager->addDockWidget(ads::DockWidgetArea::CenterDockWidgetArea, dock_widget, central_area);
} else {
if ( view->IsDeleteOnClose() ) {
delete view;
}
}
}
});

View File

@ -114,8 +114,20 @@ FindPeaksResultDialog::FindPeaksResultDialog(QWidget *parent)
connect(_peaks_result_table, &QTableWidget::currentItemChanged, [this](QTableWidgetItem* current, QTableWidgetItem* previous) {
bool is_watch_item_changed = _peaks_result_table->property("WatchItemChanged").toBool();
if (is_watch_item_changed) {
emit peakInfoChanged(peakInfo(previous, false, false));
emit peakInfoChanged(peakInfo(current, true, true));
int previous_row = -1;
if (previous ) {
previous_row = previous->row();
}
int current_row = -1;
if (current) {
current_row = current->row();
}
if ((previous_row >= 0) && (previous_row != current_row) ) {
emit peakInfoChanged(peakInfo(previous, false, false));
}
if (current_row >= 0) {
emit peakInfoChanged(peakInfo(current, true, true));
}
}
});
@ -200,9 +212,9 @@ void FindPeaksResultDialog::UpdatePeakResult()
QPushButton* btn_remove_row = new QPushButton(QStringLiteral(u"删除"));
btn_remove_row->setMaximumWidth(35);
connect(btn_remove_row, &QPushButton::clicked, [this, item, btn_remove_row]() {
item->setCheckState(Qt::Unchecked);
emit peakInfoChanged(peakInfo(item, false, false));
int remove_row = item->row();
this->_peaks_result_table->item(remove_row, 0)->setCheckState(Qt::Unchecked);
emit peakInfoChanged(peakInfo(item, false, false));
this->_peaks_result_table->removeRow(remove_row);
btn_remove_row->deleteLater();
});

View File

@ -103,6 +103,11 @@ void MeasureAnalysisProjectModel::SetTimeWinConformParticleData(uint time_win, u
this->_time_win_conform_particle_data[time_win][conform_particle_count] = filename;
}
void MeasureAnalysisProjectModel::SetTimeWinConformEnergyData(uint time_win, uint conform_particle_count, const QString& filename)
{
this->_time_win_conform_energy_data[time_win][conform_particle_count] = 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;
@ -225,6 +230,15 @@ const QMap<uint, QString> MeasureAnalysisProjectModel::GetTimeWinConformParticle
return conform_particle_data;
}
const QMap<uint, QString> MeasureAnalysisProjectModel::GetTimeWinConformEnergyDataFilenameList(uint time_win) const
{
QMap<uint, QString> conform_energy_data;
if ( this->_time_win_conform_energy_data.contains(time_win) ) {
conform_energy_data = this->_time_win_conform_energy_data[time_win];
}
return conform_energy_data;
}
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);
@ -617,9 +631,12 @@ void MeasureAnalysisProjectModelList::ApplyEnergyScale(const QString &project_na
}
pro_model->SaveProjectModel();
auto apply_erergy_scale_fit_task = new DataProcessWorkPool::ApplyEnergyScaleTask;
apply_erergy_scale_fit_task->SetFinishedNotifier(this, "onApplyEnergyScaleProcessFinished", project_name);
auto apply_erergy_scale_fit_task = new DataProcessWorkPool::EnergyScaleParticleDataTask;
apply_erergy_scale_fit_task->SetFinishedNotifier(this, "onEnergyScaleParticleDataFinished", project_name);
apply_erergy_scale_fit_task->StartTask();
auto energy_count_process_task = new DataProcessWorkPool::EnergyCountProcessTask;
energy_count_process_task->SetFinishedNotifier(this, "onEnergyCountProcessFinished", project_name);
energy_count_process_task->StartTask();
}
}
}
@ -665,7 +682,12 @@ void MeasureAnalysisProjectModelList::onChannelAddressCountProcessFinished(bool
}
}
void MeasureAnalysisProjectModelList::onApplyEnergyScaleProcessFinished(bool ok, const QString& project_name, const QVariant &data)
void MeasureAnalysisProjectModelList::onEnergyScaleParticleDataFinished(bool ok, const QString &project_name, const QVariant &data)
{
}
void MeasureAnalysisProjectModelList::onEnergyCountProcessFinished(bool ok, const QString &project_name, const QVariant &data)
{
Q_UNUSED(data);
if ( !ok )
@ -703,6 +725,11 @@ void MeasureAnalysisProjectModelList::onApplyEnergyScaleProcessFinished(bool ok,
}
}
void MeasureAnalysisProjectModelList::onCoincidenceProcessFinished(bool ok, const QString &project_name, const QVariant &data)
{
}
void MeasureAnalysisProjectModelList::intiProjectNodeStruce(MeasureAnalysisProjectModel* pro_model)
{
if (!pro_model) {

View File

@ -38,6 +38,7 @@ public:
void SetChannelEnergyCountDataFilename(uint channel, const QString& filename);
void SetAllChannelEnergyTotalCountDataFilename(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 SetAnalysisCustomData(AnalysisType analysis_type, const QString& data_item_name, const QString& data_filename);
const QString& GetProjectDir() const;
@ -61,6 +62,7 @@ public:
const QString GetChannelEnergyCountDataFilename(uint channel) const;
const QString& GetAllChannelEnergyTotalCountDataFilename() const;
const QMap<uint, QString> GetTimeWinConformParticleDataFilenameList(uint time_win) const;
const QMap<uint, QString> GetTimeWinConformEnergyDataFilenameList(uint time_win) const;
const QString GetAnalysisCustomData(AnalysisType analysis_type, const QString& data_item_name);
private:
@ -83,6 +85,7 @@ private:
QMap<uint, QString> _channel_energy_count_data_filename_list;
QString _all_channel_energy_total_count_data_filename;
QMap<uint, QMap<uint, QString> > _time_win_conform_particle_data;
QMap<uint, QMap<uint, QString> > _time_win_conform_energy_data;
QMap<AnalysisType, QMap<QString, QString> > _analysis_custom_data_set;
public:
@ -135,7 +138,9 @@ public:
private slots:
void onChannelAddressCountProcessFinished(bool ok, const QString& project_name, const QVariant& data);
void onApplyEnergyScaleProcessFinished(bool ok, const QString& project_name, const QVariant &data);
void onEnergyScaleParticleDataFinished(bool ok, const QString& project_name, const QVariant& data);
void onEnergyCountProcessFinished(bool ok, const QString& project_name, const QVariant& data);
void onCoincidenceProcessFinished(bool ok, const QString& project_name, const QVariant& data);
private:
void intiProjectNodeStruce(MeasureAnalysisProjectModel *pro_model);

View File

@ -72,8 +72,8 @@ MeasureAnalysisView *MeasureAnalysisView::NewAnalyzeView(AnalysisType view_type)
// new_view->setDeleteOnClose(false);
} break;
case AnalysisType::ParticleInTimeView: {
// new_view = new MeasureAnalysisDataTableView;
// new_view->setDeleteOnClose(false);
new_view = new MeasureAnalysisDataTableView;
new_view->setDeleteOnClose(false);
} break;
case AnalysisType::ParticleTimeDiffView: {
// new_view = new MeasureAnalysisParticleCountPlotView;

View File

@ -200,7 +200,7 @@ void NewMeasureAnalysisDlg::on_btn_ok_clicked()
QMessageBox::warning(this, QStringLiteral(u"警告"), QStringLiteral(u"请选择粒子数据文件!"));
return;
}
auto separate_task = new DataProcessWorkPool::ParticleDataSortTask;
auto separate_task = new DataProcessWorkPool::ParticleDataSortByMinimysTask;
separate_task->SetAllChannelParticleDataFilename(data_file_path);
separate_task->SetSortedResultDir(project_dir_path);
separate_task->SetFinishedNotifier(this, "onNewProjectFromFileFinished", project_name);