#include "ParticleTimeDifferenceView.h" #include "CustomQwtPlot.h" #include "csv.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "BusyIndicator.h" #include ParticleTimeDifferenceView::ParticleTimeDifferenceView(QWidget *parent) : MeasureAnalysisView { parent } { this->setViewType(PlotFrame); QHBoxLayout* layout = new QHBoxLayout(this); this->_plot = new CustomQwtPlot(this); layout->addWidget(this->_plot); setupPlot(); this->_menu = new QMenu(this); setupMenu(); _busy_indicator = new BusyIndicatorWidget(this); } ParticleTimeDifferenceView::~ParticleTimeDifferenceView() { LOG_DEBUG(QStringLiteral(u"%1析构.").arg(this->GetViewName())); } void ParticleTimeDifferenceView::InitViewWorkspace(const QString &project_name) { Q_UNUSED(project_name); } void ParticleTimeDifferenceView::SetAnalyzeDataFilename(const QMap &data_files_set) { if ( !data_files_set.isEmpty() ) { const QString& data_name = data_files_set.firstKey(); const QString& data_filename = data_files_set.first().toString(); if (QFileInfo(data_filename).exists()) { this->_data_filename = data_filename; auto functionToRun = [this](){ this->loadDataFromFile(); }; QThread* load_data_thread = QThread::create(functionToRun); load_data_thread->start(); } } } void ParticleTimeDifferenceView::setupPlot() { _plot->setCanvasBackground(Qt::white); QwtPlotCanvas* canvas = qobject_cast(_plot->canvas()); canvas->setFrameStyle(QFrame::NoFrame); QFont font = this->font(); font.setBold(false); QwtText energy_label = QStringLiteral(u"时间(ns)"); energy_label.setFont(font); QwtText count_label = QStringLiteral(u"计数"); count_label.setFont(font); _plot->setAxisTitle(QwtPlot::xBottom, energy_label); _plot->setAxisTitle(QwtPlot::yLeft, count_label); // set axis auto scale _plot->setAxisAutoScale(QwtPlot::xBottom, false); _plot->setAxisAutoScale(QwtPlot::yLeft, false); _plot->enableAxis(QwtPlot::xBottom); _plot->enableAxis(QwtPlot::yLeft); _plot->SetAxisDragScale(QwtPlot::xBottom, true); _plot->SetAxisDragScale(QwtPlot::yLeft, true); _histogram = new QwtPlotHistogram("粒子时间差分布"); _histogram->setStyle(QwtPlotHistogram::Columns); _histogram->attach(_plot); } void ParticleTimeDifferenceView::setupMenu() { this->setContextMenuPolicy(Qt::CustomContextMenu); connect(this, &ParticleTimeDifferenceView::customContextMenuRequested, [this](const QPoint& pos) { this->_menu->exec(this->mapToGlobal(pos)); }); QAction* action_plot_reset = this->_menu->addAction(QStringLiteral(u"还原")); action_plot_reset->setObjectName("plot_reset"); connect(action_plot_reset, &QAction::triggered, [this]() { this->_plot->ResetPlot(); }); this->_menu->addSeparator(); this->_menu->addSeparator(); QAction* action_plot_config = this->_menu->addAction(QStringLiteral(u"图表配置")); action_plot_config->setObjectName("plot_config"); connect(action_plot_config, &QAction::triggered, this, &ParticleTimeDifferenceView::onActionPlotConfigure); } void ParticleTimeDifferenceView::loadDataFromFile() { _busy_indicator->Start(); try { std::string board_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 time_str = QString(QStringLiteral(u"时间计数")).toStdString(); io::CSVReader< 4, io::trim_chars<' ', '\t'>, io::double_quote_escape<',', '"'>, io::throw_on_overflow, io::empty_line_comment> reader(QStrToSysPath(this->_data_filename)); reader.read_header(io::ignore_extra_column, board_id_str, channel_id_str, address_str, time_str); QMap hist_map; uint board_id, channel_id, address; unsigned long long time1 = 0, time2; while (reader.read_row(board_id, channel_id, address, time2)) { if (time1 == 0) { time1 = time2; continue; } unsigned long long d_time = time2 - time1; double bin = floor(d_time / _bin_width) * _bin_width; hist_map[bin]++; time1 = time2; } double x_max = 0.0f, y_max = 0.0f; QVector samples; for (const double& bin : hist_map.keys()) { const unsigned long long& count = hist_map.value(bin); double bin_max = bin + _bin_width; samples.append(QwtIntervalSample(count, bin, bin_max)); if ( x_max < bin_max ) x_max = bin_max; if ( y_max < count ) y_max = count; } QMetaObject::invokeMethod(this, [this, samples, x_max, y_max]() { _histogram->setData(new QwtIntervalSeriesData(samples)); _plot->SetAxisInitRange(QwtPlot::xBottom, 0.0f, x_max); _plot->SetAxisInitRange(QwtPlot::yLeft, 0.0f, y_max); _plot->replot(); const QString& info = QStringLiteral(u"粒子时间差分析处理完成."); LOG_INFO(info); }, Qt::QueuedConnection); } catch (const std::exception& e) { const QString& e_what = QString::fromStdString(e.what()); LOG_WARN(QStringLiteral(u"粒子时间差分析处理异常:%1").arg(e_what)); } QMetaObject::invokeMethod(this, [this]() { _busy_indicator->Stop(); }, Qt::QueuedConnection); } void ParticleTimeDifferenceView::onActionPlotConfigure() { } void ParticleTimeDifferenceView::showEvent(QShowEvent *e) { Q_UNUSED(e); if (_busy_indicator) { _busy_indicator->setGeometry(this->rect()); this->update(); } }