From b3ace2cc84bccc5e9becd075feb184d9c4249bc4 Mon Sep 17 00:00:00 2001 From: "Ryan@SOLARIS_testStation" Date: Thu, 29 Aug 2024 14:45:11 -0400 Subject: [PATCH] [MAJOR] Analayzer::UpdateHistograms moved to a worker that in a thread, only tested with CoincidentAnalyzer, need to change others --- FSUDAQ.cpp | 10 ++-- MultiBuilder.cpp | 102 ++++++++++++++++++++------------- MultiBuilder.h | 5 ++ SingleSpectra.cpp | 1 + analyzers/Analyser.cpp | 57 ++++++++++-------- analyzers/Analyser.h | 61 +++++++++++++------- analyzers/CoincidentAnalyzer.h | 17 +++++- 7 files changed, 158 insertions(+), 95 deletions(-) diff --git a/FSUDAQ.cpp b/FSUDAQ.cpp index a158977..6b06d4d 100644 --- a/FSUDAQ.cpp +++ b/FSUDAQ.cpp @@ -1173,6 +1173,7 @@ void FSUDAQ::StartACQ(){ lbScalarACQStatus->setText("ACQ On"); if( singleHistograms ) singleHistograms->startWork(); + if( onlineAnalyzer ) onlineAnalyzer->startWork(); bnStartACQ->setEnabled(false); bnStartACQ->setStyleSheet(""); @@ -1184,7 +1185,6 @@ void FSUDAQ::StartACQ(){ if( digiSettings ) digiSettings->EnableButtons(false); - if( onlineAnalyzer ) onlineAnalyzer->StartThread(); {//^=== elog and database if( influx && chkInflux->isChecked() ){ @@ -1242,11 +1242,9 @@ void FSUDAQ::StopACQ(){ } if( scalar ) scalarTimer->stop(); - - if( onlineAnalyzer ) onlineAnalyzer->StopThread(); if( singleHistograms ) singleHistograms->stopWork(); + if( onlineAnalyzer ) onlineAnalyzer->stopWork(); - lbScalarACQStatus->setText("ACQ Off"); bnStartACQ->setEnabled(true); @@ -1815,7 +1813,7 @@ void FSUDAQ::OpenAnalyzer(){ if( id == 5 ) onlineAnalyzer = new NeutronGamma(digi, nDigi, rawDataPath); if( id >= 0 ) onlineAnalyzer->show(); - if( isACQStarted ) onlineAnalyzer->StartThread(); + if( isACQStarted ) onlineAnalyzer->startWork(); }else{ @@ -1831,7 +1829,7 @@ void FSUDAQ::OpenAnalyzer(){ if( id >= 0 ){ onlineAnalyzer->show(); onlineAnalyzer->activateWindow(); - if( isACQStarted ) onlineAnalyzer->StartThread(); + if( isACQStarted ) onlineAnalyzer->stopWork(); } } diff --git a/MultiBuilder.cpp b/MultiBuilder.cpp index 9907a53..88d0e8d 100644 --- a/MultiBuilder.cpp +++ b/MultiBuilder.cpp @@ -7,15 +7,18 @@ MultiBuilder::MultiBuilder(Data ** multiData, std::vector type, std::vector data = multiData; typeList = type; snList = sn; + numTotCh = 0; for( uShort i = 0; i < nData; i++) { idList.push_back(i); dataSize.push_back(data[i]->GetDataSize()); + numTotCh += data[i]->GetNChannel(); } timeWindow = 100; leftOverTime = 100; breakTime = -1; timeJump = 1e8; lastEventTime = 0; + forceStop = false; ClearEvents(); @@ -29,6 +32,7 @@ MultiBuilder::MultiBuilder(Data * singleData, int type, int sn): nData(1){ DebugPrint("%s", "MultiBuilder"); data = new Data *[1]; data[0] = singleData; + numTotCh = data[0]->GetNChannel(); typeList.push_back(type); snList.push_back(sn); idList.push_back(0); @@ -37,7 +41,7 @@ MultiBuilder::MultiBuilder(Data * singleData, int type, int sn): nData(1){ breakTime = -1; timeJump = 1e8; lastEventTime = 0; - + forceStop = false; ClearEvents(); } @@ -57,6 +61,7 @@ void MultiBuilder::ClearEvents(){ loopIndex[i][j] = 0; nextIndex[i][j] = -1; chExhaused[i][j] = false; + lastBackWardIndex[i][j] = 0; } earlistDigi = -1; @@ -77,7 +82,6 @@ void MultiBuilder::PrintStat(){ if( nextIndex[i][ch] >= 0 ) printf("%d %3d %2d | %7d (%d)\n", i, snList[i], ch, nextIndex[i][ch], loopIndex[i][ch]); } } - } void MultiBuilder::PrintAllEvent(){ @@ -89,7 +93,6 @@ void MultiBuilder::PrintAllEvent(){ events[i][j].Print(); } } - } void MultiBuilder::FindEarlistTimeAndCh(bool verbose){ @@ -100,22 +103,26 @@ void MultiBuilder::FindEarlistTimeAndCh(bool verbose){ nExhaushedCh = 0; for( int i = 0; i < nData; i++){ - for( int j = 0; j < data[i]->GetNChannel(); j++ ) chExhaused[i][j] = false; + for( int j = 0; j < data[i]->GetNChannel(); j++ ) { + chExhaused[i][j] = false; + } for(unsigned int ch = 0; ch < data[i]->GetNChannel(); ch ++){ - int index = data[i]->GetDataIndex(ch); - if( index < 0 ) { - nExhaushedCh ++; - chExhaused[i][ch] = true; - continue; - } + {// check is dataIndex is valid + int index = data[i]->GetDataIndex(ch); + if( index < 0 ) { + nExhaushedCh ++; + chExhaused[i][ch] = true; + continue; + } - if( data[i]->GetTimestamp(ch, index) == 0 || - loopIndex[i][ch] * dataSize[i] > data[i]->GetLoopIndex(ch) * dataSize[i] + data[i]->GetDataIndex(ch)) { - nExhaushedCh ++; - chExhaused[i][ch] = true; - continue; + if( data[i]->GetTimestamp(ch, index) == 0 || + loopIndex[i][ch] * dataSize[i] > data[i]->GetLoopIndex(ch) * dataSize[i] + data[i]->GetDataIndex(ch)) { + nExhaushedCh ++; + chExhaused[i][ch] = true; + continue; + } } if( nextIndex[i][ch] == -1 ) nextIndex[i][ch] = 0; @@ -126,6 +133,7 @@ void MultiBuilder::FindEarlistTimeAndCh(bool verbose){ earlistDigi = i; earlistCh = ch; } + // printf(" ch : %d | time %llu | %llu\n", ch, time, earlistTime); } } @@ -147,7 +155,7 @@ void MultiBuilder::FindLatestTimeAndCh(bool verbose){ for(unsigned int ch = 0; ch < data[i]->GetNChannel(); ch ++){ - if( nextIndex[i][ch] < 0 || data[i]->GetDataIndex(ch) < 0 ) { + if( nextIndex[i][ch] < 0 || data[i]->GetDataIndex(ch) < 0 || nextIndex[i][ch] <= lastBackWardIndex[i][ch] ) { nExhaushedCh ++; chExhaused[i][ch] = true; // printf(", exhanshed. %d \n", nExhaushedCh); @@ -211,6 +219,7 @@ void MultiBuilder::FindLatestTimeOfData(bool verbose){ void MultiBuilder::BuildEvents(bool isFinal, bool skipTrace, bool verbose){ DebugPrint("%s", "MultiBuilder"); + FindEarlistTimeAmongLastData(verbose); // give lastest Time, Ch, and Digi for event building FindEarlistTimeAndCh(verbose); //Give the earliest time, ch, digi @@ -221,6 +230,8 @@ void MultiBuilder::BuildEvents(bool isFinal, bool skipTrace, bool verbose){ Hit em; do{ + if( forceStop ) break; + eventIndex ++; if( eventIndex >= MaxNEvent ) eventIndex = 0; events[eventIndex].clear(); @@ -339,13 +350,16 @@ void MultiBuilder::BuildEvents(bool isFinal, bool skipTrace, bool verbose){ } }while(nExhaushedCh < nData * MaxNChannels); + forceStop = false; + } void MultiBuilder::BuildEventsBackWard(int maxNumEvent, bool verbose){ DebugPrint("%s", "MultiBuilder"); //skip trace, and only build for maxNumEvent events max - // remember the end of DataIndex, prevent over build + // Get the last data index and loop index + for( int k = 0; k < nData; k++){ for( int i = 0; i < data[k]->GetNChannel(); i++){ nextIndex[k][i] = data[k]->GetDataIndex(i); @@ -359,12 +373,11 @@ void MultiBuilder::BuildEventsBackWard(int maxNumEvent, bool verbose){ eventBuilt = 0; Hit em; do{ + if( forceStop ) break; eventIndex ++; if( eventIndex >= MaxNEvent ) eventIndex = 0; events[eventIndex].clear(); - eventBuilt ++; - totalEventBuilt ++; em.Clear(); for( int k = 0; k < nData; k++){ @@ -375,10 +388,9 @@ void MultiBuilder::BuildEventsBackWard(int maxNumEvent, bool verbose){ for( int i = 0; i < numCh; i++){ int ch = (i + latestCh) % numCh; if( chExhaused[bd][ch] ) continue; - //if( nextIndex[bd][ch] <= lastBackWardIndex[bd][ch] || nextIndex[bd][ch] < 0){ - if( nextIndex[bd][ch] < 0){ - chExhaused[bd][ch] = true; + if( nextIndex[bd][ch] <= lastBackWardIndex[bd][ch] || nextIndex[bd][ch] <= 0){ nExhaushedCh ++; + chExhaused[bd][ch] = true; continue; } @@ -406,12 +418,27 @@ void MultiBuilder::BuildEventsBackWard(int maxNumEvent, bool verbose){ if( timeWindow == 0 ) break; } - std::sort(events[eventIndex].begin(), events[eventIndex].end(), [](const Hit& a, const Hit& b) { - return a.timestamp < b.timestamp; - }); FindLatestTimeAndCh(verbose); + if( verbose ) printf(" nExhaushedCh %d | numToCh %d \n", nExhaushedCh, numTotCh); + if( nExhaushedCh == numTotCh ) { + if( verbose ) printf("######################### no more event to be built\n"); + break; + } + if( verbose ) printf("----- next bd: %d, ch : %d, next latest Time : %llu.\n", latestDigi, latestCh, latestTime); + + if( events[eventIndex].size() > 0 ) { + eventBuilt ++; + totalEventBuilt ++; + + std::sort(events[eventIndex].begin(), events[eventIndex].end(), [](const Hit& a, const Hit& b) { + return a.timestamp < b.timestamp; + }); + }else{ + continue; + } + if( verbose ){ printf(">>>>>>>>>>>>>>>>> Event ID : %ld, total built: %ld, multiplicity : %ld\n", eventIndex, totalEventBuilt, events[eventIndex].size()); for( int i = 0; i <(int) events[eventIndex].size(); i++){ @@ -424,24 +451,19 @@ void MultiBuilder::BuildEventsBackWard(int maxNumEvent, bool verbose){ break; } } - printf("%05d, %02d | %5d | %5d %llu \n", sn, chxxx, nextIndex[bd][chxxx], events[eventIndex][i].energy, events[eventIndex][i].timestamp); + printf("%5d, %02d | %5d | %5d %llu \n", sn, chxxx, nextIndex[bd][chxxx], events[eventIndex][i].energy, events[eventIndex][i].timestamp); } - - if( nExhaushedCh == nData * MaxNChannels ) { - printf("######################### no more event to be built\n"); - break; - } - printf("----- next bd: %d, ch : %d, next latest Time : %llu.\n", latestDigi, latestCh, latestTime); - } - }while(nExhaushedCh < nData * MaxNChannels && eventBuilt < maxNumEvent); + }while(nExhaushedCh < numTotCh && eventBuilt < maxNumEvent); - // // remember the end of DataIndex, prevent over build - // for( int k = 0; k < nData; k++){ - // for( int i = 0; i < MaxRegChannel; i++){ - // lastBackWardIndex[k][i] = data[k]->DataIndex[i]; - // } - // } + forceStop = false; + + // remember the end of DataIndex, prevent over build + for( int k = 0; k < nData; k++){ + for( int i = 0; i < data[k]->GetNChannel(); i++){ + lastBackWardIndex[k][i] = data[k]->GetDataIndex(i); + } + } } diff --git a/MultiBuilder.h b/MultiBuilder.h index dd09f58..9fa8d13 100644 --- a/MultiBuilder.h +++ b/MultiBuilder.h @@ -14,6 +14,8 @@ public: MultiBuilder(Data * singleData, int type, int sn); ~MultiBuilder(); + void ForceStop(bool onOff) { forceStop = onOff;} + void SetTimeWindow(unsigned short nanosec) {timeWindow = nanosec; leftOverTime = nanosec;} unsigned short GetTimeWindow() const{return timeWindow;} @@ -48,6 +50,7 @@ private: std::vector tick2ns; const unsigned short nData; Data ** data; // assume all data has MaxNChannel (16) + int numTotCh; // number of total channel = sum digi[i]->GetNChannel() std::vector dataSize; @@ -78,6 +81,8 @@ private: int lastBackWardIndex[MaxNDigitizer][MaxNChannels]; + bool forceStop; + }; diff --git a/SingleSpectra.cpp b/SingleSpectra.cpp index b66be9e..bc08501 100644 --- a/SingleSpectra.cpp +++ b/SingleSpectra.cpp @@ -236,6 +236,7 @@ void SingleSpectra::ChangeHistView(){ void SingleSpectra::FillHistograms(){ // printf("%s | %d %d \n", __func__, chkIsFillHistogram->checkState(), isFillingHistograms); + if( this->isVisible() == false ) return; if( chkIsFillHistogram->checkState() == Qt::Unchecked ) return; if( isFillingHistograms) return; diff --git a/analyzers/Analyser.cpp b/analyzers/Analyser.cpp index 2fcc2ae..0039ecc 100644 --- a/analyzers/Analyser.cpp +++ b/analyzers/Analyser.cpp @@ -30,9 +30,9 @@ Analyzer::Analyzer(Digitizer ** digi, unsigned int nDigi, QMainWindow * parent ) isBuildBackward = false; mb = new MultiBuilder(dataList, typeList, snList); - buildTimerThread = new TimingThread(this); - buildTimerThread->SetWaitTimeinSec(1.0); //^Set event build interval - connect( buildTimerThread, &TimingThread::timeUp, this, &Analyzer::UpdateHistograms); + // buildTimerThread = new TimingThread(this); + // buildTimerThread->SetWaitTimeinSec(1.0); //^Set event build interval + // connect( buildTimerThread, &TimingThread::timeUp, this, &Analyzer::UpdateHistograms); QWidget * layoutWidget = new QWidget(this); setCentralWidget(layoutWidget); @@ -42,19 +42,39 @@ Analyzer::Analyzer(Digitizer ** digi, unsigned int nDigi, QMainWindow * parent ) // QPushButton * bnSetting = new QPushButton("Settings", this); // layout->addWidget(bnSetting); + anaThread = new QThread(this); + anaWorker = new AnalyzerWorker(this); + anaTimer = new QTimer(); + isWorking = false; + + anaWorker->moveToThread(anaThread); + + connect(anaTimer, &QTimer::timeout, anaWorker, [=](){ + if( isWorking ) return; + anaWorker->UpdateHistograms(); + }); + + // connect(anaWorker, &AnalyzerWorker::workDone, this, [=](){ + // printf(" --------- work Done\n"); + // }); + + anaThread->start(); + } Analyzer::~Analyzer(){ - if( buildTimerThread ){ - if( !buildTimerThread->isStopped() ){ - buildTimerThread->Stop(); - buildTimerThread->quit(); - buildTimerThread->wait(); - } - delete buildTimerThread; + printf("Analyzer::%s\n", __func__); + anaTimer->stop(); + + printf(" is anaThread is running %d \n", anaThread->isRunning()); + if( anaThread->isRunning() ){ + anaThread->quit(); + anaThread->wait(); } + printf("------ end of anaThread \n"); + delete influx; delete mb; delete [] dataList; @@ -144,28 +164,17 @@ void Analyzer::RedefineEventBuilder(std::vector idList){ mb = new MultiBuilder(dataList, typeList, snList); } -void Analyzer::StartThread(){ - mb->ClearEvents(); - buildTimerThread->start(); -} - -void Analyzer::StopThread(){ - // printf("%s\n", __func__); - buildTimerThread->Stop(); - buildTimerThread->quit(); - buildTimerThread->wait(); -} - void Analyzer::BuildEvents(bool verbose){ - unsigned int nData = mb->GetNumOfDigitizer(); - std::vector idList = mb->GetDigiIDList(); + // unsigned int nData = mb->GetNumOfDigitizer(); + // std::vector idList = mb->GetDigiIDList(); // for( unsigned int i = 0; i < nData; i++ ) digiMTX[idList[i]].lock(); if( isBuildBackward ){ mb->BuildEventsBackWard(maxNumEventBuilt, verbose); }else{ mb->BuildEvents(0, true, verbose); } + // mb->PrintStat(); // for( unsigned int i = 0; i < nData; i++ ) digiMTX[idList[i]].unlock(); } diff --git a/analyzers/Analyser.h b/analyzers/Analyser.h index 084ae91..e698a7e 100644 --- a/analyzers/Analyser.h +++ b/analyzers/Analyser.h @@ -38,7 +38,7 @@ and recompile FSUDAQ to incorporate the changes and activate the custom analyzer #include "Histogram1D.h" #include "Histogram2D.h" -// class AnalyzerWorker; //Forward decalration +class AnalyzerWorker; //Forward decalration //^============================================== //^============================================== @@ -56,27 +56,40 @@ public: void SetDatabase(QString IP, QString Name, QString Token); double RandomGauss(double mean, double sigma); - -public slots: - void StartThread(); - void StopThread(); void SetDatabaseButton(); - + + double GetUpdateTimeInSec() const {return waitTimeinSec;} + virtual void SetUpCanvas(); virtual void UpdateHistograms(); // where event-building, analysis, and ploting +public slots: + void startWork(){ + // printf("start timer\n"); + mb->ForceStop(false); + mb->ClearEvents(); + anaTimer->start(waitTimeinSec*1000); + } + void stopWork(){ + // printf("stop worker\n"); + anaTimer->stop(); + mb->ForceStop(true); + } + private slots: protected: QGridLayout * layout; void BuildEvents(bool verbose = false); - void SetUpdateTimeInSec(double sec = 1.0) {waitTimeinSec = sec; buildTimerThread->SetWaitTimeinSec(waitTimeinSec);} + void SetUpdateTimeInSec(double sec = 1.0) { waitTimeinSec = sec; } InfluxDB * influx; QString dataBaseIP; QString dataBaseName; QString dataBaseToken; + bool isWorking; // a flag to indicate the worker is working + private: Digitizer ** digi; unsigned short nDigi; @@ -90,29 +103,33 @@ private: MultiBuilder * mb; bool isBuildBackward; int maxNumEventBuilt; - TimingThread * buildTimerThread; + // TimingThread * buildTimerThread; + + QThread * anaThread; + AnalyzerWorker * anaWorker; + QTimer * anaTimer; }; //^================================================ AnalyzerWorker -// class ScalarWorker : public QObject{ -// Q_OBJECT -// public: -// ScalarWorker(Analyzer * parent): SS(parent){} +class AnalyzerWorker : public QObject{ + Q_OBJECT +public: + AnalyzerWorker(Analyzer * parent): SS(parent){} -// public slots: -// void UpdateScalar(){ -// SS->UpdateHistograms(); -// emit workDone(); -// } +public slots: + void UpdateHistograms(){ + SS->UpdateHistograms(); + emit workDone(); + } -// signals: -// void workDone(); +signals: + void workDone(); -// private: -// Analyzer * SS; -// }; +private: + Analyzer * SS; +}; #endif \ No newline at end of file diff --git a/analyzers/CoincidentAnalyzer.h b/analyzers/CoincidentAnalyzer.h index b34db4c..682fb29 100644 --- a/analyzers/CoincidentAnalyzer.h +++ b/analyzers/CoincidentAnalyzer.h @@ -403,16 +403,22 @@ inline void CoincidentAnalyzer::SetUpCanvas(){ inline void CoincidentAnalyzer::UpdateHistograms(){ + // printf(">>>>>>>>>>>>> CoincidentAnalyzer::%s | %d %d %d \n", __func__, this->isVisible(), chkRunAnalyzer->isChecked(), isWorking); + if( this->isVisible() == false ) return; if( chkRunAnalyzer->isChecked() == false ) return; + if( isWorking ) return; + isWorking = true; // This is important. set the isWorking = true to prevent another call of UpdateHistograms() + unsigned long long t0 = getTime_ns(); - BuildEvents(); // call the event builder to build events + BuildEvents(false); // call the event builder to build events // unsigned long long t1 = getTime_ns(); // printf("Event Build time : %llu ns = %.f msec\n", t1 - t0, (t1-t0)/1e6); //============ Get events, and do analysis long eventBuilt = evtbder->eventBuilt; + if( eventBuilt == 0 ) return; //============ Get the cut list, if any @@ -450,7 +456,7 @@ inline void CoincidentAnalyzer::UpdateHistograms(){ int xE = -1, yE = -1; unsigned long long xT = 0; for( int k = 0; k < (int) event.size(); k++ ){ - //event[k].Print(); + // event[k].Print(); if( event[k].sn == a_sn && event[k].ch == a_ch) { h1->Fill(event[k].energy); aE = event[k].energy; @@ -478,10 +484,11 @@ inline void CoincidentAnalyzer::UpdateHistograms(){ } unsigned long long ta = getTime_ns(); - if( ta - t0 > sbUpdateTime->value() * 0.9 * 1e9 ) break; + if( ta - t0 > sbUpdateTime->value() * 0.9 * GetUpdateTimeInSec() * 1e9 ) break; } + // printf("--------------- update histograms\n"); h2D->UpdatePlot(); h1->UpdatePlot(); hMulti->UpdatePlot(); @@ -502,6 +509,10 @@ inline void CoincidentAnalyzer::UpdateHistograms(){ influx->WriteData(dataBaseName.toStdString()); influx->ClearDataPointsBuffer(); } + + // printf("<<<<<<<<<<<<< end of UpdateHistorgams\n"); + + isWorking = false; } inline void CoincidentAnalyzer::SaveSettings(){