From 5b58083fb3d9f2c923e6b7b5df5fbe78b771801a Mon Sep 17 00:00:00 2001 From: splitPoleDAQ Date: Fri, 26 May 2023 18:06:37 -0400 Subject: [PATCH] added OnlineAnalyser.h/cpp --- .vscode/settings.json | 3 +- CanvasClass.cpp | 2 +- CanvasClass.h | 10 +--- ClassData.h | 61 +++++++++------------ CustomThreads.h | 1 + CustomWidgets.h | 21 ++++---- FSUDAQ.cpp | 22 ++++++-- FSUDAQ.h | 9 ++++ FSUDAQ_Qt6.pro | 4 +- OnlineAnalyser.cpp | 78 +++++++++++++++++++++++++++ OnlineAnalyser.h | 118 +++++++++++++++++++++++++++++++++++++++++ OnlineEventBuilder.cpp | 3 +- Scope.cpp | 6 +-- Scope.h | 4 +- 14 files changed, 273 insertions(+), 69 deletions(-) create mode 100644 OnlineAnalyser.cpp create mode 100644 OnlineAnalyser.h diff --git a/.vscode/settings.json b/.vscode/settings.json index 0378a2e..a1f3254 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -151,6 +151,7 @@ "typeinfo": "cpp", "variant": "cpp", "qmainwindow": "cpp", - "qchartview": "cpp" + "qchartview": "cpp", + "qthread": "cpp" } } \ No newline at end of file diff --git a/CanvasClass.cpp b/CanvasClass.cpp index 3c63a80..3ea4749 100644 --- a/CanvasClass.cpp +++ b/CanvasClass.cpp @@ -61,7 +61,7 @@ Canvas::Canvas(Digitizer ** digi, unsigned int nDigi, QMainWindow * parent) : QM for( int j = 0; j < MaxNChannels; j++){ if( i < nDigi ) { hist[i][j] = new Histogram("Digi-" + QString::number(digi[i]->GetSerialNumber()) +", Ch-" + QString::number(j), xMin, xMax, nBin); - histView[i][j] = new TraceView(hist[i][j]->GetTrace()); + histView[i][j] = new RChartView(hist[i][j]->GetChart()); histView[i][j]->SetVRange(0, 10); }else{ hist[i][j] = nullptr; diff --git a/CanvasClass.h b/CanvasClass.h index 768cd58..6937c5c 100644 --- a/CanvasClass.h +++ b/CanvasClass.h @@ -4,18 +4,12 @@ #include #include #include -#include #include #include #include #include -#include #include #include -#include -#include -#include -#include #include "macro.h" #include "ClassDigitizer.h" @@ -42,7 +36,7 @@ private: unsigned short nDigi; Histogram * hist[MaxNDigitizer][MaxNChannels]; - TraceView * histView[MaxNDigitizer][MaxNChannels]; + RChartView * histView[MaxNDigitizer][MaxNChannels]; RComboBox * cbDivision; @@ -54,6 +48,4 @@ private: int oldBd, oldCh; }; - - #endif \ No newline at end of file diff --git a/ClassData.h b/ClassData.h index 4aa9189..0f8ef12 100644 --- a/ClassData.h +++ b/ClassData.h @@ -57,10 +57,6 @@ class Data{ void Allocate80MBMemory(); void AllocateMemory(uint32_t size); - void SetSaveWaveToMemory(bool OnOff) { // store the waveform in memory - this->SaveWaveToMemory = OnOff; - } - void ClearData(); void ClearTriggerRate(); void ClearBuffer(); @@ -86,7 +82,7 @@ class Data{ protected: unsigned int nw; - bool SaveWaveToMemory; + //bool SaveWaveToMemory; ///for temperary std::vector tempWaveform1; @@ -123,7 +119,6 @@ inline Data::Data(){ for ( int i = 0; i < MaxNChannels; i++) TotNumEvents[i] = 0; ClearData(); ClearTriggerRate(); - SaveWaveToMemory = true; nw = 0; outFileIndex = 0; @@ -376,7 +371,6 @@ inline void Data::DecodeBuffer(bool fastDecode, int verbose){ continue; } - //TODO ====== when NumEventsDecoded is too small, the trigger rate is not reliable? if( NumEventsDecoded[ch] > 4 ){ int indexStart = DataIndex[ch] - NumEventsDecoded[ch] + 1; @@ -523,9 +517,8 @@ inline int Data::DecodePHADualChannelBlock(unsigned int ChannelMask, bool fastDe int channel = ChannelMask*2 + channelTag; if( verbose >= 2 ) printf("ch : %d, timeStamp0 %u \n", channel, timeStamp0); - //TODO Skip ///===== read waveform - if( !fastDecode && SaveWaveToMemory ) { + if( !fastDecode ) { tempWaveform1.clear(); tempWaveform2.clear(); tempDigiWaveform1.clear(); @@ -561,18 +554,16 @@ inline int Data::DecodePHADualChannelBlock(unsigned int ChannelMask, bool fastDe trace0 = static_cast(wave0); } - if( SaveWaveToMemory){ - if( hasDualTrace ){ - tempWaveform1.push_back(trace1); - tempWaveform2.push_back(trace0); - tempDigiWaveform1.push_back(dp1); - tempDigiWaveform2.push_back(dp0); - }else{ - tempWaveform1.push_back(trace1); - tempWaveform1.push_back(trace0); - tempDigiWaveform1.push_back(dp1); - tempDigiWaveform1.push_back(dp0); - } + if( hasDualTrace ){ + tempWaveform1.push_back(trace1); + tempWaveform2.push_back(trace0); + tempDigiWaveform1.push_back(dp1); + tempDigiWaveform2.push_back(dp0); + }else{ + tempWaveform1.push_back(trace1); + tempWaveform1.push_back(trace0); + tempDigiWaveform1.push_back(dp1); + tempDigiWaveform1.push_back(dp0); } if( isTrigger0 == 1 ) triggerAtSample = 2*wi ; @@ -641,7 +632,7 @@ inline int Data::DecodePHADualChannelBlock(unsigned int ChannelMask, bool fastDe NumNonPileUpDecoded[channel] ++; } - if( SaveWaveToMemory ) { + if( !fastDecode ) { if( hasDualTrace ){ Waveform1[channel][DataIndex[channel]] = tempWaveform1; Waveform2[channel][DataIndex[channel]] = tempWaveform2; @@ -759,7 +750,7 @@ inline int Data::DecodePSDDualChannelBlock(unsigned int ChannelMask, bool fastDe if( verbose >= 2 ) printf("ch : %d, timeStamp %u \n", channel, timeStamp0); ///===== read waveform - if( !fastDecode && SaveWaveToMemory ) { + if( !fastDecode ) { tempWaveform1.clear(); tempWaveform2.clear(); tempDigiWaveform1.clear(); @@ -779,19 +770,17 @@ inline int Data::DecodePSDDualChannelBlock(unsigned int ChannelMask, bool fastDe bool dp1a = (( word >> 14 ) & 0x1 ); unsigned short wavea = ( word & 0x3FFF); - if( SaveWaveToMemory){ - if( hasDualTrace ){ - tempWaveform1.push_back(wavea); - tempWaveform2.push_back(waveb); - }else{ - tempWaveform1.push_back(wavea); - tempWaveform1.push_back(waveb); - } - tempDigiWaveform1.push_back(dp1a); - tempDigiWaveform1.push_back(dp1b); - tempDigiWaveform2.push_back(dp2a); - tempDigiWaveform2.push_back(dp2b); + if( hasDualTrace ){ + tempWaveform1.push_back(wavea); + tempWaveform2.push_back(waveb); + }else{ + tempWaveform1.push_back(wavea); + tempWaveform1.push_back(waveb); } + tempDigiWaveform1.push_back(dp1a); + tempDigiWaveform1.push_back(dp1b); + tempDigiWaveform2.push_back(dp2a); + tempDigiWaveform2.push_back(dp2b); if( verbose >= 3 ){ printf("%4d| %5d, %d, %d \n", 2*wi, wavea, dp1a, dp2a); @@ -827,7 +816,7 @@ inline int Data::DecodePSDDualChannelBlock(unsigned int ChannelMask, bool fastDe Energy2[channel][DataIndex[channel]] = Qlong; Timestamp[channel][DataIndex[channel]] = timeStamp; - if( SaveWaveToMemory ) { + if( !fastDecode ) { if( hasDualTrace ){ Waveform1[channel][DataIndex[channel]] = tempWaveform1; Waveform2[channel][DataIndex[channel]] = tempWaveform2; diff --git a/CustomThreads.h b/CustomThreads.h index 8daa8cf..285b777 100644 --- a/CustomThreads.h +++ b/CustomThreads.h @@ -39,6 +39,7 @@ public: readCount ++; if( stop) break; + if( ret == CAEN_DGTZ_Success && !stop){ digiMTX[ID].lock(); digi->GetData()->DecodeBuffer(!isScope, 0); diff --git a/CustomWidgets.h b/CustomWidgets.h index 1ddb831..7ef5599 100644 --- a/CustomWidgets.h +++ b/CustomWidgets.h @@ -60,14 +60,14 @@ class RComboBox : public QComboBox{ }; //^==================================================== -class Trace : public QChart{ +class RChart : public QChart{ public: - explicit Trace(QGraphicsItem *parent = nullptr, Qt::WindowFlags wFlags = {}) + explicit RChart(QGraphicsItem *parent = nullptr, Qt::WindowFlags wFlags = {}) : QChart(QChart::ChartTypeCartesian, parent, wFlags){ grabGesture(Qt::PanGesture); grabGesture(Qt::PinchGesture); } - ~Trace(){} + ~RChart(){} protected: bool sceneEvent(QEvent *event){ @@ -94,9 +94,9 @@ private: }; //^==================================================== -class TraceView : public QChartView{ +class RChartView : public QChartView{ public: - TraceView(QChart * chart, QWidget * parent = nullptr): QChartView(chart, parent){ + RChartView(QChart * chart, QWidget * parent = nullptr): QChartView(chart, parent){ m_isTouching = false; this->setRubberBand(QChartView::RectangleRubberBand); @@ -110,6 +110,9 @@ public: vRangeMin = -(0x1FFF); vRangeMax = 0x1FFF; + + hRangeMin = 0; + hRangeMax = 0; } void SetHRange(int min, int max) { @@ -161,7 +164,7 @@ protected: case Qt::Key_R : //chart()->axes(Qt::Vertical).first()->setRange(-(0x1FFF), 0x1FFF); chart()->axes(Qt::Vertical).first()->setRange(vRangeMin, vRangeMax); - //chart()->axes(Qt::Horizontal).first()->setRange(hRangeMin, hRangeMax); + if( hRangeMax != hRangeMin ) chart()->axes(Qt::Horizontal).first()->setRange(hRangeMin, hRangeMax); break; default: QGraphicsView::keyPressEvent(event); break; } @@ -181,7 +184,7 @@ class Histogram { public: Histogram(QString title, double xMin, double xMax, int nBin){ - plot = new Trace(); + plot = new RChart(); dataSeries = new QLineSeries(); Rebin(xMin, xMax, nBin); @@ -216,7 +219,7 @@ public: delete plot; } - Trace * GetTrace() { return plot;} + RChart * GetChart() { return plot;} void Clear(){ for( int i = 0; i <= nBin; i++) { @@ -267,7 +270,7 @@ public: } private: - Trace * plot; + RChart * plot; QLineSeries * dataSeries; QAreaSeries * areaSeries; diff --git a/FSUDAQ.cpp b/FSUDAQ.cpp index d5b900a..5c11a93 100644 --- a/FSUDAQ.cpp +++ b/FSUDAQ.cpp @@ -26,6 +26,7 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent){ scope = nullptr; digiSettings = nullptr; canvas = nullptr; + onlineAnalyzer = nullptr; QWidget * mainLayoutWidget = new QWidget(this); setCentralWidget(mainLayoutWidget); @@ -55,8 +56,7 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent){ bnAnalyzer = new QPushButton("Online Analyzer", this); layout->addWidget(bnAnalyzer, 0, 2); - connect(bnAnalyzer, &QPushButton::clicked, this, &MainWindow::OpenScope); - bnAnalyzer->setEnabled(false); + connect(bnAnalyzer, &QPushButton::clicked, this, &MainWindow::OpenAnalyzer); bnCanvas = new QPushButton("Online 1D Histograms", this); layout->addWidget(bnCanvas, 1, 2); @@ -287,6 +287,8 @@ MainWindow::~MainWindow(){ if( canvas ) delete canvas; + if( onlineAnalyzer ) delete onlineAnalyzer; + if( scalar ) { CleanUpScalar(); scalarThread->Stop(); @@ -611,6 +613,7 @@ void MainWindow::WaitForDigitizersOpen(bool onOff){ bnStopACQ->setEnabled(!onOff); chkSaveData->setEnabled(!onOff); bnCanvas->setEnabled(!onOff); + bnAnalyzer->setEnabled(!onOff); } @@ -813,7 +816,6 @@ void MainWindow::StartACQ(){ readDataThread[i]->SetSaveData(chkSaveData->isChecked()); LogMsg("Digi-" + QString::number(digi[i]->GetSerialNumber()) + " is starting ACQ." ); digi[i]->WriteRegister(DPP::SoftwareClear_W, 1); - digi[i]->GetData()->SetSaveWaveToMemory(false); digi[i]->StartACQ(); readDataThread[i]->start(); } @@ -1067,7 +1069,6 @@ void MainWindow::OpenScope(){ bnStartACQ->setEnabled(false); bnStopACQ->setEnabled(false); - chkSaveData->setChecked(false); } @@ -1101,6 +1102,19 @@ void MainWindow::OpenCanvas(){ canvas->activateWindow(); } +} +//*************************************************************** +//*************************************************************** +void MainWindow::OpenAnalyzer(){ + + if( onlineAnalyzer == nullptr ) { + onlineAnalyzer = new OnlineAnalyzer(digi, nDigi); + onlineAnalyzer->show(); + }else{ + onlineAnalyzer->show(); + onlineAnalyzer->activateWindow(); + } + } //*************************************************************** diff --git a/FSUDAQ.h b/FSUDAQ.h index a6e2368..64b695d 100644 --- a/FSUDAQ.h +++ b/FSUDAQ.h @@ -18,6 +18,7 @@ #include "DigiSettingsPanel.h" #include "CanvasClass.h" #include "influxdb.h" +#include "OnlineAnalyser.h" //^#===================================================== MainWindow class MainWindow : public QMainWindow{ @@ -30,6 +31,7 @@ public: if( scope ) scope->close(); if( digiSettings ) digiSettings->close(); if( canvas ) canvas->close(); + if( onlineAnalyzer ) onlineAnalyzer->close(); event->accept(); } @@ -62,6 +64,8 @@ private slots: void OpenCanvas(); + void OpenAnalyzer(); + void UpdateAllPanels(int panelID); void SetUpInflux(); @@ -70,6 +74,7 @@ private slots: void WriteElog(QString htmlText, QString subject, QString category, int runNumber); void AppendElog(QString appendHtmlText); + private: Digitizer ** digi; @@ -149,6 +154,10 @@ private: Canvas * canvas; TimingThread * histThread; + //@----- Analyzer + OnlineAnalyzer * onlineAnalyzer; + + }; diff --git a/FSUDAQ_Qt6.pro b/FSUDAQ_Qt6.pro index df89840..5808eb6 100644 --- a/FSUDAQ_Qt6.pro +++ b/FSUDAQ_Qt6.pro @@ -33,7 +33,8 @@ HEADERS += ClassData.h \ influxdb.h\ Scope.h \ CanvasClass.h \ - OnlineEventBuilder.h + OnlineEventBuilder.h \ + OnlineAnalyser.h SOURCES += ClassDigitizer.cpp \ DigiSettingsPanel.cpp \ FSUDAQ.cpp \ @@ -42,3 +43,4 @@ SOURCES += ClassDigitizer.cpp \ Scope.cpp \ CanvasClass.cpp \ OnlineEventBuilder.cpp \ + OnlineAnalyser.cpp diff --git a/OnlineAnalyser.cpp b/OnlineAnalyser.cpp new file mode 100644 index 0000000..c504546 --- /dev/null +++ b/OnlineAnalyser.cpp @@ -0,0 +1,78 @@ +#include "OnlineAnalyser.h" + +#include +#include + +OnlineAnalyzer::OnlineAnalyzer(Digitizer ** digi, unsigned int nDigi, QMainWindow * parent ): QMainWindow(parent){ + + this->digi = digi; + this->nDigi = nDigi; + + oeb = new OnlineEventBuilder * [nDigi]; + for( unsigned int i = 0; i < nDigi; i++ ) oeb[i] = new OnlineEventBuilder(digi[i]); + + buildTimerThread = new TimingThread(this); + buildTimerThread->SetWaitTimeinSec(1.0); //^Set event build interval + connect( buildTimerThread, &TimingThread::timeUp, this, &OnlineAnalyzer::UpdateHistograms); + + setWindowTitle("Online Analyzer"); + setGeometry(0, 0, 1000, 800); + + QWidget * layoutWidget = new QWidget(this); + setCentralWidget(layoutWidget); + layout = new QGridLayout(layoutWidget); + layoutWidget->setLayout(layout); + + // QPushButton * bnSetting = new QPushButton("Settings", this); + // layout->addWidget(bnSetting); + + SetUpCanvas(); + +} + +OnlineAnalyzer::~OnlineAnalyzer(){ + + for( unsigned int i = 0; i < nDigi; i++ ) delete oeb[i]; + delete [] oeb; + +} + +void OnlineAnalyzer::StartThread(){ + +} + +void OnlineAnalyzer::StopThread(){ + +} + +void OnlineAnalyzer::SetUpCanvas(){ + + //TODO a simple way to set it at once + Histogram2D * h2 = new Histogram2D("testing", -10, 10, -10, 10); + RChartView * h2View = new RChartView(h2->GetChart()); + h2View->SetVRange(-10, 10); // this only set the reset key 'r' + h2View->SetHRange(-10, 10); + + layout->addWidget(h2View); + + std::random_device rd; + std::mt19937 gen(rd()); + std::normal_distribution distribution(0.0, 2.0); + + for( int i = 0; i < 1000 ; i++ ){ + h2->Fill(distribution(gen), distribution(gen)); + } + +} + +void OnlineAnalyzer::UpdateHistograms(){ + + //Set with digitizer to be event build + digiMTX[0].lock(); + oeb[0]->BuildEvents(100); + digiMTX[0].unlock(); + + //============ Get events, and do analysis + + +} \ No newline at end of file diff --git a/OnlineAnalyser.h b/OnlineAnalyser.h new file mode 100644 index 0000000..e24dd92 --- /dev/null +++ b/OnlineAnalyser.h @@ -0,0 +1,118 @@ +#ifndef ONLINE_ANALYZER_H +#define ONLINE_ANALYZER_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "macro.h" +#include "ClassDigitizer.h" +#include "CustomThreads.h" +#include "CustomWidgets.h" +#include "OnlineEventBuilder.h" + +/************************************** + +This class is for, obviously, Online analysis. + +It provides essential event building, histograms, and filling. + +This is the mother of all other derivative analysis class. + +derivative class should define the SetUpCanvas() and UpdateHistogram(); + +***************************************/ + + +#include + +//^============================================== +//^============================================== +class Histogram2D{ +public: + Histogram2D(QString title, double xMin, double xMax, double yMin, double yMax){ + + this->xMin = xMin; + this->xMax = xMax; + this->yMin = yMin; + this->yMax = yMax; + + plot = new RChart(); + scatterSeries = new QScatterSeries(); + scatterSeries->setName(title); + scatterSeries->setMarkerShape(QScatterSeries::MarkerShapeCircle); + scatterSeries->setBorderColor(QColor(0,0,0,0)); + scatterSeries->setMarkerSize(5.0); + + plot->addSeries(scatterSeries); + plot->createDefaultAxes(); + + QValueAxis * xaxis = qobject_cast (plot->axes(Qt::Horizontal).first()); + xaxis->setRange(xMin, xMax); + + QValueAxis * yaxis = qobject_cast (plot->axes(Qt::Vertical).first()); + yaxis->setRange(yMin, yMax); + + } + + ~Histogram2D(){ + delete scatterSeries; + delete plot; + } + + double GetXMin() const {return xMin;} + double GetXMax() const {return xMax;} + double GetyMin() const {return yMin;} + double GetyMax() const {return yMax;} + + RChart * GetChart() {return plot;} + void SetMarkerColor(QColor color) { scatterSeries->setColor(color); } + void SetMarkerSize(qreal size) { scatterSeries->setMarkerSize(size);} + void Clear(){ scatterSeries->clear();} + void Fill(double x, double y) { scatterSeries->append(x, y); } + +private: + double xMin, xMax, yMin, yMax; + + RChart * plot; + QScatterSeries * scatterSeries; + +}; + +//^============================================== +//^============================================== +class OnlineAnalyzer : public QMainWindow{ + Q_OBJECT + +public: + OnlineAnalyzer(Digitizer ** digi, unsigned int nDigi, QMainWindow * parent = nullptr); + virtual ~OnlineAnalyzer(); + + virtual void SetUpCanvas(); + +public slots: + void StartThread(); + void StopThread(); + +private slots: + + virtual void UpdateHistograms(); // where event-building, analysis, and ploting + +private: + + Digitizer ** digi; + unsigned short nDigi; + + OnlineEventBuilder ** oeb; + TimingThread * buildTimerThread; + + QGridLayout * layout; + +}; +#endif \ No newline at end of file diff --git a/OnlineEventBuilder.cpp b/OnlineEventBuilder.cpp index 686f01f..ab5a1b8 100644 --- a/OnlineEventBuilder.cpp +++ b/OnlineEventBuilder.cpp @@ -27,7 +27,6 @@ OnlineEventBuilder::~OnlineEventBuilder(){ } - void OnlineEventBuilder::FindEarlistTimeAndCh(){ earlistTime = -1; @@ -38,7 +37,7 @@ void OnlineEventBuilder::FindEarlistTimeAndCh(){ chExhaused[i] = false; } - for(unsigned int ch = 0; ch < nCh; ch ++){ + for(unsigned int ch = 0; ch < nCh; ch ++){ if( data->DataIndex[ch] == -1 || nextIndex[ch] > data->DataIndex[ch]) { nExhaushedCh ++; chExhaused[ch] = true; diff --git a/Scope.cpp b/Scope.cpp index 8a04392..78708b4 100644 --- a/Scope.cpp +++ b/Scope.cpp @@ -19,7 +19,7 @@ Scope::Scope(Digitizer ** digi, unsigned int nDigi, ReadDataThread ** readDataTh enableSignalSlot = false; - plot = new Trace(); + plot = new RChart(); for( int i = 0; i < MaxNumberOfTrace; i++) { dataTrace[i] = new QLineSeries(); dataTrace[i]->setName("Trace " + QString::number(i)); @@ -153,7 +153,7 @@ Scope::Scope(Digitizer ** digi, unsigned int nDigi, ReadDataThread ** readDataTh } //================ Plot view rowID ++; - plotView = new TraceView(plot, this); + plotView = new RChartView(plot, this); layout->addWidget(plotView, rowID, 0, 1, 6); @@ -233,8 +233,6 @@ void Scope::StartScope(){ traceOn[iDigi] = digi[iDigi]->IsRecordTrace(); //remember setting digi[iDigi]->SetBits(DPP::BoardConfiguration, DPP::Bit_BoardConfig::RecordTrace, 1, -1); - digi[iDigi]->GetData()->SetSaveWaveToMemory(true); - digi[iDigi]->StartACQ(); printf("----- readDataThread running ? %d.\n", readDataThread[iDigi]->isRunning()); diff --git a/Scope.h b/Scope.h index c33f6e9..013fee9 100644 --- a/Scope.h +++ b/Scope.h @@ -79,8 +79,8 @@ private: bool enableSignalSlot; - Trace * plot; - TraceView * plotView; + RChart * plot; + RChartView * plotView; QLineSeries * dataTrace[MaxNumberOfTrace]; // 2 analog, 2 digi RComboBox * cbScopeDigi;