From 25d074a3932401738f6e8fd92ac156ab594363bd Mon Sep 17 00:00:00 2001 From: "Ryan@SOLARIS_testStation" Date: Mon, 30 Sep 2024 18:38:48 -0400 Subject: [PATCH 01/35] update the master branch from 0ee20bc --- DigiSettingsPanel.cpp | 2 +- FSUDAQ | 6 +- FSUDAQ.cpp | 30 ++-- FSUDAQ_Qt6.pro | 23 +-- Histogram1D.h | 2 + Histogram2D.h | 6 +- MultiBuilder.cpp | 180 +++++++++++++----------- SingleSpectra.cpp | 17 +++ SingleSpectra.h | 2 + analyzers/Analyser.cpp | 11 +- analyzers/Analyser.h | 6 +- analyzers/Cross.h | 311 +++++++++++++++++++++++++++++++++++++++++ macro.h | 9 ++ 13 files changed, 490 insertions(+), 115 deletions(-) create mode 100644 analyzers/Cross.h diff --git a/DigiSettingsPanel.cpp b/DigiSettingsPanel.cpp index 264a8a2..8d682cf 100644 --- a/DigiSettingsPanel.cpp +++ b/DigiSettingsPanel.cpp @@ -3634,7 +3634,7 @@ void DigiSettingsPanel::SyncCheckBox(QCheckBox *(&chk)[][MaxRegChannel+1]){ } void DigiSettingsPanel::EnableButtons(bool enable){ - for( int i = 0; i < nDigi; i++ ){ + for( unsigned int i = 0; i < nDigi; i++ ){ if( !enable ) { leSaveFilePath[i]->setText("changing setting is disabled due to ACQ is running."); leSaveFilePath[i]->setStyleSheet("color:red;"); diff --git a/FSUDAQ b/FSUDAQ index 04a3b23..a990aef 100755 --- a/FSUDAQ +++ b/FSUDAQ @@ -2,6 +2,10 @@ timestamp=$(date +%Y%m%d_%H%M%S) -outFile=program_${timestamp}.log +outFile=log/program_${timestamp}.log + +mkdir -p "$(dirname "$outFile")" + +echo "FSUDAQ, save stdout to $outFile" stdbuf -oL ./FSUDAQ_Qt6 | tee $outFile \ No newline at end of file diff --git a/FSUDAQ.cpp b/FSUDAQ.cpp index e4a74bf..676fc7d 100644 --- a/FSUDAQ.cpp +++ b/FSUDAQ.cpp @@ -19,10 +19,10 @@ #include "analyzers/SplitPoleAnalyzer.h" #include "analyzers/EncoreAnalyzer.h" #include "analyzers/MUSICAnalyzer.h" -#include "analyzers/RAISOR.h" #include "analyzers/NeutronGamma.h" +#include "analyzers/Cross.h" -std::vector onlineAnalyzerList = {"Coincident","Splie-Pole", "Encore", "RAISOR", "MUSICS", "Neutron-Gamma"}; +std::vector onlineAnalyzerList = {"Coincident","Splie-Pole", "Encore", "MUSICS", "Neutron-Gamma", "Cross"}; FSUDAQ::FSUDAQ(QWidget *parent) : QMainWindow(parent){ DebugPrint("%s", "FSUDAQ"); @@ -684,9 +684,6 @@ void FSUDAQ::OpenDigitizers(){ digi[i] = new Digitizer(portList[i].first, portList[i].second); //digi[i]->Reset(); - //===== set no trace, even when FSQDAQ segfault at scope, the digitizer will save no trace - digi[i]->SetTrace(false); - if( cbOpenMethod->currentData().toInt() == 2 ) { digi[i]->ProgramBoard(); } @@ -731,6 +728,10 @@ void FSUDAQ::OpenDigitizers(){ } digi[i]->ReadAllSettingsFromBoard(true); + //===== set no trace, even when FSQDAQ segfault at scope, the digitizer will save no trace + digi[i]->SetTrace(false); + // if( digi[i]->GetDPPType() == V1730_DPP_PHA_CODE) digi[i]->WriteRegister(DPP::BoardConfiguration, 0xE8915); + readDataThread[i] = new ReadDataThread(digi[i], i); connect(readDataThread[i], &ReadDataThread::sendMsg, this, &FSUDAQ::LogMsg); @@ -1207,7 +1208,7 @@ void FSUDAQ::StartACQ(){ influx->ClearDataPointsBuffer(); } - if( elogID > 0 && !chkElog->isChecked() && chkSaveData->isChecked() ){ + if( elogID > 0 && chkElog->isChecked() && chkSaveData->isChecked() ){ QString msg = "================================= Run-" + QString::number(runID).rightJustified(3, '0') + "

" + QDateTime::currentDateTime().toString("MM.dd hh:mm:ss") + "

" + startComment + "

" @@ -1297,7 +1298,7 @@ void FSUDAQ::StopACQ(){ influx->ClearDataPointsBuffer(); } - if( elogID > 0 && !chkElog->isChecked() && chkSaveData->isChecked()){ + if( elogID > 0 && chkElog->isChecked() && chkSaveData->isChecked()){ QString msg = QDateTime::currentDateTime().toString("MM.dd hh:mm:ss") + "

" + stopComment + "

"; uint64_t totalFileSize = 0; for(unsigned int i = 0 ; i < nDigi; i++){ @@ -1837,9 +1838,11 @@ void FSUDAQ::OpenAnalyzer(){ if( id == 0 ) onlineAnalyzer = new CoincidentAnalyzer(digi, nDigi, rawDataPath); if( id == 1 ) onlineAnalyzer = new SplitPole(digi, nDigi); if( id == 2 ) onlineAnalyzer = new Encore(digi, nDigi); - if( id == 3 ) onlineAnalyzer = new RAISOR(digi, nDigi); - if( id == 4 ) onlineAnalyzer = new MUSIC(digi, nDigi); - if( id == 5 ) onlineAnalyzer = new NeutronGamma(digi, nDigi, rawDataPath); + if( id == 3 ) onlineAnalyzer = new MUSIC(digi, nDigi); + if( id == 4 ) onlineAnalyzer = new NeutronGamma(digi, nDigi, rawDataPath); + + if( id == 5 ) onlineAnalyzer = new Cross(digi, nDigi); + if( id >= 0 ) onlineAnalyzer->show(); if( isACQStarted ) onlineAnalyzer->startTimer(); @@ -1851,9 +1854,10 @@ void FSUDAQ::OpenAnalyzer(){ if( id == 0 ) onlineAnalyzer = new CoincidentAnalyzer(digi, nDigi, rawDataPath); if( id == 1 ) onlineAnalyzer = new SplitPole(digi, nDigi); if( id == 2 ) onlineAnalyzer = new Encore(digi, nDigi); - if( id == 3 ) onlineAnalyzer = new RAISOR(digi, nDigi); - if( id == 4 ) onlineAnalyzer = new MUSIC(digi, nDigi); - if( id == 5 ) onlineAnalyzer = new NeutronGamma(digi, nDigi, rawDataPath); + if( id == 3 ) onlineAnalyzer = new MUSIC(digi, nDigi); + if( id == 4 ) onlineAnalyzer = new NeutronGamma(digi, nDigi, rawDataPath); + + if( id == 5 ) onlineAnalyzer = new Cross(digi, nDigi); if( id >= 0 ){ onlineAnalyzer->show(); diff --git a/FSUDAQ_Qt6.pro b/FSUDAQ_Qt6.pro index c0ca0bd..0846a1b 100644 --- a/FSUDAQ_Qt6.pro +++ b/FSUDAQ_Qt6.pro @@ -25,28 +25,29 @@ QMAKE_CFLAGS_RELEASE = -O0 # Input HEADERS += ClassData.h \ ClassDigitizer.h \ + ClassInfluxDB.h\ CustomThreads.h \ CustomWidgets.h \ - Histogram1D.h \ - Histogram2D.h \ DigiSettingsPanel.h \ FSUDAQ.h \ - macro.h \ - RegisterAddress.h \ - ClassInfluxDB.h\ - Scope.h \ - SingleSpectra.h \ + Histogram1D.h \ + Histogram2D.h \ Hit.h \ + macro.h \ MultiBuilder.h \ qcustomplot.h \ - analyzers/Isotope.h \ + RegisterAddress.h \ + Scope.h \ + SingleSpectra.h \ analyzers/Analyser.h \ analyzers/CoincidentAnalyzer.h \ - analyzers/SplitPoleAnalyzer.h \ + analyzers/Cross.h\ analyzers/EncoreAnalyzer.h \ + analyzers/Isotope.h \ + analyzers/SplitPoleAnalyzer.h \ analyzers/MUSICAnalyzer.h \ - analyzers/NeutronGamma.h \ - analyzers/RAISOR.h + analyzers/NeutronGamma.h + SOURCES += ClassDigitizer.cpp \ DigiSettingsPanel.cpp \ FSUDAQ.cpp \ diff --git a/Histogram1D.h b/Histogram1D.h index a0f5704..4c6cdc1 100644 --- a/Histogram1D.h +++ b/Histogram1D.h @@ -276,6 +276,7 @@ public: UpdatePlot(); } + void SetLineTitle(QString title, int lineID = 0) { graph(lineID)->setName(title); } void SetXTitle(QString xTitle) { xAxis->setLabel(xTitle);} void Rebin(int xbin, double xmin, double xmax){ @@ -283,6 +284,7 @@ public: xMin = xmin; xMax = xmax; xBin = xbin; + if( xBin > 1000) xBin = 1000; dX = (xMax - xMin)/(xBin); diff --git a/Histogram2D.h b/Histogram2D.h index 33492b6..0392a24 100644 --- a/Histogram2D.h +++ b/Histogram2D.h @@ -310,6 +310,9 @@ inline void Histogram2D::Rebin(int xbin, double xmin, double xmax, int ybin, do xBin = xbin + 2; yBin = ybin + 2; + if( xBin > 1002) xBin = 1002; + if( yBin > 1002) yBin = 1002; + colorMap->data()->clear(); colorMap->data()->setSize(xBin, yBin); colorMap->data()->setRange(QCPRange(xMin, xMax), QCPRange(yMin, yMax)); @@ -752,7 +755,7 @@ inline void Histogram2D::LoadCuts(QString cutFileName){ int colorID = tempCutID% colorCycle.count(); text->setColor(colorCycle[colorID].first); cutTextIDList.push_back(itemCount() - 1); - // cutList.push_back(tempCut); + cutList.push_back(tempCut); cutIDList.push_back(tempCutID); } tempCut.clear(); @@ -792,6 +795,7 @@ inline void Histogram2D::LoadCuts(QString cutFileName){ // Close the file file.close(); qDebug() << "File read successfully from" << cutFileName; + qDebug() << " Number of cut loaded " << numCut << ", " << cutList.count(); // PrintCutEntry(); // DrawCut(); diff --git a/MultiBuilder.cpp b/MultiBuilder.cpp index 88d0e8d..874db37 100644 --- a/MultiBuilder.cpp +++ b/MultiBuilder.cpp @@ -95,6 +95,8 @@ void MultiBuilder::PrintAllEvent(){ } } +//^############################################### forward event builder + void MultiBuilder::FindEarlistTimeAndCh(bool verbose){ DebugPrint("%s", "MultiBuilder"); earlistTime = -1; @@ -103,9 +105,7 @@ 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 ++){ @@ -118,7 +118,7 @@ void MultiBuilder::FindEarlistTimeAndCh(bool verbose){ } if( data[i]->GetTimestamp(ch, index) == 0 || - loopIndex[i][ch] * dataSize[i] > data[i]->GetLoopIndex(ch) * dataSize[i] + data[i]->GetDataIndex(ch)) { + loopIndex[i][ch] * dataSize[i] + nextIndex[i][ch] > data[i]->GetLoopIndex(ch) * dataSize[i] + data[i]->GetDataIndex(ch)) { nExhaushedCh ++; chExhaused[i][ch] = true; continue; @@ -138,42 +138,6 @@ void MultiBuilder::FindEarlistTimeAndCh(bool verbose){ } if( verbose ) printf("%s | bd : %d, ch : %d, %llu\n", __func__, earlistDigi, earlistCh, earlistTime); - -} - -void MultiBuilder::FindLatestTimeAndCh(bool verbose){ - DebugPrint("%s", "MultiBuilder"); - latestTime = 0; - latestDigi = -1; - latestCh = -1; - - nExhaushedCh = 0; - - for( int i = 0; i < nData; i++){ - - for( int j = 0; j < data[i]->GetNChannel(); j++ ) chExhaused[i][j] = false; - - for(unsigned int ch = 0; ch < data[i]->GetNChannel(); ch ++){ - - 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); - continue; - } - - unsigned long long time = data[i]->GetTimestamp(ch, nextIndex[i][ch]); - // printf(", time : %llu\n", time ); - if( time > latestTime ) { - latestTime = time; - latestDigi = i; - latestCh = ch; - } - } - } - - if( verbose ) printf("%s | bd : %d, ch : %d, %llu\n", __func__, latestDigi, latestCh, latestTime); - } void MultiBuilder::FindEarlistTimeAmongLastData(bool verbose){ @@ -195,35 +159,16 @@ void MultiBuilder::FindEarlistTimeAmongLastData(bool verbose){ } if( verbose ) printf("%s | bd : %d, ch : %d, %lld \n", __func__, latestDigi, latestCh, latestTime); } - -void MultiBuilder::FindLatestTimeOfData(bool verbose){ - DebugPrint("%s", "MultiBuilder"); - latestTime = 0; - latestCh = -1; - latestDigi = -1; - for( int i = 0; i < nData; i++){ - // printf("%s | digi-%d-th | %d\n", __func__, i, data[i]->GetNChannel()); - for( unsigned ch = 0; ch < data[i]->GetNChannel(); ch++ ){ - int index = data[i]->GetDataIndex(ch); - // printf("ch-%2d | index : %d \n", ch, index); - if( index == -1 ) continue; - if( data[i]->GetTimestamp(ch, index) > latestTime ) { - latestTime = data[i]->GetTimestamp(ch, index); - latestCh = ch; - latestDigi = i; - } - } - } - if( verbose ) printf("%s | bd : %d, ch : %d, %lld \n", __func__, latestDigi, latestCh, latestTime); -} + void MultiBuilder::BuildEvents(bool isFinal, bool skipTrace, bool verbose){ DebugPrint("%s", "MultiBuilder"); + FindEarlistTimeAndCh(verbose); //Give the earliest time, ch, digi + FindEarlistTimeAmongLastData(verbose); // give lastest Time, Ch, and Digi for event building - FindEarlistTimeAndCh(verbose); //Give the earliest time, ch, digi - if( earlistCh == -1 || nExhaushedCh == nData * MaxNChannels) return; /// no data + if( earlistCh == -1 || nExhaushedCh == numTotCh) return; /// no data eventBuilt = 0; //======= Start building event @@ -235,14 +180,13 @@ void MultiBuilder::BuildEvents(bool isFinal, bool skipTrace, bool verbose){ eventIndex ++; if( eventIndex >= MaxNEvent ) eventIndex = 0; events[eventIndex].clear(); - em.Clear(); for( int k = 0; k < nData; k++){ int bd = (k + earlistDigi) % nData; - // printf("##### %d/%d | ", k, nData); - // data[k]->PrintAllData(true, 10); + // printf("##### %d/%d | ", bd, nData); + // data[bd]->PrintAllData(true); const int numCh = data[bd]->GetNChannel(); @@ -250,16 +194,22 @@ void MultiBuilder::BuildEvents(bool isFinal, bool skipTrace, bool verbose){ int ch = (i + earlistCh ) % numCh; // printf("ch : %d | exhaused ? %s \n", ch, chExhaused[bd][ch] ? "Yes" : "No"); if( chExhaused[bd][ch] ) continue; - if( loopIndex[bd][ch] * dataSize[bd] + nextIndex[bd][ch] > data[bd]->GetLoopIndex(ch) * dataSize[bd] + data[bd]->GetDataIndex(ch)) { + + // printf(" ch : %2d | %d(%d) | %d(%d)\n", ch, loopIndex[bd][ch], nextIndex[bd][ch], data[bd]->GetLoopIndex(ch), data[bd]->GetDataIndex(ch) ); + + if( nextIndex[bd][ch] == -1 + || loopIndex[bd][ch] * dataSize[bd] + nextIndex[bd][ch] > data[bd]->GetLoopIndex(ch) * dataSize[bd] + data[bd]->GetDataIndex(ch)) { nExhaushedCh ++; chExhaused[bd][ch] = true; + + // printf(" ch : %d exhaused\n", ch); continue; } do { unsigned long long time = data[bd]->GetTimestamp(ch, nextIndex[bd][ch]); - //printf("%6ld, sn: %5d, ch: %2d, timestamp : %16llu | earlistTime : %16llu | timeWindow : %u \n", eventIndex, data[bd]->boardSN, ch, time, earlistTime, timeWindow); + // printf("%6d, sn: %5d, ch: %2d, timestamp : %16llu | earlistTime : %16llu | timeWindow : %u \n", nextIndex[bd][ch], data[bd]->boardSN, ch, time, earlistTime, timeWindow); if( time >= earlistTime && (time - earlistTime <= timeWindow) ){ em.sn = snList[bd]; @@ -280,14 +230,21 @@ void MultiBuilder::BuildEvents(bool isFinal, bool skipTrace, bool verbose){ }else{ break; } - if( timeWindow <= 0 ) break; + if( timeWindow == 0 ) break; }while( true ); - if( timeWindow <= 0 ) break; + if( timeWindow == 0 ) break; } - if( timeWindow <= 0 ) break; + if( timeWindow == 0 ) break; } - if( events[eventIndex].size() == 0 ) continue; + if( events[eventIndex].size() == 0 ) { + if( eventIndex > 1) { + eventIndex --; + }else{ + eventIndex = MaxNEvent - 1; + } + continue; + } if( events[eventIndex].size() > 1) { std::sort(events[eventIndex].begin(), events[eventIndex].end(), [](const Hit& a, const Hit& b) { @@ -295,21 +252,21 @@ void MultiBuilder::BuildEvents(bool isFinal, bool skipTrace, bool verbose){ }); } - lastEventTime = events[eventIndex].back().timestamp; + // lastEventTime = events[eventIndex].back().timestamp; ///Find the next earlist FindEarlistTimeAndCh(false); // //if there is a time jump, say, bigger than TimeJump. break - if( earlistTime - lastEventTime > timeJump ) { - if( verbose ){ - printf("!!!!!!!! Time Jump detected stop event building and get more data.\n"); - printf("event index : %6lu, earlist time : %16llu\n", eventIndex, earlistTime); - printf(" %6s last event time : %16llu \n", "", lastEventTime); - printf(" %6s time jump > %16llu \n", "", timeJump); - } - return; - } + // if( earlistTime - lastEventTime > timeJump ) { + // if( verbose ){ + // printf("!!!!!!!! Time Jump detected stop event building and get more data.\n"); + // printf("event index : %6lu, last event time : %16llu\n", eventIndex, lastEventTime); + // printf(" %6s earilest time : %16llu \n", "", earlistTime); + // printf(" %6s time jump > %16llu \n", "", timeJump); + // } + // return; + // } eventBuilt ++; totalEventBuilt ++; @@ -329,7 +286,7 @@ void MultiBuilder::BuildEvents(bool isFinal, bool skipTrace, bool verbose){ printf("%05d, %02d | %5d | %5d %llu \n", sn, chxxx, nextIndex[bd][chxxx], events[eventIndex][i].energy, events[eventIndex][i].timestamp); } - if( nExhaushedCh == nData * MaxNChannels ) { + if( nExhaushedCh == numTotCh ) { printf("######################### no more event to be built\n"); break; } @@ -348,12 +305,67 @@ void MultiBuilder::BuildEvents(bool isFinal, bool skipTrace, bool verbose){ break; } } - }while(nExhaushedCh < nData * MaxNChannels); + }while(nExhaushedCh < numTotCh); forceStop = false; } +//^############################################### backward event builder + +void MultiBuilder::FindLatestTimeAndCh(bool verbose){ + DebugPrint("%s", "MultiBuilder"); + latestTime = 0; + latestDigi = -1; + latestCh = -1; + + nExhaushedCh = 0; + + for( int i = 0; i < nData; i++){ + for( int j = 0; j < data[i]->GetNChannel(); j++ ) chExhaused[i][j] = false; + + for(unsigned int ch = 0; ch < data[i]->GetNChannel(); ch ++){ + 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); + continue; + } + + unsigned long long time = data[i]->GetTimestamp(ch, nextIndex[i][ch]); + // printf(", time : %llu\n", time ); + if( time > latestTime ) { + latestTime = time; + latestDigi = i; + latestCh = ch; + } + } + } + + if( verbose ) printf("%s | bd : %d, ch : %d, %llu\n", __func__, latestDigi, latestCh, latestTime); +} + +void MultiBuilder::FindLatestTimeOfData(bool verbose){ + DebugPrint("%s", "MultiBuilder"); + latestTime = 0; + latestCh = -1; + latestDigi = -1; + for( int i = 0; i < nData; i++){ + // printf("%s | digi-%d-th | %d\n", __func__, i, data[i]->GetNChannel()); + for( unsigned ch = 0; ch < data[i]->GetNChannel(); ch++ ){ + int index = data[i]->GetDataIndex(ch); + // printf("ch-%2d | index : %d \n", ch, index); + if( index == -1 ) continue; + if( data[i]->GetTimestamp(ch, index) > latestTime ) { + latestTime = data[i]->GetTimestamp(ch, index); + latestCh = ch; + latestDigi = i; + } + } + } + if( verbose ) printf("%s | bd : %d, ch : %d, %lld \n", __func__, latestDigi, latestCh, latestTime); +} + void MultiBuilder::BuildEventsBackWard(int maxNumEvent, bool verbose){ DebugPrint("%s", "MultiBuilder"); //skip trace, and only build for maxNumEvent events max diff --git a/SingleSpectra.cpp b/SingleSpectra.cpp index bc08501..95a1081 100644 --- a/SingleSpectra.cpp +++ b/SingleSpectra.cpp @@ -151,6 +151,9 @@ SingleSpectra::SingleSpectra(Digitizer ** digi, unsigned int nDigi, QString rawD // Setup the timer to trigger every second connect(timer, &QTimer::timeout, histWorker, &HistWorker::FillHistograms); + + connect( histWorker, &HistWorker::workDone, this, &SingleSpectra::ReplotHistograms); + workerThread->start(); } @@ -314,6 +317,20 @@ void SingleSpectra::FillHistograms(){ } +void SingleSpectra::ReplotHistograms(){ + + int ID = cbDigi->currentData().toInt(); + int ch = cbCh->currentData().toInt(); + + if( ch == digi[ID]->GetNumInputCh()) { + if( hist2DVisibility[ID] ) hist2D[ID]->UpdatePlot(); + return; + } + + if( histVisibility[ID][ch] ) hist[ID][ch]->UpdatePlot(); + +} + void SingleSpectra::SaveSetting(){ DebugPrint("%s", "SingleSpectra"); diff --git a/SingleSpectra.h b/SingleSpectra.h index 9a0d19d..60cb25d 100644 --- a/SingleSpectra.h +++ b/SingleSpectra.h @@ -43,6 +43,8 @@ public: QVector generateNonRepeatedCombination(int size); + void ReplotHistograms(); + public slots: void FillHistograms(); void ChangeHistView(); diff --git a/analyzers/Analyser.cpp b/analyzers/Analyser.cpp index 38330d0..bcfd5ed 100644 --- a/analyzers/Analyser.cpp +++ b/analyzers/Analyser.cpp @@ -60,6 +60,8 @@ Analyzer::Analyzer(Digitizer ** digi, unsigned int nDigi, QMainWindow * parent ) // printf(" --------- work Done\n"); // }); + connect( anaWorker, &AnalyzerWorker::workDone, this, &Analyzer::ReplotHistograms); + anaThread->start(); } @@ -138,12 +140,12 @@ void Analyzer::SetDatabase(QString IP, QString Name, QString Token){ influx = nullptr; } }else{ - printf("Database name : %s NOT found.\n", dataBaseName.toStdString().c_str()); + printf(RED "Database name : %s NOT found.\n" RESET, dataBaseName.toStdString().c_str()); delete influx; influx = nullptr; } }else{ - printf("InfluxDB URL (%s) is NOT Valid. \n", dataBaseIP.toStdString().c_str()); + printf(RED "InfluxDB URL (%s) is NOT Valid. \n" RESET, dataBaseIP.toStdString().c_str()); delete influx; influx = nullptr; } @@ -242,4 +244,9 @@ void Analyzer::SetUpCanvas(){ void Analyzer::UpdateHistograms(){ +} + +void Analyzer::ReplotHistograms(){ + + } \ No newline at end of file diff --git a/analyzers/Analyser.h b/analyzers/Analyser.h index 75dade6..8c1a677 100644 --- a/analyzers/Analyser.h +++ b/analyzers/Analyser.h @@ -17,6 +17,7 @@ #include "CustomWidgets.h" #include "MultiBuilder.h" #include "ClassInfluxDB.h" +#include "math.h" /************************************** @@ -62,18 +63,19 @@ public: virtual void SetUpCanvas(); virtual void UpdateHistograms(); // where event-building, analysis, and ploting + virtual void ReplotHistograms(); public slots: void startTimer(){ // printf("start timer\n"); mb->ForceStop(false); - mb->ClearEvents(); anaTimer->start(waitTimeinSec*1000); } void stopTimer(){ // printf("stop worker\n"); anaTimer->stop(); mb->ForceStop(true); + mb->ClearEvents(); } private slots: @@ -130,4 +132,4 @@ private: Analyzer * SS; }; -#endif \ No newline at end of file +#endif diff --git a/analyzers/Cross.h b/analyzers/Cross.h new file mode 100644 index 0000000..c2060f0 --- /dev/null +++ b/analyzers/Cross.h @@ -0,0 +1,311 @@ +#ifndef Cross_h +#define Cross_h + +/********************************************* + * This is online analyzer for PID, ANL + * + * Created by Khushi @ 2024-09-03 + * + * ******************************************/ +#include "Analyser.h" + +class Cross : public Analyzer{ + +public: + Cross(Digitizer ** digi, unsigned int nDigi, QMainWindow * parent = nullptr): Analyzer(digi, nDigi, parent){ + + SetUpdateTimeInSec(1.0); + + RedefineEventBuilder({0}); // only builder for the 0-th digitizer. + tick2ns = digi[0]->GetTick2ns(); + + SetBackwardBuild(false, 100); // using normal building (acceding in time) or backward building, int the case of backward building, default events to be build is 100. + evtbder = GetEventBuilder(); + evtbder->SetTimeWindow(500); + + SetDatabase("http://localhost:8086/", "testing", "zKhzKk4Yhf1l9QU-yE2GsIZ1RazqUgoW3NlF8LJqq_xDMwatOJwg1sKrjgq36uLEsQf8Fmn4sJALP7Kkilk14A=="); + + SetUpCanvas(); // see below + + }; + + void SetUpCanvas(); + +public slots: + void UpdateHistograms(); + void ReplotHistograms(); + +private: + + MultiBuilder *evtbder; + + //Histogram2D * hPID; + + Histogram1D * hdE; // raw dE (ch=1): ch1 + Histogram1D * hE; // raw E (ch=4) : ch4 + Histogram1D * hdT; // raw dT (ch=7): ch7 + + Histogram1D * hTotE; // total energy (dE+E): ch1+ch4 + Histogram1D * hTWin; // coincidence time window TWin: (t4-t1)*1e9 + + Histogram2D * hdEE; // dE versus E : ch1 versus ch4 + Histogram2D * hdEtotE; // dE versus totE : ch1 versus (ch1+ch4) + + Histogram2D * hdEdT; // dE versus TOF: ch1 versus (t7-t1)*1e9 + + Histogram1D * hMulti; //Multiplicity of an event + + int tick2ns; + + int chDE, chE; + float energyDE, energyE, ch7; + unsigned long long t1, t4, t7; + + QPushButton * bnClearHist; + QLabel * lbInfluxIP; + RComboBox * cbLocation; + QCheckBox * chkDEFourTime; + +}; + +inline void Cross::ReplotHistograms(){ + + hdE->UpdatePlot(); + hE->UpdatePlot(); + hdT->UpdatePlot(); + hTotE->UpdatePlot(); + hdEE->UpdatePlot(); + hdEtotE->UpdatePlot(); + hdEdT->UpdatePlot(); + hTWin->UpdatePlot(); + hMulti->UpdatePlot(); + +} + +inline void Cross::SetUpCanvas(){ + + setGeometry(0, 0, 2000, 1000); + + //============ histograms + + //hPID = new Histogram2D("RAISOR", "E", "dE", 100, 0, 5000, 100, 0, 5000, this); + //layout->addWidget(hPID, 2, 0); + + int row = 0; + cbLocation = new RComboBox(this); + cbLocation->addItem("Cross", 0); + cbLocation->addItem("Target", 1); + layout->addWidget(cbLocation, row, 0); + + connect(cbLocation, &RComboBox::currentIndexChanged, this, [=](){ + switch (cbLocation->currentData().toInt() ) { + case 0 : { + hdE->SetLineTitle("raw dE (ch = 0)"); + hE->SetLineTitle("raw E (ch = 2)"); + hdE->replot(); + hE->replot(); + chDE = 0; + chE = 2; + //Can also set histograms range + + } + break; + case 1 : { + hdE->SetLineTitle("raw dE (ch = 1)"); + hE->SetLineTitle("raw E (ch = 4)"); + hdE->replot(); + hE->replot(); + chDE = 1; + chE = 4; + //Can also set histograms range + } + } + }); + + chkDEFourTime = new QCheckBox("dE channel / 4", this); + layout->addWidget(chkDEFourTime, row, 1); + + bnClearHist = new QPushButton("Clear All Hist.", this); + layout->addWidget(bnClearHist, row, 2); + + connect( bnClearHist, &QPushButton::clicked, this, [=](){ + hdE->Clear(); + hE->Clear(); + hdT->Clear(); + hTotE->Clear(); + hdEE->Clear(); + hdEtotE->Clear(); + hdEdT->Clear(); + hTWin->Clear(); + hMulti->Clear(); + }); + + + QString haha; + if( influx ) { + haha = dataBaseIP + ", DB : " + dataBaseName; + }else{ + haha = "No influxDB connection."; + } + lbInfluxIP = new QLabel( haha , this); + if( influx == nullptr ) lbInfluxIP->setStyleSheet("color : red;"); + layout->addWidget(lbInfluxIP, row, 3, 1, 3); + + row ++; + hdEE = new Histogram2D("dE vs E", "E[ch]", "dE[ch]", 500, -100, 5000, 500, -100, 5000, this); + layout->addWidget(hdEE, row, 0, 1, 2); + + hdE = new Histogram1D("raw dE (ch=0)", "dE [ch]", 300, 0, 5000, this); + layout->addWidget(hdE, row, 2); + + hE = new Histogram1D("raw E (ch=2)", "E [ch]", 300, 0, 10000, this); + layout->addWidget(hE, row, 3); + + hTotE = new Histogram1D("total energy (dE+E)", "TotE [ch]", 300, 0, 16000, this); + layout->addWidget(hTotE, row, 4); + + hMulti = new Histogram1D("Multiplicity", "", 10, 0, 10, this); + layout->addWidget(hMulti, row, 5); + + row ++; + hdEtotE = new Histogram2D("dE vs TotE", "TotE[ch]", "dE[ch]", 500, 0, 10000, 500, 0, 5000, this); + layout->addWidget(hdEtotE, row, 0, 1, 2); + + hdT = new Histogram1D("raw dT (ch=7)", "dT [ch]", 300, 0, 1000, this); + layout->addWidget(hdT, row, 2); + + hdEdT = new Histogram2D("dE vs TOF", "TOF [ns]", "dE", 100, 0, 500, 100, 0, 4000, this); + layout->addWidget(hdEdT, row, 3); + + hTWin = new Histogram1D("coincidence time window", "TWin [ns]", 100, 0, 100, this); + layout->addWidget(hTWin, row, 4); + + +} + +inline void Cross::UpdateHistograms(){ + + if( this->isVisible() == false ) return; + + BuildEvents(false); // call the event builder to build events + + //============ Get events, and do analysis + long eventBuilt = evtbder->eventBuilt; + if( eventBuilt == 0 ) return; + + //============ Get the cut list, if any + QList cutList1 = hdEE->GetCutList(); + const int nCut1 = cutList1.count(); + unsigned long long tMin1[nCut1], tMax1[nCut1]; + unsigned int count1[nCut1]; + + QList cutList2 = hdEtotE->GetCutList(); + const int nCut2 = cutList2.count(); + unsigned long long tMin2[nCut2], tMax2[nCut2]; + unsigned int count2[nCut2]; + + //============ Processing data and fill histograms + long eventIndex = evtbder->eventIndex; + long eventStart = eventIndex - eventBuilt + 1; + if(eventStart < 0 ) eventStart += MaxNEvent; + + for( int i = 0; i < nCut1; i++) { + tMin1[i] = -1; + tMax1[i] = 0; + count1[i] = 0; + } + + for( int i = 0; i < nCut2; i++) { + tMin2[i] = -1; + tMax2[i] = 0; + count2[i] = 0; + } + + for( long i = eventStart ; i <= eventIndex; i ++ ){ + + std::vector event = evtbder->events[i]; + //printf("-------------- %ld\n", i); + + if( event.size() == 0 ) return; + + hMulti->Fill(event.size()); + + energyDE = -100; t1 = 0; + energyE = -100; t4 = 0; + ch7 = -100; t7 = 0; + + for( int k = 0; k < (int) event.size(); k++ ){ + //event[k].Print(); + if( event[k].ch == chDE ) {energyDE = event[k].energy; t1 = event[k].timestamp;} // Reads channel 0 of the digitizer corresponding to dE + if( event[k].ch == chE ) {energyE = event[k].energy; t4 = event[k].timestamp;} // Reads channel 2 of the digitizer corresponding to E + if( event[k].ch == 7 ) {ch7 = event[k].energy; t7 = event[k].timestamp;} //RF Timing if setup + + } + + // printf("(E, dE) = (%f, %f)\n", E, dE); + //hPID->Fill(ch4 , ch1); // x, y + //etotal = ch1*0.25*0.25 + ch4 + if( energyDE > 0 ) hdE->Fill(energyDE); + if( energyE > 0 ) hE->Fill(energyE); + if( ch7 > 0 ) hdT->Fill(ch7); + if( energyDE > 0 && energyE > 0 ){ + hTotE->Fill(0.25 * energyDE + energyE); + hdEE->Fill(energyE,energyDE); + if( t4 > t1 ) { + hTWin->Fill((t4-t1)); + }else{ + hTWin->Fill((t1-t4)); + } + hdEtotE->Fill( (chkDEFourTime->isChecked() ? 0.25 : 1) * energyDE + energyE,energyDE); + } + + if( energyDE > 0 && ch7 > 0) hdEdT->Fill((t7-t1)*1e9,energyDE); + + //check events inside any Graphical cut and extract the rate + // if( ch1 == 0 && ch4 == 0 ) continue; + for(int p = 0; p < cutList1.count(); p++ ){ + if( cutList1[p].isEmpty() ) continue; + if( cutList1[p].containsPoint(QPointF(energyE, energyDE), Qt::OddEvenFill) ){ + if( t1 < tMin1[p] ) tMin1[p] = t1; + if( t1 > tMax1[p] ) tMax1[p] = t1; + count1[p] ++; + //printf("hdEE.... %d \n", count1[p]); + } + } + + for(int p = 0; p < cutList2.count(); p++ ){ + if( cutList2[p].isEmpty() ) continue; + if( cutList2[p].containsPoint(QPointF(energyDE+energyE,energyDE), Qt::OddEvenFill) ){ + if( t1 < tMin2[p] ) tMin2[p] = t1; + if( t1 > tMax2[p] ) tMax2[p] = t1; + count2[p] ++; + //printf("hdEtotE.... %d \n", count2[p]); + } + } + } + + + for(int p = 0; p < cutList2.count(); p++ ){ + printf("hdEE.... %d %d \n", p, count1[p]); + } + + //========== output to Influx + QList cutNameList1 = hdEE->GetCutNameList(); + for( int p = 0; p < cutList1.count(); p ++){ + if( cutList1[p].isEmpty() ) continue; + double dT = (tMax1[p]-tMin1[p]) / 1e9; // tick to sec + double rate = count1[p]*1.0/(dT); + //printf("%llu %llu, %f %d\n", tMin1[p], tMax1[p], dT, count1[p]); + printf("%10s | %d | %f Hz \n", cutNameList1[p].toStdString().c_str(), count1[p], rate); + + if( influx ){ + influx->AddDataPoint("Cut,name=" + cutNameList1[p].toStdString()+ " value=" + std::to_string(rate)); + influx->WriteData("testing"); + influx->ClearDataPointsBuffer(); + } + } + +} + + +#endif diff --git a/macro.h b/macro.h index 34c802d..d734ec6 100644 --- a/macro.h +++ b/macro.h @@ -19,6 +19,15 @@ #define SETTINGSIZE 2048 +#define RESET "\033[0m" +#define RED "\033[31m" +#define GREEN "\033[32m" +#define YELLOW "\033[33m" +#define BLUE "\033[34m" +#define MAGENTA "\033[35m" +#define CYAN "\033[36m" +#define WHITE "\033[37m" + #define DAQLockFile "DAQLock.dat" #define PIDFile "pid.dat" -- 2.34.1 From 2f55f6ecb5ac467908e05314ac43825aee723765 Mon Sep 17 00:00:00 2001 From: "Ryan@SOLARIS_testStation" Date: Mon, 14 Oct 2024 16:51:02 -0400 Subject: [PATCH 02/35] add software waveform decimation to reduce raw data file size --- .gitignore | 1 + Aux/Makefile | 11 ++-- Aux/test.cpp | 41 +++++++++++++- ClassData.h | 148 ++++++++++++++++++++++++++++++++++++++++++++++++--- 4 files changed, 190 insertions(+), 11 deletions(-) diff --git a/.gitignore b/.gitignore index 84e79bb..2bb661a 100644 --- a/.gitignore +++ b/.gitignore @@ -27,6 +27,7 @@ Bin2Root data Data raw_binary +log *.d *.pcm diff --git a/Aux/Makefile b/Aux/Makefile index 1433ca5..c3b10e1 100644 --- a/Aux/Makefile +++ b/Aux/Makefile @@ -12,9 +12,9 @@ CAENLIBS = -lCAENDigitizer -lCAENVME ROOTLIBS = `root-config --cflags --glibs` -OBJS = ClassDigitizer.o MultiBuilder.o ClassInfluxDB.o +OBJS = ClassDigitizer.o MultiBuilder.o ClassInfluxDB.o ClassDigitizerAPI.o -ALL = test EventBuilder DataReader DumpFSU2ROOT SettingsExplorer FSU2CAEN +ALL = test EventBuilder DataReader DumpFSU2ROOT SettingsExplorer FSU2CAEN haha ######################################################################### @@ -29,12 +29,15 @@ MultiBuilder.o : ../MultiBuilder.cpp ../MultiBuilder.h ../Hit.h ClassDigitizer.o : ../ClassDigitizer.cpp ../ClassDigitizer.h ../RegisterAddress.h ../macro.h ../ClassData.h $(CC) $(COPTS) -c ../ClassDigitizer.cpp +ClassDigitizerAPI.o : ../ClassDigitizer.cpp ClassDigitizerAPI.cpp ../ClassDigitizer.h ../RegisterAddress.h ../macro.h ../ClassData.h + $(CC) $(COPTS) -c ClassDigitizerAPI.cpp + ClassInfluxDB.o : ../ClassInfluxDB.cpp ../ClassInfluxDB.h $(CC) $(COPTS) -c ../ClassInfluxDB.cpp -lcurl -test : test.cpp ../ClassDigitizer.o ../MultiBuilder.o ../ClassInfluxDB.o +test : test.cpp ../ClassDigitizer.o ../MultiBuilder.o ../ClassInfluxDB.o ClassDigitizerAPI.o @echo "--------- making test" - $(CC) -fPIC -DLINUX -O0 -std=c++17 -lpthread -g -o test test.cpp ../ClassDigitizer.o ../MultiBuilder.o ../ClassInfluxDB.o $(CAENLIBS) $(ROOTLIBS) -lcurl + $(CC) -fPIC -DLINUX -O0 -std=c++17 -lpthread -g -o test test.cpp ../ClassDigitizer.o ClassDigitizerAPI.o ../MultiBuilder.o ../ClassInfluxDB.o $(CAENLIBS) $(ROOTLIBS) -lcurl # test_indep : test_indep.cpp ../RegisterAddress.h ../macro.h # @echo "--------- making test_indep" diff --git a/Aux/test.cpp b/Aux/test.cpp index 63966c2..6a5c4f8 100644 --- a/Aux/test.cpp +++ b/Aux/test.cpp @@ -3,6 +3,7 @@ #include "../ClassDigitizer.h" #include "../MultiBuilder.h" #include "../ClassInfluxDB.h" +#include "ClassDigitizerAPI.h" #include #include @@ -322,6 +323,38 @@ int TestDigitizerRaw(){ } +void SimpleDAQ(){ + + std::unique_ptr digi = std::make_unique(0, 49093, false, true); + + digi->ProgramBoard(); + digi->SetBits(DPP::QDC::DPPAlgorithmControl, DPP::QDC::Bit_DPPAlgorithmControl::Polarity, 0, -1); + digi->WriteRegister(DPP::QDC::NumberEventsPerAggregate, 5); + digi->SetBits(DPP::BoardConfiguration, DPP::Bit_BoardConfig::RecordTrace, 1, -1); // enable trace recording + digi->WriteRegister(DPP::MaxAggregatePerBlockTransfer, 10); + + Data * data = digi->GetData(); + data->OpenSaveFile("haha2"); + + digi->StartACQ(); + + for( int i = 0; i < 10 ; i++ ){ + + usleep(500*1000); + + digi->ReadData(); + data->DecodeBuffer(true, 0); + data->SaveData(2); + + data->PrintStat(); + + } + + digi->StopACQ(); + +} + + void Compare_CAEN_Decoder(){ std::unique_ptr digi = std::make_unique(0, 49093, false, true); @@ -384,14 +417,20 @@ void Compare_CAEN_Decoder(){ //^====================================== int main(int argc, char* argv[]){ - Compare_CAEN_Decoder(); + // Compare_CAEN_Decoder(); // Data * data = digi->GetData(); + SimpleDAQ(); + // MultiBuilder * builder = new MultiBuilder(data, DPPType::DPP_PHA_CODE, digi->GetSerialNumber()); // builder->SetTimeWindow(100); + // std::unique_ptr digi = std::make_unique(0, 49093, false, true); + + + return 0; } diff --git a/ClassData.h b/ClassData.h index 39606c9..ef6650a 100644 --- a/ClassData.h +++ b/ClassData.h @@ -105,7 +105,8 @@ class Data{ //^================= Saving data bool OpenSaveFile(std::string fileNamePrefix); // return false when fail std::string GetOutFileName() const {return outFileName;} - void SaveData(); + void SetDecimationFactor(unsigned short factor) { decimation = factor; } + void SaveData(); void CloseSaveFile(); unsigned int GetFileSize() const {return outFileSize;} uint64_t GetTotalFileSize() const {return FinishedOutFilesSize + outFileSize;} @@ -138,6 +139,8 @@ class Data{ std::vector tempDigiWaveform3; std::vector tempDigiWaveform4; + unsigned short decimation; + FILE * outFile; uint64_t FinishedOutFilesSize; // sum of files size. unsigned int outFileIndex; @@ -177,6 +180,8 @@ inline Data::Data(unsigned short numCh, uInt dataSize): numInputCh(numCh){ ClearNumEventsDecoded(); nw = 0; + decimation = 0; + outFileIndex = 0; outFilePrefix = ""; outFileName = ""; @@ -472,10 +477,137 @@ inline void Data::SaveData(){ outFile = fopen(outFileName.c_str(), "wb"); //overwrite binary } - fwrite(buffer, nByte, 1, outFile); - outFileSize = ftell(outFile); + if( decimation == 0){ + fwrite(buffer, nByte, 1, outFile); + }else{ + + int Deci = pow(2, decimation); + // printf("Decimation Factor : %d | Deci : %d | nByte %d | nWord %d\n", decimation, Deci, nByte, nByte / 4); + + const size_t chunkSize = 4; + size_t numChunk = nByte / chunkSize; + + uint32_t word = 0; + + int bdAggWordCount = 0; + int groupWordCount = 0; + int chWordCount = 0; + int sampleWordCount = 0; + + int bdAggSize = 0; + int groupAggSize = 0; + int sampleSize = 0; + int chAggSize = 0; + + uint32_t oldHeader0 = 0; + uint32_t oldHeader1 = 0; + uint32_t oldHeader2 = 0; + uint32_t oldHeader3 = 0; + + for( size_t i = 0; i < numChunk; i++ ){ + + bdAggWordCount ++; + memcpy(&word, buffer + i * chunkSize, chunkSize); + + if( bdAggWordCount <= 4) { + + if( bdAggWordCount == 1 ) { + bdAggSize = word & 0x0FFFFFFF; + // printf("###################### Bd Agg Size : %d\n", bdAggSize); + } + + // fwrite(buffer + i * chunkSize, sizeof(char), chunkSize, outFile); + // fwrite(&word, sizeof(word), 1, outFile); + + if( bdAggWordCount == 1 ) oldHeader0 = word; + if( bdAggWordCount == 2 ) oldHeader1 = word; + if( bdAggWordCount == 3 ) oldHeader2 = word; + if( bdAggWordCount == 4 ) oldHeader3 = word; + + }else{ + + groupWordCount ++; + + if( groupWordCount == 1 ) { + groupAggSize = word & 0x3FFFFFFF; + // printf("============= Coupled Channel Agg Size : %d \n", groupAggSize); + } + if( groupWordCount == 2 ) { + sampleSize = (word & 0xFFF) * 8; + bool isExtra = ( (word >> 28 ) & 0x1 ); + chAggSize = 2 + sampleSize / 2 + isExtra; + uint32_t oldWord = word; + + word = (word & 0xFFFFF000) + (sampleSize / 8 / Deci); // change the number of sample + // printf("============= Sample Size : %d | Ch Size : %d | old %08X new %08X\n", sampleSize, chAggSize, oldWord, word); + + int nEvent = (groupAggSize - 2 ) / chAggSize; + int newGroupAggSize = 2 + nEvent * ( 2 + sampleSize / Deci / 2 + isExtra ); + int newBdAggSize = 4 + newGroupAggSize; + + //Write board header and Agg header + uint32_t newHeader0 = (0xA << 28) + newBdAggSize; + fwrite(&newHeader0, sizeof(uint32_t), 1, outFile); + fwrite(&oldHeader1, sizeof(uint32_t), 1, outFile); + fwrite(&oldHeader2, sizeof(uint32_t), 1, outFile); + fwrite(&oldHeader3, sizeof(uint32_t), 1, outFile); + + uint32_t newAggHeader0 = (0x8 << 28) + newGroupAggSize + (decimation << 12); // add decimation factor in the word + fwrite(&newAggHeader0, sizeof(uint32_t), 1, outFile); + fwrite(&word, sizeof(uint32_t), 1, outFile); + + // printf(" New Board Agg Size : %d \n", newBdAggSize); + // printf(" New Group Agg Size : %d \n", newGroupAggSize); + // printf(" nEvent : %d \n", nEvent); + // printf(" New Event Agg Size : %d \n", 2 + sampleSize / Deci / 2 + isExtra); + + // printf("%3d | %08X \n", 1, newHeader0); + // printf("%3d | %08X \n", 2, oldHeader1); + // printf("%3d | %08X \n", 3, oldHeader2); + // printf("%3d | %08X \n", 4, oldHeader3); + // printf("%3d | %3d | %08X \n", 5, 1, newAggHeader0); + // printf("%3d | %3d | %08X \n", 6, 2, word); + } + + if( groupWordCount > 2 ) { + chWordCount ++; + + if( 1 < chWordCount && chWordCount <= chAggSize - 2 ){ // trace + sampleWordCount ++; + uint16_t S0 = word & 0xFFFF; + + if( decimation == 1 ){ + // printf("%3d | %3d | %3d | %3d | %08X | %4X \n", bdAggWordCount, groupWordCount, chWordCount, sampleWordCount, word, S0); + fwrite(&S0, sizeof(S0), 1, outFile); + }else if( sampleWordCount % decimation == 1) { + // printf("%3d | %3d | %3d | %3d | %08X | %4X \n", bdAggWordCount, groupWordCount, chWordCount, sampleWordCount, word, S0); + fwrite(&S0, sizeof(S0), 1, outFile); + } + + }else{ + // printf("%3d | %3d | %3d | %08X \n", bdAggWordCount, groupWordCount, chWordCount, word); + fwrite(&word, sizeof(word), 1, outFile); + } + } + + if( sampleWordCount == sampleSize / 2 ) sampleWordCount = 0; + + if( chAggSize == chWordCount) chWordCount = 0; + + if( groupWordCount == groupAggSize ) groupWordCount = 0; + + } + + if( bdAggWordCount == bdAggSize ) bdAggWordCount = 0; + + } + + } + + outFileSize = ftell(outFile); } + inline void Data::CloseSaveFile(){ if( outFile != nullptr ){ fclose(outFile); @@ -576,7 +708,8 @@ inline unsigned int Data::ReadBuffer(unsigned int nWord, int verbose){ if( buffer == NULL ) return 0; unsigned int word = 0; - for( int i = 0 ; i < 4 ; i++) word += ((buffer[i + 4 * nWord] & 0xFF) << 8*i); + // for( int i = 0 ; i < 4 ; i++) word += ((buffer[i + 4 * nWord] & 0xFF) << 8*i); + memcpy(&word, buffer + 4 * nWord, 4); // Copy 4 bytes directly into word if( verbose >= 2) printf("%6d | 0x%08X |", nWord, word); return word; } @@ -700,6 +833,7 @@ inline int Data::DecodePHADualChannelBlock(unsigned int ChannelMask, bool fastDe bool hasFormatInfo = ((word >> 31) & 0x1); unsigned int aggSize = ( word & 0x7FFFFFFF ) ; if( verbose >= 2 ) printf("Dual Channel size : %d \n", aggSize); + unsigned short decimation = (word >> 12) & 0xF ; unsigned int nSample = 0; /// wave form; unsigned int nEvents = 0; unsigned int extra2Option = 0; @@ -950,6 +1084,7 @@ inline int Data::DecodePSDDualChannelBlock(unsigned int ChannelMask, bool fastDe unsigned int nEvents = 0; nw = nw + 1; word = ReadBuffer(nw, verbose); + unsigned short decimation = (word >> 12) & 0xF ; unsigned int nSample = ( word & 0xFFFF ) * 8; unsigned int digitalProbe1 = ( (word >> 16 ) & 0x7 ); unsigned int digitalProbe2 = ( (word >> 19 ) & 0x7 ); @@ -1169,6 +1304,7 @@ inline int Data::DecodeQDCGroupedChannelBlock(unsigned int ChannelMask, bool fas unsigned int nEvents = 0; nw = nw + 1; word = ReadBuffer(nw, verbose); + unsigned short decimation = (word >> 12) & 0xF ; unsigned int nSample = ( word & 0xFFFF ) * 8; unsigned int analogProbe = ( (word >> 22 ) & 0x3 ); bool hasWaveForm = ( (word >> 27 ) & 0x1 ); @@ -1180,7 +1316,7 @@ inline int Data::DecodeQDCGroupedChannelBlock(unsigned int ChannelMask, bool fas if( verbose >= 2 ) { printf("Charge : %d, Time: %d, Wave : %d, Extra: %d\n", hasEnergy, hasTimeStamp, hasWaveForm, hasExtra); if( hasWaveForm ){ - printf(".... analog Probe (%d): ", analogProbe); + printf("Sample Size : %d .... analog Probe (%d): ", nSample, analogProbe); switch(analogProbe){ case 0 : printf("Input\n"); break; case 1 : printf("Smoothed Input\n"); break; @@ -1232,7 +1368,7 @@ inline int Data::DecodeQDCGroupedChannelBlock(unsigned int ChannelMask, bool fas if( verbose >= 3 ){ printf("%4d| %5d, %d, %d, %d, %d \n", 2*wi, (word & 0xFFF) , (( word >> 12 ) & 0x1 ), (( word >> 13 ) & 0x1 ), (( word >> 14 ) & 0x1 ), (( word >> 15 ) & 0x1 )); - printf("%-22s", ""); + printf("%-21s", ""); printf("%4d| %5d, %d, %d, %d, %d \n", 2*wi+1, (( word >> 16) & 0xFFF), (( word >> 28 ) & 0x1 ), (( word >> 29 ) & 0x1 ), (( word >> 30 ) & 0x1 ), (( word >> 31 ) & 0x1 )); } } -- 2.34.1 From 256390ffafaedb4a8df624bb898eeb4c4cb8d35e Mon Sep 17 00:00:00 2001 From: "Ryan@SOLARIS_testStation" Date: Mon, 14 Oct 2024 17:47:11 -0400 Subject: [PATCH 03/35] added SW Decimation on the Digi setting panle for QDC. this setting is not saved in setting file --- ClassData.h | 11 +++++------ DigiSettingsPanel.cpp | 34 ++++++++++++++++++++++++++++++++++ DigiSettingsPanel.h | 2 ++ FSUDAQ.cpp | 1 + 4 files changed, 42 insertions(+), 6 deletions(-) diff --git a/ClassData.h b/ClassData.h index ef6650a..e82c083 100644 --- a/ClassData.h +++ b/ClassData.h @@ -105,7 +105,7 @@ class Data{ //^================= Saving data bool OpenSaveFile(std::string fileNamePrefix); // return false when fail std::string GetOutFileName() const {return outFileName;} - void SetDecimationFactor(unsigned short factor) { decimation = factor; } + void SetDecimationFactor(unsigned short factor) { decimation = factor; printf("Set Decimation Factor to be %d\n", factor);} void SaveData(); void CloseSaveFile(); unsigned int GetFileSize() const {return outFileSize;} @@ -500,7 +500,6 @@ inline void Data::SaveData(){ int sampleSize = 0; int chAggSize = 0; - uint32_t oldHeader0 = 0; uint32_t oldHeader1 = 0; uint32_t oldHeader2 = 0; uint32_t oldHeader3 = 0; @@ -520,7 +519,6 @@ inline void Data::SaveData(){ // fwrite(buffer + i * chunkSize, sizeof(char), chunkSize, outFile); // fwrite(&word, sizeof(word), 1, outFile); - if( bdAggWordCount == 1 ) oldHeader0 = word; if( bdAggWordCount == 2 ) oldHeader1 = word; if( bdAggWordCount == 3 ) oldHeader2 = word; if( bdAggWordCount == 4 ) oldHeader3 = word; @@ -537,8 +535,7 @@ inline void Data::SaveData(){ sampleSize = (word & 0xFFF) * 8; bool isExtra = ( (word >> 28 ) & 0x1 ); chAggSize = 2 + sampleSize / 2 + isExtra; - uint32_t oldWord = word; - + // uint32_t oldWord = word; word = (word & 0xFFFFF000) + (sampleSize / 8 / Deci); // change the number of sample // printf("============= Sample Size : %d | Ch Size : %d | old %08X new %08X\n", sampleSize, chAggSize, oldWord, word); @@ -874,6 +871,7 @@ inline int Data::DecodePHADualChannelBlock(unsigned int ChannelMask, bool fastDe } } if( hasWaveForm ){ + printf("Sample Size : %d | Decimation: %d \n", nSample, decimation); printf("...... Analog Probe 1 : "); switch (analogProbe1 ){ case 0 : printf("Input \n"); break; @@ -1114,6 +1112,7 @@ inline int Data::DecodePSDDualChannelBlock(unsigned int ChannelMask, bool fastDe } } if( hasWaveForm ){ + printf("Sample Size : %d | Decimation: %d \n", nSample, decimation); printf(".... digital Probe 1 : "); switch(digitalProbe1){ case 0 : printf("Long gate \n"); break; @@ -1316,7 +1315,7 @@ inline int Data::DecodeQDCGroupedChannelBlock(unsigned int ChannelMask, bool fas if( verbose >= 2 ) { printf("Charge : %d, Time: %d, Wave : %d, Extra: %d\n", hasEnergy, hasTimeStamp, hasWaveForm, hasExtra); if( hasWaveForm ){ - printf("Sample Size : %d .... analog Probe (%d): ", nSample, analogProbe); + printf("Sample Size : %d | Decimation %d .... analog Probe (%d): ", nSample, decimation, analogProbe); switch(analogProbe){ case 0 : printf("Input\n"); break; case 1 : printf("Smoothed Input\n"); break; diff --git a/DigiSettingsPanel.cpp b/DigiSettingsPanel.cpp index 8d682cf..1f5fb48 100644 --- a/DigiSettingsPanel.cpp +++ b/DigiSettingsPanel.cpp @@ -2534,6 +2534,40 @@ void DigiSettingsPanel::SetUpBoard_QDC(){ SetUpSpinBox(sbNumEventAgg[ID][0], "Event pre Agg. : ", bdCfgLayout[ID], 5, 0, DPP::QDC::NumberEventsPerAggregate, -1, true); SetUpSpinBox(sbRecordLength[ID][0], "Record Length [ns] : ", bdCfgLayout[ID], 6, 0, DPP::QDC::RecordLength_W, -1, true); + + QLabel * lbSWDeci = new QLabel("SW Decimation Factor :", this); + lbSWDeci->setAlignment(Qt::AlignRight | Qt::AlignCenter); + bdCfgLayout[ID]->addWidget(lbSWDeci, 7, 0); + + cbSWDecimation[ID] = new RComboBox(this); + bdCfgLayout[ID]->addWidget(cbSWDecimation[ID], 7, 1); + cbSWDecimation[ID]->addItem("No Deci.", 0); + cbSWDecimation[ID]->addItem("Factor 2", 1); + cbSWDecimation[ID]->addItem("Factor 4", 2); + cbSWDecimation[ID]->addItem("Factor 8", 3); + cbSWDecimation[ID]->addItem("Factor 16", 4); + cbSWDecimation[ID]->addItem("Factor 32", 5); + cbSWDecimation[ID]->addItem("Factor 64", 6); + cbSWDecimation[ID]->addItem("Factor 128", 7); + + connect(cbSWDecimation[ID], &RComboBox::currentIndexChanged, this, [=](){ + if( !enableSignalSlot ) return; + + unsigned short factor = cbSWDecimation[ID]->currentData().toInt(); + + int deci = pow(2, factor); + + int sampleSize = sbRecordLength[ID][0]->value() / digi[ID]->GetTick2ns(); + + if( sampleSize / deci <= 2 ) { + SendLogMsg("Tried to set waveform decimation to be " + QString::number(deci) + ", which make the number of trace less than 2. Abort."); + cbSWDecimation[ID]->setCurrentIndex(0); + }else{ + SendLogMsg("Set waveform decimation to be " + QString::number(deci) + "."); + digi[ID]->GetData()->SetDecimationFactor(factor); + } + }); + } void DigiSettingsPanel::SetUpChannel_QDC(){ diff --git a/DigiSettingsPanel.h b/DigiSettingsPanel.h index 495d972..8aef719 100644 --- a/DigiSettingsPanel.h +++ b/DigiSettingsPanel.h @@ -125,6 +125,8 @@ private: QGridLayout * bdTriggerLayout[MaxNDigitizer]; QGridLayout * bdLVDSLayout[MaxNDigitizer]; + RComboBox * cbSWDecimation[MaxNDigitizer]; // software decimation + QCheckBox * chkAutoDataFlush[MaxNDigitizer]; QCheckBox * chkDecimateTrace[MaxNDigitizer]; QCheckBox * chkTrigPropagation[MaxNDigitizer]; diff --git a/FSUDAQ.cpp b/FSUDAQ.cpp index 676fc7d..21587af 100644 --- a/FSUDAQ.cpp +++ b/FSUDAQ.cpp @@ -1803,6 +1803,7 @@ void FSUDAQ::OpenDigiSettings(){ digiSettings = new DigiSettingsPanel(digi, nDigi, rawDataPath); //connect(scope, &Scope::SendLogMsg, this, &FSUDAQ::LogMsg); connect(digiSettings, &DigiSettingsPanel::UpdateOtherPanels, this, [=](){ UpdateAllPanels(2); }); + connect(digiSettings, &DigiSettingsPanel::SendLogMsg, this, &FSUDAQ::LogMsg); digiSettings->show(); }else{ -- 2.34.1 From fa3e015e3e7d841b9b925f3186d82dcf2f8c0757 Mon Sep 17 00:00:00 2001 From: "Ryan@SOLARIS_testStation" Date: Mon, 14 Oct 2024 18:33:18 -0400 Subject: [PATCH 04/35] Created an artifical Register 0x8044 for SWDecimation. Simplify a lot of things --- ClassDigitizer.cpp | 6 ++++++ DigiSettingsPanel.cpp | 46 ++++++++++++------------------------------- DigiSettingsPanel.h | 3 ++- RegisterAddress.h | 7 +++++-- 4 files changed, 26 insertions(+), 36 deletions(-) diff --git a/ClassDigitizer.cpp b/ClassDigitizer.cpp index 1c3bb54..a2094b0 100644 --- a/ClassDigitizer.cpp +++ b/ClassDigitizer.cpp @@ -743,6 +743,8 @@ void Digitizer::WriteRegister (Reg registerAddress, uint32_t value, int ch, bool ret = CAEN_DGTZ_WriteRegister(handle, registerAddress.ActualAddress(ch), value); + if( registerAddress == DPP::DecimationFactor ) data->SetDecimationFactor(value); + if( ret == 0 && isSave2MemAndFile && !AcqRun && registerAddress.GetRWType() == RW::ReadWrite ) { if( ch < 0 ) { if( registerAddress.GetAddress() < 0x8000 ){ @@ -790,6 +792,8 @@ uint32_t Digitizer::ReadRegister(Reg registerAddress, unsigned short ch, bool is SaveSettingToFile(registerAddress, returnData, ch); } + if( registerAddress == DPP::DecimationFactor ) data->SetDecimationFactor( returnData ); + std::stringstream ss; ss << std::hex << registerAddress.ActualAddress(ch); @@ -995,6 +999,8 @@ void Digitizer::ProgramSettingsToBoard(){ haha = DPP::QDC::RecordLength_W; WriteRegister(haha, GetSettingFromMemory(haha), -1, false); // haha = DPP::QDC::NumberEventsPerAggregate; WriteRegister(haha, GetSettingFromMemory(haha), -1, false); + haha = DPP::DecimationFactor; WriteRegister(haha, GetSettingFromMemory(haha), -1, false); + /// Channels Setting for( int ch = 0; ch < GetNumRegChannels(); ch ++){ for( int p = 0; p < (int) RegisterChannelList_QDC.size(); p++){ diff --git a/DigiSettingsPanel.cpp b/DigiSettingsPanel.cpp index 1f5fb48..d345ab3 100644 --- a/DigiSettingsPanel.cpp +++ b/DigiSettingsPanel.cpp @@ -548,6 +548,16 @@ void DigiSettingsPanel::SetUpSpinBox(RSpinBox * &sb, QString label, QGridLayout return; } + if( para == DPP::DecimationFactor ){ + int deci = pow(2, sb->value()); + if( sbRecordLength[ID][0]->value() / digi[ID]->GetTick2ns() <= 2 * deci ){ + SendLogMsg("Tried to set waveform decimation to be " + QString::number(deci) + ", which make the number of trace less than 2. Abort."); + sbSWDecimation[ID]->setValue(0); + }else{ + SendLogMsg("Set waveform decimation to be " + QString::number(deci) + "."); + } + } + uint32_t bit = para.GetPartialStep() == -1 ? sb->value() : sb->value() / para.GetPartialStep() / digi[ID]->GetTick2ns(); if( para.IsCoupled() == true && chID >= 0 ) { @@ -2534,39 +2544,7 @@ void DigiSettingsPanel::SetUpBoard_QDC(){ SetUpSpinBox(sbNumEventAgg[ID][0], "Event pre Agg. : ", bdCfgLayout[ID], 5, 0, DPP::QDC::NumberEventsPerAggregate, -1, true); SetUpSpinBox(sbRecordLength[ID][0], "Record Length [ns] : ", bdCfgLayout[ID], 6, 0, DPP::QDC::RecordLength_W, -1, true); - - QLabel * lbSWDeci = new QLabel("SW Decimation Factor :", this); - lbSWDeci->setAlignment(Qt::AlignRight | Qt::AlignCenter); - bdCfgLayout[ID]->addWidget(lbSWDeci, 7, 0); - - cbSWDecimation[ID] = new RComboBox(this); - bdCfgLayout[ID]->addWidget(cbSWDecimation[ID], 7, 1); - cbSWDecimation[ID]->addItem("No Deci.", 0); - cbSWDecimation[ID]->addItem("Factor 2", 1); - cbSWDecimation[ID]->addItem("Factor 4", 2); - cbSWDecimation[ID]->addItem("Factor 8", 3); - cbSWDecimation[ID]->addItem("Factor 16", 4); - cbSWDecimation[ID]->addItem("Factor 32", 5); - cbSWDecimation[ID]->addItem("Factor 64", 6); - cbSWDecimation[ID]->addItem("Factor 128", 7); - - connect(cbSWDecimation[ID], &RComboBox::currentIndexChanged, this, [=](){ - if( !enableSignalSlot ) return; - - unsigned short factor = cbSWDecimation[ID]->currentData().toInt(); - - int deci = pow(2, factor); - - int sampleSize = sbRecordLength[ID][0]->value() / digi[ID]->GetTick2ns(); - - if( sampleSize / deci <= 2 ) { - SendLogMsg("Tried to set waveform decimation to be " + QString::number(deci) + ", which make the number of trace less than 2. Abort."); - cbSWDecimation[ID]->setCurrentIndex(0); - }else{ - SendLogMsg("Set waveform decimation to be " + QString::number(deci) + "."); - digi[ID]->GetData()->SetDecimationFactor(factor); - } - }); + SetUpSpinBox( sbSWDecimation[ID], "SW Decimation Factor : ", bdCfgLayout[ID], 7, 0, DPP::DecimationFactor, -1, true); } @@ -4039,6 +4017,8 @@ void DigiSettingsPanel::UpdateSettings_QDC(){ UpdateSpinBox(sbNumEventAgg[ID][0], DPP::QDC::NumberEventsPerAggregate, -1); + UpdateSpinBox(sbSWDecimation[ID], DPP::DecimationFactor, -1); + for(int grp = 0; grp < digi[ID]->GetNumRegChannels(); grp ++){ UpdateSpinBox(sbPreTrigger[ID][grp], DPP::QDC::PreTrigger, grp); diff --git a/DigiSettingsPanel.h b/DigiSettingsPanel.h index 8aef719..779000c 100644 --- a/DigiSettingsPanel.h +++ b/DigiSettingsPanel.h @@ -125,7 +125,8 @@ private: QGridLayout * bdTriggerLayout[MaxNDigitizer]; QGridLayout * bdLVDSLayout[MaxNDigitizer]; - RComboBox * cbSWDecimation[MaxNDigitizer]; // software decimation + // RComboBox * cbSWDecimation[MaxNDigitizer]; // software decimation + RSpinBox * sbSWDecimation[MaxNDigitizer]; QCheckBox * chkAutoDataFlush[MaxNDigitizer]; QCheckBox * chkDecimateTrace[MaxNDigitizer]; diff --git a/RegisterAddress.h b/RegisterAddress.h index 2bf8036..619203f 100644 --- a/RegisterAddress.h +++ b/RegisterAddress.h @@ -171,7 +171,7 @@ const Reg FrontPanelTRGOUTEnableMask ("FrontPanelTRGOUTEnableMask" , 0x8110, const Reg PostTrigger ("PostTrigger" , 0x8114, RW::ReadWrite, false, {}); /// R/W const Reg LVDSIOData ("LVDSIOData" , 0x8118, RW::ReadWrite, false, {}); /// R/W const Reg FrontPanelIOControl ("FrontPanelIOControl" , 0x811C, RW::ReadWrite, false, {}); /// R/W -const Reg RegChannelEnableMask ("RegChannelEnableMask" , 0x8120, RW::ReadWrite, false, {}); /// R/W +const Reg RegChannelEnableMask ("RegChannelEnableMask" , 0x8120, RW::ReadWrite, false, {}); /// R/W const Reg ROCFPGAFirmwareRevision_R ("ROCFPGAFirmwareRevision_R" , 0x8124, RW::ReadONLY , false, {}); /// R const Reg EventStored_R ("EventStored_R" , 0x812C, RW::ReadONLY , false, {}); /// R const Reg VoltageLevelModeConfig ("VoltageLevelModeConfig" , 0x8138, RW::ReadWrite, false, {}); /// R/W @@ -199,7 +199,6 @@ const Reg Scratch ("Scratch" , 0xEF20, const Reg SoftwareReset_W ("SoftwareReset_W" , 0xEF24, RW::WriteONLY, false, {}); /// W const Reg SoftwareClear_W ("SoftwareClear_W" , 0xEF28, RW::WriteONLY, false, {}); /// W - ///====== Common for PHA and PSD namespace DPP { @@ -601,6 +600,9 @@ namespace DPP { const Reg TriggerValidationMask_G ("TriggerValidationMask_G" , 0x8180, RW::ReadWrite, true, {}); /// R/W, + //& Artifical Register that not in CAEN manual + const Reg DecimationFactor ("Decimation Factor" , 0x8044, RW::ReadWrite, false, 0x7, -1); /// R/W + namespace PHA { const Reg DataFlush_W ("DataFlush_W" , 0x103C, RW::WriteONLY, false, {}); /// W not sure const Reg ChannelStopAcquisition ("ChannelStopAcquisition" , 0x1040, RW::ReadWrite, false, {{"Run", 0}, {"Stop", 1}}); /// R/W not sure @@ -1027,6 +1029,7 @@ const std::vector RegisterBoardList_QDC = { DPP::QDC::NumberEventsPerAggregate, DPP::QDC::RecordLength_W, DPP::QDC::RecordLength_R, + DPP::DecimationFactor, DPP::AcquisitionControl, DPP::AcquisitionStatus_R, DPP::SoftwareTrigger_W, -- 2.34.1 From 83fbea2743084fc4b9a493ef9b74990d4c96ec69 Mon Sep 17 00:00:00 2001 From: "Ryan@SOLARIS_testStation" Date: Tue, 15 Oct 2024 17:23:43 -0400 Subject: [PATCH 05/35] bug fix on Histogram2D --- FSUDAQ.cpp | 3 -- Histogram2D.h | 131 +++++++++++++++++++++++++------------------------- 2 files changed, 66 insertions(+), 68 deletions(-) diff --git a/FSUDAQ.cpp b/FSUDAQ.cpp index 21587af..be66139 100644 --- a/FSUDAQ.cpp +++ b/FSUDAQ.cpp @@ -59,9 +59,6 @@ FSUDAQ::FSUDAQ(QWidget *parent) : QMainWindow(parent){ cbOpenDigitizers = new RComboBox(this); cbOpenDigitizers->addItem("Open Digitizers ... ", 0); cbOpenDigitizers->addItem("Open Digitizers via Optical/USB", 1); - // cbOpenDigitizers->addItem("Open Digitizers (default program)", 2); - // cbOpenDigitizers->addItem("Open Digitizers + load Settings", 3); - //cbOpenDigitizers->addItem("Open Digitizers via USB", 3); cbOpenDigitizers->addItem("Open Digitizers via A4818(s)", 4); layout->addWidget(cbOpenDigitizers, 0, 0); connect(cbOpenDigitizers, &RComboBox::currentIndexChanged, this, &FSUDAQ::OpenDigitizers); diff --git a/Histogram2D.h b/Histogram2D.h index 0392a24..c080c60 100644 --- a/Histogram2D.h +++ b/Histogram2D.h @@ -439,12 +439,15 @@ inline void Histogram2D::rightMouseClickMenu(QMouseEvent * event){ QAction * a4 = menu->addAction("Rebin (clear histogram)"); QAction * a8 = menu->addAction("Load Cut(s)"); QAction * a5 = menu->addAction("Create a Cut"); - QAction * a7 = nullptr; + + QAction * b0 = nullptr; + QAction * b1 = nullptr; + QAction * b2 = nullptr; if( numCut > 0 ) { - a7 = menu->addAction("Save Cut(s)"); menu->addSeparator(); - menu->addAction("Add/Edit names to Cuts"); - menu->addAction("Clear all Cuts"); + b0 = menu->addAction("Save Cut(s)"); + b2 = menu->addAction("Add/Edit names to Cuts"); + b1 = menu->addAction("Clear all Cuts"); } for( int i = 0; i < cutList.size(); i++){ if( cutList[i].isEmpty()) continue; @@ -454,20 +457,25 @@ inline void Histogram2D::rightMouseClickMenu(QMouseEvent * event){ QAction *selectedAction = menu->exec(event->globalPosition().toPoint()); + // qDebug() << "======================="; + // qDebug() << selectedAction; + // qDebug() << b2; + + if( selectedAction == nullptr ){ + usingMenu = false; + return; + } + if( selectedAction == a1 ){ xAxis->setRangeLower(xMin); xAxis->setRangeUpper(xMax); yAxis->setRangeLower(yMin); yAxis->setRangeUpper(yMax); replot(); - usingMenu = false; - return; } if( selectedAction == a2 ) { Clear(); - usingMenu = false; - return; } if( selectedAction == a3 ){ @@ -478,23 +486,17 @@ inline void Histogram2D::rightMouseClickMenu(QMouseEvent * event){ } } replot(); - usingMenu = false; - return; } if( selectedAction == a4){ rightMouseClickRebin(); - usingMenu = false; - return; } if( selectedAction == a5 ){ tempCut.clear(); tempCutID ++; isDrawCut= true; - usingMenu = false; numCut ++; - return; } if( selectedAction == a6){ @@ -508,6 +510,55 @@ inline void Histogram2D::rightMouseClickMenu(QMouseEvent * event){ replot(); } + if( selectedAction == a8 ){ // load Cuts + QString filePath = QFileDialog::getOpenFileName(this, + "Load Cuts from File", + settingPath, + "Text file (*.txt)"); + + if (!filePath.isEmpty()) LoadCuts(filePath); + } + + //*==================================== when there are cuts + if( selectedAction == b0 ){ // Save Cuts + + QString filePath = QFileDialog::getSaveFileName(this, + "Save Cuts to File", + settingPath, + "Text file (*.txt)"); + + if (!filePath.isEmpty()) SaveCuts(filePath); + } + + if( selectedAction == b1 ){ + ClearAllCuts(); + } + + if( selectedAction == b2 ){ + + QDialog dialog(this); + dialog.setWindowTitle("Add/Edit name of cuts "); + + QFormLayout layout(&dialog); + + for(int i = 0; i < cutTextIDList.count(); i++){ + if( cutTextIDList[i] < 0 ) continue; + QLineEdit * le = new QLineEdit(&dialog); + layout.addRow(colorCycle[i%colorCycle.count()].second, le); + le->setText( cutNameList[i] ); + connect(le, &QLineEdit::textChanged, this, [=](){ + le->setStyleSheet("color : blue;"); + }); + connect(le, &QLineEdit::returnPressed, this, [=](){ + le->setStyleSheet(""); + cutNameList[i] = le->text(); + ((QCPItemText *) this->item(cutTextIDList[i]))->setText(le->text()); + replot(); + }); + } + dialog.exec(); + } + if( selectedAction && numCut > 0 && selectedAction->text().contains("Delete ") ){ QString haha = selectedAction->text(); @@ -542,61 +593,11 @@ inline void Histogram2D::rightMouseClickMenu(QMouseEvent * event){ cutNameList.clear(); cutEntryList.clear(); } - return; } - if( selectedAction && numCut > 0 && selectedAction->text().contains("Clear all Cuts") ){ - ClearAllCuts(); - return; - } - if( selectedAction && numCut > 0 && selectedAction->text().contains("Add/Edit names to Cuts") ){ - - QDialog dialog(this); - dialog.setWindowTitle("Add/Edit name of cuts "); - - QFormLayout layout(&dialog); - - for(int i = 0; i < cutTextIDList.count(); i++){ - if( cutTextIDList[i] < 0 ) continue; - QLineEdit * le = new QLineEdit(&dialog); - layout.addRow(colorCycle[i%colorCycle.count()].second, le); - le->setText( cutNameList[i] ); - connect(le, &QLineEdit::textChanged, this, [=](){ - le->setStyleSheet("color : blue;"); - }); - connect(le, &QLineEdit::returnPressed, this, [=](){ - le->setStyleSheet(""); - cutNameList[i] = le->text(); - ((QCPItemText *) this->item(cutTextIDList[i]))->setText(le->text()); - replot(); - }); - } - dialog.exec(); - return; - } - - if( selectedAction == a8 ){ // load Cuts - QString filePath = QFileDialog::getOpenFileName(this, - "Load Cuts from File", - settingPath, - "Text file (*.txt)"); - - if (!filePath.isEmpty()) LoadCuts(filePath); - - } - - if( selectedAction == a7 ){ // Save Cuts - - QString filePath = QFileDialog::getSaveFileName(this, - "Save Cuts to File", - settingPath, - "Text file (*.txt)"); - - if (!filePath.isEmpty()) SaveCuts(filePath); - - } + usingMenu = false; } -- 2.34.1 From f8b9abc70d322d5e6793e08d585cd42b24dd6dc7 Mon Sep 17 00:00:00 2001 From: "Ryan@SOLARIS_testStation" Date: Tue, 15 Oct 2024 17:27:16 -0400 Subject: [PATCH 06/35] remove any UpdatePlot in SingleSpectra::FillHistogram --- SingleSpectra.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/SingleSpectra.cpp b/SingleSpectra.cpp index 95a1081..be0c05e 100644 --- a/SingleSpectra.cpp +++ b/SingleSpectra.cpp @@ -302,13 +302,13 @@ void SingleSpectra::FillHistograms(){ } hist2D[ID]->Fill(ch, data); } - if( histVisibility[ID][ch] ) hist[ID][ch]->UpdatePlot(); + // if( histVisibility[ID][ch] ) hist[ID][ch]->UpdatePlot(); clock_gettime(CLOCK_REALTIME, &t1); if( t1.tv_nsec - t0.tv_nsec + (t1.tv_sec - t0.tv_sec)*1e9 > maxFillTimePerDigi * 1e6 ) break; } - if( hist2DVisibility[ID] ) hist2D[ID]->UpdatePlot(); + // if( hist2DVisibility[ID] ) hist2D[ID]->UpdatePlot(); // digiMTX[ID].unlock(); } -- 2.34.1 From 84b89cb36aac47eaa5c944ac52a5c653b8675121 Mon Sep 17 00:00:00 2001 From: "Ryan@SOLARIS_testStation" Date: Wed, 16 Oct 2024 16:56:59 -0400 Subject: [PATCH 07/35] change the SingleSpectra::FillHistogram() Algorithm --- SingleSpectra.cpp | 205 +++++++++++++++++++++++++++++----------------- SingleSpectra.h | 6 +- 2 files changed, 135 insertions(+), 76 deletions(-) diff --git a/SingleSpectra.cpp b/SingleSpectra.cpp index be0c05e..cc8cdc0 100644 --- a/SingleSpectra.cpp +++ b/SingleSpectra.cpp @@ -4,6 +4,7 @@ #include #include #include +#include // #include SingleSpectra::SingleSpectra(Digitizer ** digi, unsigned int nDigi, QString rawDataPath, QMainWindow * parent) : QMainWindow(parent){ @@ -12,7 +13,7 @@ SingleSpectra::SingleSpectra(Digitizer ** digi, unsigned int nDigi, QString rawD this->nDigi = nDigi; this->settingPath = rawDataPath + "/HistogramSettings.txt"; - maxFillTimeinMilliSec = 1000; + maxFillTimeinMilliSec = 900; maxFillTimePerDigi = maxFillTimeinMilliSec/nDigi; isSignalSlotActive = true; @@ -51,15 +52,17 @@ SingleSpectra::SingleSpectra(Digitizer ** digi, unsigned int nDigi, QString rawD isSignalSlotActive = true; //printf("oldCh = %d \n", oldCh); - if( oldCh >= digi[index]->GetNumInputCh()) { - cbCh->setCurrentIndex(0); - }else{ - if( oldCh >= 0 ){ - cbCh->setCurrentIndex(oldCh); - }else{ - cbCh->setCurrentIndex(0); - } - } + // if( oldCh >= digi[index]->GetNumInputCh()) { + // cbCh->setCurrentIndex(0); + // }else{ + // if( oldCh >= 0 ){ + // cbCh->setCurrentIndex(oldCh); + // }else{ + // cbCh->setCurrentIndex(0); + // } + // } + + cbCh->setCurrentIndex(oldChComboBoxindex[index]); ChangeHistView(); }); @@ -81,6 +84,7 @@ SingleSpectra::SingleSpectra(Digitizer ** digi, unsigned int nDigi, QString rawD } }); + chkIsFillHistogram = new QCheckBox("Fill Histograms", this); ctrlLayout->addWidget(chkIsFillHistogram, 0, 6, 1, 2); chkIsFillHistogram->setChecked(false); @@ -133,10 +137,12 @@ SingleSpectra::SingleSpectra(Digitizer ** digi, unsigned int nDigi, QString rawD histLayout->addWidget(hist2D[0], 0, 0); hist2DVisibility[0] = true; - oldBd = 0; - oldCh = digi[0]->GetNumInputCh(); } + //set default oldChComboBoxindex + for( unsigned int i = 0; i < nDigi; i++ ) oldChComboBoxindex[i] = 0; + oldBd = 0; + layout->setStretch(0, 1); layout->setStretch(1, 6); @@ -149,12 +155,17 @@ SingleSpectra::SingleSpectra(Digitizer ** digi, unsigned int nDigi, QString rawD histWorker->moveToThread(workerThread); - // Setup the timer to trigger every second - connect(timer, &QTimer::timeout, histWorker, &HistWorker::FillHistograms); - + // connect(timer, &QTimer::timeout, histWorker, &HistWorker::FillHistograms); connect( histWorker, &HistWorker::workDone, this, &SingleSpectra::ReplotHistograms); - workerThread->start(); + // workerThread->start(); + + connect(timer, &QTimer::timeout, this, [=](){ + if( isFillingHistograms == false){ + histWorker->FillHistograms(); + // ReplotHistograms(); + } + }); } @@ -198,23 +209,34 @@ void SingleSpectra::ChangeHistView(){ //printf("bd : %d, ch : %d \n", bd, ch); // Remove oldCh - if( oldCh >= 0 && oldCh < digi[oldBd]->GetNumInputCh()){ - histLayout->removeWidget(hist[oldBd][oldCh]); - hist[oldBd][oldCh]->setParent(nullptr); - histVisibility[oldBd][oldCh] = false; - } + int oldCh = oldChComboBoxindex[oldBd] == 0 ? digi[oldBd]->GetNumInputCh() : oldChComboBoxindex[oldBd] - 1; - if( oldCh == digi[oldBd]->GetNumInputCh() ){ + if( oldChComboBoxindex[oldBd] > 0 ){ + histLayout->removeWidget(hist[oldBd][oldCh]); + histVisibility[oldBd][oldCh] = false; + hist[oldBd][oldCh]->setParent(nullptr); + }else{ histLayout->removeWidget(hist2D[oldBd]); hist2D[oldBd]->setParent(nullptr); hist2DVisibility[oldBd] = false; } + // if( oldCh >= 0 && oldCh < digi[oldBd]->GetNumInputCh()){ + // histLayout->removeWidget(hist[oldBd][oldCh]); + // hist[oldBd][oldCh]->setParent(nullptr); + // histVisibility[oldBd][oldCh] = false; + // } + + // if( oldCh == digi[oldBd]->GetNumInputCh() ){ + // histLayout->removeWidget(hist2D[oldBd]); + // hist2D[oldBd]->setParent(nullptr); + // hist2DVisibility[oldBd] = false; + // } + // Add ch if( ch >=0 && ch < digi[bd]->GetNumInputCh()) { histLayout->addWidget(hist[bd][ch], 0, 0); histVisibility[bd][ch] = true; - hist[bd][ch]->UpdatePlot(); } @@ -225,7 +247,7 @@ void SingleSpectra::ChangeHistView(){ } oldBd = bd; - oldCh = ch; + oldChComboBoxindex[bd] = cbCh->currentIndex(); // for( unsigned int i = 0; i < nDigi; i++ ){ // if( hist2DVisibility[i] ) printf(" hist2D-%d is visible\n", i); @@ -244,74 +266,111 @@ void SingleSpectra::FillHistograms(){ if( isFillingHistograms) return; isFillingHistograms = true; - timespec t0, t1; + // timespec t0, t1; + timespec ta, tb; - QVector randomDigiList = generateNonRepeatedCombination(nDigi); + printf("####################### SingleSpectra::%s\n", __func__); + clock_gettime(CLOCK_REALTIME, &ta); - // qDebug() << randomDigiList; + std::vector digiChList; // (digi*1000 + ch) + std::vector digiChLastIndex; // lastIndex + std::vector digiChLoopIndex; // loopIndex + std::vector digiChFilled; - for( int i = 0; i < nDigi; i++){ - int ID = randomDigiList[i]; - - QVector randomChList = generateNonRepeatedCombination(digi[ID]->GetNumInputCh()); - - // qDebug() << randomChList; - // digiMTX[ID].lock(); - // digi[ID]->GetData()->PrintAllData(); - - clock_gettime(CLOCK_REALTIME, &t0); - for( int k = 0; k < digi[ID]->GetNumInputCh(); k ++ ){ - int ch = randomChList[k]; + for( int ID = 0; ID < nDigi; ID++){ + for( int ch = 0; ch < digi[ID]->GetNumInputCh(); ch++){ int lastIndex = digi[ID]->GetData()->GetDataIndex(ch); - if( lastIndex < 0 ) continue; - // printf("--- ch %2d | last index %d \n", ch, lastIndex); - int loopIndex = digi[ID]->GetData()->GetLoopIndex(ch); int temp1 = lastIndex + loopIndex * digi[ID]->GetData()->GetDataSize(); int temp2 = lastFilledIndex[ID][ch] + loopFilledIndex[ID][ch] * digi[ID]->GetData()->GetDataSize() + 1; - // printf("loopIndx : %d | ID now : %d, ID old : %d \n", loopIndex, temp1, temp2); - if( temp1 <= temp2 ) continue; + digiChList.push_back( ID*1000 + ch ) ; + digiChLastIndex.push_back(lastIndex); + digiChLoopIndex.push_back(loopIndex); + digiChFilled.push_back(false); + } + } - if( temp1 - temp2 > digi[ID]->GetData()->GetDataSize() ) { //DefaultDataSize = 10k - temp2 = temp1 - digi[ID]->GetData()->GetDataSize(); - lastFilledIndex[ID][ch] = lastIndex; - lastFilledIndex[ID][ch] = loopIndex - 1; - } + int nSize = digiChList.size(); - // printf("ch %d | regulated ID now %d new %d | last fill idx %d\n", ch, temp2, temp1, lastFilledIndex[ID][ch]); - - for( int j = 0 ; j <= temp1 - temp2; j ++){ - lastFilledIndex[ID][ch] ++; - if( lastFilledIndex[ID][ch] > digi[ID]->GetData()->GetDataSize() ) { - lastFilledIndex[ID][ch] = 0; - loopFilledIndex[ID][ch] ++; - } + // printf("------------ nSize : %d \n", nSize); - uShort data = digi[ID]->GetData()->GetEnergy(ch, lastFilledIndex[ID][ch]); + if( nSize == 0 ) { + isFillingHistograms = false; + return; + } - // printf(" ch: %d, last fill idx : %d | %d \n", ch, lastFilledIndex[ID][ch], data); + // this method, small trigger rate channel will have more chance to fill all data + do{ + size_t filledCount = 0; + for( size_t i = 0; i < digiChFilled.size() ; i++ ){ + if( digiChFilled[i] ) filledCount ++; + } + if( filledCount == digiChFilled.size() ) break; - hist[ID][ch]->Fill( data ); - if( digi[i]->GetDPPType() == DPPTypeCode::DPP_PSD_CODE ){ - uShort e2 = digi[ID]->GetData()->GetEnergy2(ch, lastFilledIndex[ID][ch]); - // printf("%u \n", e2); - hist[ID][ch]->Fill( e2, 1); - } - hist2D[ID]->Fill(ch, data); - } - // if( histVisibility[ID][ch] ) hist[ID][ch]->UpdatePlot(); + int randomValue = QRandomGenerator::global()->bounded(nSize); + if( digiChFilled[randomValue] == true ) continue; + + int digiCh = digiChList[randomValue]; + int ID = digiCh / 1000; + int ch = digiCh % 1000; + // printf(" -------------------- %d / %d | %d\n", randomValue, nSize-1, digiCh); - clock_gettime(CLOCK_REALTIME, &t1); - if( t1.tv_nsec - t0.tv_nsec + (t1.tv_sec - t0.tv_sec)*1e9 > maxFillTimePerDigi * 1e6 ) break; + int lastIndex = digiChLastIndex[randomValue]; + int loopIndex = digiChLoopIndex[randomValue]; + + int temp1 = lastIndex + loopIndex * digi[ID]->GetData()->GetDataSize(); + int temp2 = lastFilledIndex[ID][ch] + loopFilledIndex[ID][ch] * digi[ID]->GetData()->GetDataSize() + 1; + + if( temp1 <= temp2 ) { + digiChFilled[randomValue] = true; + // printf("Digi-%2d ch-%2d all filled | %zu\n", ID, ch, digiChList.size()); + continue; + } + if( temp1 - temp2 > digi[ID]->GetData()->GetDataSize() ) { //DefaultDataSize = 10k + temp2 = temp1 - digi[ID]->GetData()->GetDataSize(); + lastFilledIndex[ID][ch] = lastIndex; + lastFilledIndex[ID][ch] = loopIndex - 1; } - // if( hist2DVisibility[ID] ) hist2D[ID]->UpdatePlot(); - // digiMTX[ID].unlock(); + lastFilledIndex[ID][ch] ++; + if( lastFilledIndex[ID][ch] > digi[ID]->GetData()->GetDataSize() ) { + lastFilledIndex[ID][ch] = 0; + loopFilledIndex[ID][ch] ++; + } - } + uShort data = digi[ID]->GetData()->GetEnergy(ch, lastFilledIndex[ID][ch]); + + hist[ID][ch]->Fill( data ); + if( digi[ID]->GetDPPType() == DPPTypeCode::DPP_PSD_CODE ){ + uShort e2 = digi[ID]->GetData()->GetEnergy2(ch, lastFilledIndex[ID][ch]); + hist[ID][ch]->Fill( e2, 1); + } + hist2D[ID]->Fill(ch, data); + + clock_gettime(CLOCK_REALTIME, &tb); + }while( (tb.tv_nsec - ta.tv_nsec)/1e6 + (tb.tv_sec - ta.tv_sec)*1e3 < maxFillTimeinMilliSec ); + + //*--------------- generate fillign report + for( size_t i = 0; i < digiChFilled.size() ; i++){ + int digiCh = digiChList[i]; + int ID = digiCh / 1000; + int ch = digiCh % 1000; + // printf(" -------------------- %d / %d | %d\n", randomValue, nSize-1, digiCh); + + int lastIndex = digiChLastIndex[i]; + int loopIndex = digiChLoopIndex[i]; + + int temp1 = lastIndex + loopIndex * digi[ID]->GetData()->GetDataSize(); + int temp2 = lastFilledIndex[ID][ch] + loopFilledIndex[ID][ch] * digi[ID]->GetData()->GetDataSize() + 1; + + printf("Digi-%2d ch-%2d | event unfilled %d\n", ID, ch, temp1 - temp2 ); + } + + clock_gettime(CLOCK_REALTIME, &tb); + printf("total time : %8.3f ms\n", (tb.tv_nsec - ta.tv_nsec)/1e6 + (tb.tv_sec - ta.tv_sec)*1e3 ); isFillingHistograms = false; diff --git a/SingleSpectra.h b/SingleSpectra.h index 60cb25d..6b5b498 100644 --- a/SingleSpectra.h +++ b/SingleSpectra.h @@ -73,7 +73,6 @@ private: Histogram1D * hist[MaxNDigitizer][MaxNChannels]; Histogram2D * hist2D[MaxNDigitizer]; - QCheckBox * chkIsFillHistogram; RComboBox * cbDivision; @@ -83,7 +82,8 @@ private: QGroupBox * histBox; QGridLayout * histLayout; - int oldBd, oldCh; + int oldBd; + int oldChComboBoxindex[MaxNDigitizer]; // the ID of hist for display QString settingPath; @@ -97,7 +97,7 @@ private: }; -//^#======================================================== HistWorker +// //^#======================================================== HistWorker class HistWorker : public QObject{ Q_OBJECT public: -- 2.34.1 From 88823af2c68e1932e091eb64e9bb94c1e426dafd Mon Sep 17 00:00:00 2001 From: "Ryan@SOLARIS_testStation" Date: Wed, 16 Oct 2024 17:57:12 -0400 Subject: [PATCH 08/35] change the Decimation for QDC to be average of 2^n --- ClassData.h | 55 ++++++++++++++++++++++++++----------------- DigiSettingsPanel.cpp | 2 ++ 2 files changed, 36 insertions(+), 21 deletions(-) diff --git a/ClassData.h b/ClassData.h index e82c083..2f2c334 100644 --- a/ClassData.h +++ b/ClassData.h @@ -504,6 +504,8 @@ inline void Data::SaveData(){ uint32_t oldHeader2 = 0; uint32_t oldHeader3 = 0; + uint16_t average = 0; // to calculate Decimation average + for( size_t i = 0; i < numChunk; i++ ){ bdAggWordCount ++; @@ -513,7 +515,7 @@ inline void Data::SaveData(){ if( bdAggWordCount == 1 ) { bdAggSize = word & 0x0FFFFFFF; - // printf("###################### Bd Agg Size : %d\n", bdAggSize); + printf("###################### Bd Agg Size : %d\n", bdAggSize); } // fwrite(buffer + i * chunkSize, sizeof(char), chunkSize, outFile); @@ -529,18 +531,19 @@ inline void Data::SaveData(){ if( groupWordCount == 1 ) { groupAggSize = word & 0x3FFFFFFF; - // printf("============= Coupled Channel Agg Size : %d \n", groupAggSize); + printf("============= Coupled Channel Agg Size : %d \n", groupAggSize); } if( groupWordCount == 2 ) { sampleSize = (word & 0xFFF) * 8; bool isExtra = ( (word >> 28 ) & 0x1 ); chAggSize = 2 + sampleSize / 2 + isExtra; - // uint32_t oldWord = word; - word = (word & 0xFFFFF000) + (sampleSize / 8 / Deci); // change the number of sample - // printf("============= Sample Size : %d | Ch Size : %d | old %08X new %08X\n", sampleSize, chAggSize, oldWord, word); + uint32_t oldWord = word; + uint32_t newSampleSize = sampleSize / Deci; + word = (word & 0xFFFFF000) + (newSampleSize / 8 ); // change the number of sample + printf("============= Sample Size : %d | Ch Size : %d | old %08X new %08X\n", sampleSize, chAggSize, oldWord, word); int nEvent = (groupAggSize - 2 ) / chAggSize; - int newGroupAggSize = 2 + nEvent * ( 2 + sampleSize / Deci / 2 + isExtra ); + int newGroupAggSize = 2 + nEvent * ( 2 + newSampleSize / 2 + isExtra ); int newBdAggSize = 4 + newGroupAggSize; //Write board header and Agg header @@ -550,21 +553,22 @@ inline void Data::SaveData(){ fwrite(&oldHeader2, sizeof(uint32_t), 1, outFile); fwrite(&oldHeader3, sizeof(uint32_t), 1, outFile); - uint32_t newAggHeader0 = (0x8 << 28) + newGroupAggSize + (decimation << 12); // add decimation factor in the word + uint32_t newAggHeader0 = (0x8 << 28) + newGroupAggSize ; // add decimation factor in the word + uint32_t newAggHeader1 = word + (decimation << 12); // add decimation factor in the word fwrite(&newAggHeader0, sizeof(uint32_t), 1, outFile); - fwrite(&word, sizeof(uint32_t), 1, outFile); + fwrite(&newAggHeader1, sizeof(uint32_t), 1, outFile); // printf(" New Board Agg Size : %d \n", newBdAggSize); // printf(" New Group Agg Size : %d \n", newGroupAggSize); // printf(" nEvent : %d \n", nEvent); // printf(" New Event Agg Size : %d \n", 2 + sampleSize / Deci / 2 + isExtra); - // printf("%3d | %08X \n", 1, newHeader0); - // printf("%3d | %08X \n", 2, oldHeader1); - // printf("%3d | %08X \n", 3, oldHeader2); - // printf("%3d | %08X \n", 4, oldHeader3); - // printf("%3d | %3d | %08X \n", 5, 1, newAggHeader0); - // printf("%3d | %3d | %08X \n", 6, 2, word); + printf("%3d | %08X \n", 1, newHeader0); + printf("%3d | %08X \n", 2, oldHeader1); + printf("%3d | %08X \n", 3, oldHeader2); + printf("%3d | %08X \n", 4, oldHeader3); + printf("%3d | %3d | %08X \n", 5, 1, newAggHeader0); + printf("%3d | %3d | %08X \n", 6, 2, newAggHeader1); } if( groupWordCount > 2 ) { @@ -573,17 +577,25 @@ inline void Data::SaveData(){ if( 1 < chWordCount && chWordCount <= chAggSize - 2 ){ // trace sampleWordCount ++; uint16_t S0 = word & 0xFFFF; + uint16_t S1 = (word >> 16) & 0xFFFF; if( decimation == 1 ){ - // printf("%3d | %3d | %3d | %3d | %08X | %4X \n", bdAggWordCount, groupWordCount, chWordCount, sampleWordCount, word, S0); - fwrite(&S0, sizeof(S0), 1, outFile); - }else if( sampleWordCount % decimation == 1) { - // printf("%3d | %3d | %3d | %3d | %08X | %4X \n", bdAggWordCount, groupWordCount, chWordCount, sampleWordCount, word, S0); - fwrite(&S0, sizeof(S0), 1, outFile); + average = S0/2 + S1/2; + printf("%3d | %3d | %3d | %3d | %08X | %4X \n", bdAggWordCount, groupWordCount, chWordCount, sampleWordCount, word, average); + fwrite(&average, sizeof(average), 1, outFile); + }else{ + average += S0/Deci + S1/Deci; + printf("%3d | %3d | %3d | %3d | %08X | %4X \n", bdAggWordCount, groupWordCount, chWordCount, sampleWordCount, word, average); + if( sampleWordCount % (Deci/2) == 0) { + // fwrite(&S0, sizeof(S0), 1, outFile); + printf(" --> %4X \n", average); + fwrite(&average, sizeof(average), 1, outFile); + average = 0; + } } }else{ - // printf("%3d | %3d | %3d | %08X \n", bdAggWordCount, groupWordCount, chWordCount, word); + printf("%3d | %3d | %3d | %08X \n", bdAggWordCount, groupWordCount, chWordCount, word); fwrite(&word, sizeof(word), 1, outFile); } } @@ -1292,6 +1304,7 @@ inline int Data::DecodePSDDualChannelBlock(unsigned int ChannelMask, bool fastDe //*================================================= inline int Data::DecodeQDCGroupedChannelBlock(unsigned int ChannelMask, bool fastDecode, int verbose){ + if( verbose ) printf("########## %s \n", __func__); //nw = nw + 1; unsigned int word = ReadBuffer(nw, verbose); @@ -1304,7 +1317,7 @@ inline int Data::DecodeQDCGroupedChannelBlock(unsigned int ChannelMask, bool fas unsigned int nEvents = 0; nw = nw + 1; word = ReadBuffer(nw, verbose); unsigned short decimation = (word >> 12) & 0xF ; - unsigned int nSample = ( word & 0xFFFF ) * 8; + unsigned int nSample = ( word & 0xFFF ) * 8; unsigned int analogProbe = ( (word >> 22 ) & 0x3 ); bool hasWaveForm = ( (word >> 27 ) & 0x1 ); bool hasExtra = ( (word >> 28 ) & 0x1 ); diff --git a/DigiSettingsPanel.cpp b/DigiSettingsPanel.cpp index d345ab3..04d8dc8 100644 --- a/DigiSettingsPanel.cpp +++ b/DigiSettingsPanel.cpp @@ -2545,6 +2545,8 @@ void DigiSettingsPanel::SetUpBoard_QDC(){ SetUpSpinBox(sbRecordLength[ID][0], "Record Length [ns] : ", bdCfgLayout[ID], 6, 0, DPP::QDC::RecordLength_W, -1, true); SetUpSpinBox( sbSWDecimation[ID], "SW Decimation Factor : ", bdCfgLayout[ID], 7, 0, DPP::DecimationFactor, -1, true); + QLabel * lbDeci = new QLabel("This average trace.", this); + bdCfgLayout[ID]->addWidget(lbDeci, 7, 2, 1, 2); } -- 2.34.1 From c2e76c75aef52b7224e13322d70d62aa39f6e979 Mon Sep 17 00:00:00 2001 From: "Ryan@SOLARIS_testStation" Date: Wed, 16 Oct 2024 18:00:07 -0400 Subject: [PATCH 09/35] comment out printf --- Aux/test.cpp | 3 ++- ClassData.h | 26 +++++++++++++------------- 2 files changed, 15 insertions(+), 14 deletions(-) diff --git a/Aux/test.cpp b/Aux/test.cpp index 6a5c4f8..6864749 100644 --- a/Aux/test.cpp +++ b/Aux/test.cpp @@ -344,7 +344,8 @@ void SimpleDAQ(){ digi->ReadData(); data->DecodeBuffer(true, 0); - data->SaveData(2); + data->SetDecimationFactor(3); + data->SaveData(); data->PrintStat(); diff --git a/ClassData.h b/ClassData.h index 2f2c334..8344aa5 100644 --- a/ClassData.h +++ b/ClassData.h @@ -515,7 +515,7 @@ inline void Data::SaveData(){ if( bdAggWordCount == 1 ) { bdAggSize = word & 0x0FFFFFFF; - printf("###################### Bd Agg Size : %d\n", bdAggSize); + // printf("###################### Bd Agg Size : %d\n", bdAggSize); } // fwrite(buffer + i * chunkSize, sizeof(char), chunkSize, outFile); @@ -531,7 +531,7 @@ inline void Data::SaveData(){ if( groupWordCount == 1 ) { groupAggSize = word & 0x3FFFFFFF; - printf("============= Coupled Channel Agg Size : %d \n", groupAggSize); + // printf("============= Coupled Channel Agg Size : %d \n", groupAggSize); } if( groupWordCount == 2 ) { sampleSize = (word & 0xFFF) * 8; @@ -540,7 +540,7 @@ inline void Data::SaveData(){ uint32_t oldWord = word; uint32_t newSampleSize = sampleSize / Deci; word = (word & 0xFFFFF000) + (newSampleSize / 8 ); // change the number of sample - printf("============= Sample Size : %d | Ch Size : %d | old %08X new %08X\n", sampleSize, chAggSize, oldWord, word); + // printf("============= Sample Size : %d | Ch Size : %d | old %08X new %08X\n", sampleSize, chAggSize, oldWord, word); int nEvent = (groupAggSize - 2 ) / chAggSize; int newGroupAggSize = 2 + nEvent * ( 2 + newSampleSize / 2 + isExtra ); @@ -563,12 +563,12 @@ inline void Data::SaveData(){ // printf(" nEvent : %d \n", nEvent); // printf(" New Event Agg Size : %d \n", 2 + sampleSize / Deci / 2 + isExtra); - printf("%3d | %08X \n", 1, newHeader0); - printf("%3d | %08X \n", 2, oldHeader1); - printf("%3d | %08X \n", 3, oldHeader2); - printf("%3d | %08X \n", 4, oldHeader3); - printf("%3d | %3d | %08X \n", 5, 1, newAggHeader0); - printf("%3d | %3d | %08X \n", 6, 2, newAggHeader1); + // printf("%3d | %08X \n", 1, newHeader0); + // printf("%3d | %08X \n", 2, oldHeader1); + // printf("%3d | %08X \n", 3, oldHeader2); + // printf("%3d | %08X \n", 4, oldHeader3); + // printf("%3d | %3d | %08X \n", 5, 1, newAggHeader0); + // printf("%3d | %3d | %08X \n", 6, 2, newAggHeader1); } if( groupWordCount > 2 ) { @@ -581,21 +581,21 @@ inline void Data::SaveData(){ if( decimation == 1 ){ average = S0/2 + S1/2; - printf("%3d | %3d | %3d | %3d | %08X | %4X \n", bdAggWordCount, groupWordCount, chWordCount, sampleWordCount, word, average); + // printf("%3d | %3d | %3d | %3d | %08X | %4X \n", bdAggWordCount, groupWordCount, chWordCount, sampleWordCount, word, average); fwrite(&average, sizeof(average), 1, outFile); }else{ average += S0/Deci + S1/Deci; - printf("%3d | %3d | %3d | %3d | %08X | %4X \n", bdAggWordCount, groupWordCount, chWordCount, sampleWordCount, word, average); + // printf("%3d | %3d | %3d | %3d | %08X | %4X \n", bdAggWordCount, groupWordCount, chWordCount, sampleWordCount, word, average); if( sampleWordCount % (Deci/2) == 0) { // fwrite(&S0, sizeof(S0), 1, outFile); - printf(" --> %4X \n", average); + // printf(" --> %4X \n", average); fwrite(&average, sizeof(average), 1, outFile); average = 0; } } }else{ - printf("%3d | %3d | %3d | %08X \n", bdAggWordCount, groupWordCount, chWordCount, word); + // printf("%3d | %3d | %3d | %08X \n", bdAggWordCount, groupWordCount, chWordCount, word); fwrite(&word, sizeof(word), 1, outFile); } } -- 2.34.1 From 3f007cebbdeedec1778a75e75818e3fee3aa97fa Mon Sep 17 00:00:00 2001 From: "Ryan@SOLARIS_testStation" Date: Wed, 16 Oct 2024 18:18:50 -0400 Subject: [PATCH 10/35] comment out more --- ClassData.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ClassData.h b/ClassData.h index 8344aa5..2f2752f 100644 --- a/ClassData.h +++ b/ClassData.h @@ -537,9 +537,9 @@ inline void Data::SaveData(){ sampleSize = (word & 0xFFF) * 8; bool isExtra = ( (word >> 28 ) & 0x1 ); chAggSize = 2 + sampleSize / 2 + isExtra; - uint32_t oldWord = word; uint32_t newSampleSize = sampleSize / Deci; - word = (word & 0xFFFFF000) + (newSampleSize / 8 ); // change the number of sample + // uint32_t oldWord = word; + // word = (word & 0xFFFFF000) + (newSampleSize / 8 ); // change the number of sample // printf("============= Sample Size : %d | Ch Size : %d | old %08X new %08X\n", sampleSize, chAggSize, oldWord, word); int nEvent = (groupAggSize - 2 ) / chAggSize; @@ -554,7 +554,7 @@ inline void Data::SaveData(){ fwrite(&oldHeader3, sizeof(uint32_t), 1, outFile); uint32_t newAggHeader0 = (0x8 << 28) + newGroupAggSize ; // add decimation factor in the word - uint32_t newAggHeader1 = word + (decimation << 12); // add decimation factor in the word + uint32_t newAggHeader1 = (word & 0xFFFFF000) + (newSampleSize / 8 ) + (decimation << 12); // add decimation factor in the word fwrite(&newAggHeader0, sizeof(uint32_t), 1, outFile); fwrite(&newAggHeader1, sizeof(uint32_t), 1, outFile); -- 2.34.1 From 921580a6c63712a65f0da212b970283e00b23993 Mon Sep 17 00:00:00 2001 From: "Ryan@SOLARIS_testStation" Date: Wed, 16 Oct 2024 18:32:20 -0400 Subject: [PATCH 11/35] small bug fix for Filling Historgam when trigge rate > 10k --- SingleSpectra.cpp | 8 +++++--- SingleSpectra.h | 1 + 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/SingleSpectra.cpp b/SingleSpectra.cpp index cc8cdc0..013cd43 100644 --- a/SingleSpectra.cpp +++ b/SingleSpectra.cpp @@ -275,6 +275,7 @@ void SingleSpectra::FillHistograms(){ std::vector digiChList; // (digi*1000 + ch) std::vector digiChLastIndex; // lastIndex std::vector digiChLoopIndex; // loopIndex + std::vector digiChAvalibleData; std::vector digiChFilled; for( int ID = 0; ID < nDigi; ID++){ @@ -289,6 +290,7 @@ void SingleSpectra::FillHistograms(){ digiChList.push_back( ID*1000 + ch ) ; digiChLastIndex.push_back(lastIndex); digiChLoopIndex.push_back(loopIndex); + digiChAvalibleData.push_back(temp1-temp2); digiChFilled.push_back(false); } } @@ -332,7 +334,7 @@ void SingleSpectra::FillHistograms(){ if( temp1 - temp2 > digi[ID]->GetData()->GetDataSize() ) { //DefaultDataSize = 10k temp2 = temp1 - digi[ID]->GetData()->GetDataSize(); lastFilledIndex[ID][ch] = lastIndex; - lastFilledIndex[ID][ch] = loopIndex - 1; + loopFilledIndex[ID][ch] = loopIndex - 1; } lastFilledIndex[ID][ch] ++; @@ -351,7 +353,7 @@ void SingleSpectra::FillHistograms(){ hist2D[ID]->Fill(ch, data); clock_gettime(CLOCK_REALTIME, &tb); - }while( (tb.tv_nsec - ta.tv_nsec)/1e6 + (tb.tv_sec - ta.tv_sec)*1e3 < maxFillTimeinMilliSec ); + }while( isFillingHistograms || (tb.tv_nsec - ta.tv_nsec)/1e6 + (tb.tv_sec - ta.tv_sec)*1e3 < maxFillTimeinMilliSec ); //*--------------- generate fillign report for( size_t i = 0; i < digiChFilled.size() ; i++){ @@ -366,7 +368,7 @@ void SingleSpectra::FillHistograms(){ int temp1 = lastIndex + loopIndex * digi[ID]->GetData()->GetDataSize(); int temp2 = lastFilledIndex[ID][ch] + loopFilledIndex[ID][ch] * digi[ID]->GetData()->GetDataSize() + 1; - printf("Digi-%2d ch-%2d | event unfilled %d\n", ID, ch, temp1 - temp2 ); + printf("Digi-%2d ch-%2d | event unfilled %d / %d\n", ID, ch, temp1 - temp2, digiChAvalibleData[i] ); } clock_gettime(CLOCK_REALTIME, &tb); diff --git a/SingleSpectra.h b/SingleSpectra.h index 6b5b498..6fb0aeb 100644 --- a/SingleSpectra.h +++ b/SingleSpectra.h @@ -55,6 +55,7 @@ public slots: void stopTimer(){ // printf("timer stop\n"); timer->stop(); + isFillingHistograms = false; // this will also break the FillHistogram do-loop ClearInternalDataCount(); } -- 2.34.1 From 2e9a64ccfde3ecc0b5ebd5cf025cadf791edc51a Mon Sep 17 00:00:00 2001 From: "Ryan@SOLARIS_testStation" Date: Wed, 16 Oct 2024 19:11:15 -0400 Subject: [PATCH 12/35] Histogram2D, nan value is transperant --- Histogram2D.h | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/Histogram2D.h b/Histogram2D.h index c080c60..fb9ae49 100644 --- a/Histogram2D.h +++ b/Histogram2D.h @@ -32,7 +32,7 @@ public: void SetChannelMap(bool onOff, int tickStep = 1) { isChannelMap = onOff; this->tickStep = tickStep;} - void UpdatePlot(){ colorMap->rescaleDataRange(); replot(); } + void UpdatePlot(){ colorMap->rescaleDataRange(true); replot(); } void Clear(); // Clear Data and histrogram void Fill(double x, double y); @@ -135,7 +135,7 @@ inline Histogram2D::Histogram2D(QString title, QString xLabel, QString yLabel, i QCPColorGradient color; color.setNanHandling(QCPColorGradient::NanHandling::nhNanColor); - color.setNanColor(QColor("white")); + color.setNanColor(QColor(0,0,0,0)); color.clearColorStops(); // color.setColorStopAt( 0.0, QColor("white" )); color.setColorStopAt( 0.0, QColor("purple" )); @@ -268,8 +268,6 @@ inline Histogram2D::Histogram2D(QString title, QString xLabel, QString yLabel, i }); } - - inline void Histogram2D::Fill(double x, double y){ // DebugPrint("%s", "Histogram2D"); if( isBusy ) return; -- 2.34.1 From d67dc8d3edc4dcad1e02f975ce6b9586ec1b82a2 Mon Sep 17 00:00:00 2001 From: "Ryan@SOLARIS_testStation" Date: Fri, 18 Oct 2024 16:30:21 -0400 Subject: [PATCH 13/35] add elog port number --- FSUDAQ.cpp | 38 +++++++++++++++++++++++--------------- FSUDAQ.h | 1 + 2 files changed, 24 insertions(+), 15 deletions(-) diff --git a/FSUDAQ.cpp b/FSUDAQ.cpp index be66139..8d4eb66 100644 --- a/FSUDAQ.cpp +++ b/FSUDAQ.cpp @@ -446,9 +446,10 @@ void FSUDAQ::LoadProgramSettings(){ if( count == 2 ) dataBaseName = line; if( count == 3 ) influxToken = line; if( count == 4 ) elogIP = line; - if( count == 5 ) elogName = line; - if( count == 6 ) elogUser = line; - if( count == 7 ) elogPWD = line; + if( count == 5 ) elogPort = line; + if( count == 6 ) elogName = line; + if( count == 7 ) elogUser = line; + if( count == 8 ) elogPWD = line; count ++; line = in.readLine(); @@ -467,6 +468,7 @@ void FSUDAQ::LoadProgramSettings(){ LogMsg(" Database Name : " + dataBaseName); LogMsg("Database Token : " + maskText(influxToken)); LogMsg(" Elog IP : " + elogIP); + LogMsg(" Elog Port : " + elogPort); LogMsg(" Elog Name : " + elogName); LogMsg(" Elog User : " + maskText(elogUser)); LogMsg(" Elog PWD : " + maskText(elogPWD)); @@ -501,6 +503,7 @@ void FSUDAQ::SaveProgramSettings(){ file.write((dataBaseName+"\n").toStdString().c_str()); file.write((influxToken+"\n").toStdString().c_str()); file.write((elogIP+"\n").toStdString().c_str()); + file.write((elogPort+"\n").toStdString().c_str()); file.write((elogName+"\n").toStdString().c_str()); file.write((elogUser+"\n").toStdString().c_str()); file.write((elogPWD+"\n").toStdString().c_str()); @@ -1561,13 +1564,16 @@ void FSUDAQ::SetAndLockInfluxElog(){ QVBoxLayout layout(&dialog); QFormLayout formLayout; + QLineEdit portLineEdit; QLineEdit usernameLineEdit; QLineEdit passwordLineEdit; //passwordLineEdit.setEchoMode(QLineEdit::Password); + formLayout.addRow("Port:", &portLineEdit); formLayout.addRow("Username:", &usernameLineEdit); formLayout.addRow("Password:", &passwordLineEdit); + portLineEdit.setText(elogPort); usernameLineEdit.setText(elogUser); passwordLineEdit.setText(elogPWD); @@ -1584,17 +1590,19 @@ void FSUDAQ::SetAndLockInfluxElog(){ // Show the dialog and get the result if (dialog.exec() == QDialog::Accepted) { - QString username = usernameLineEdit.text(); - QString password = passwordLineEdit.text(); + QString portNum = portLineEdit.text(); + QString username = usernameLineEdit.text(); + QString password = passwordLineEdit.text(); - // Check if username and password are not empty - if (!username.isEmpty() && !password.isEmpty()) { - elogUser = username; - elogPWD = password; + // Check if username and password are not empty + if (!portNum.isEmpty() && !username.isEmpty() && !password.isEmpty()) { + elogPort = portNum; + elogUser = username; + elogPWD = password; - } else { - qDebug() << "Please enter both username and password."; - } + } else { + qDebug() << "Please enter both port, username, and password."; + } } } @@ -2044,7 +2052,7 @@ void FSUDAQ::WriteElog(QString htmlText, QString subject, QString category, int if( elogUser == "" ) return; if( elogPWD == "" ) return; QStringList arg; - arg << "-h" << elogIP << "-p" << "8080" << "-l" << elogName << "-u" << elogUser << elogPWD << "-a" << "Author=FSUDAQ"; + arg << "-h" << elogIP << "-p" << elogPort << "-l" << elogName << "-u" << elogUser << elogPWD << "-a" << "Author=FSUDAQ"; if( runNumber > 0 ) arg << "-a" << "RunNo=" + QString::number(runNumber); if( category != "" ) arg << "-a" << "Category=" + category; arg << "-a" << "Subject=" + subject @@ -2074,7 +2082,7 @@ void FSUDAQ::AppendElog(QString appendHtmlText){ QProcess elogBash(this); QStringList arg; - arg << "-h" << elogIP << "-p" << "8080" << "-l" << elogName << "-u" << elogUser << elogPWD << "-w" << QString::number(elogID); + arg << "-h" << elogIP << "-p" << elogPort << "-l" << elogName << "-u" << elogUser << elogPWD << "-w" << QString::number(elogID); //retrevie the elog elogBash.start("elog", arg); elogBash.waitForFinished(); @@ -2085,7 +2093,7 @@ void FSUDAQ::AppendElog(QString appendHtmlText){ if( index != -1){ QString originalHtml = output.mid(index + separator.length()); arg.clear(); - arg << "-h" << elogIP << "-p" << "8080" << "-l" << elogName << "-u" << elogUser << elogPWD << "-e" << QString::number(elogID) + arg << "-h" << elogIP << "-p" << elogPort << "-l" << elogName << "-u" << elogUser << elogPWD << "-e" << QString::number(elogID) << "-n" << "2" << originalHtml + "
" + appendHtmlText; elogBash.start("elog", arg); diff --git a/FSUDAQ.h b/FSUDAQ.h index 07f22d7..6a87eea 100644 --- a/FSUDAQ.h +++ b/FSUDAQ.h @@ -144,6 +144,7 @@ private: //@----- Elog QString elogIP; + QString elogPort; QString elogName; QString elogUser; QString elogPWD; -- 2.34.1 From 9367670a535dbb0d2d24f90f97dbce0083de0500 Mon Sep 17 00:00:00 2001 From: "Ryan@SOLARIS_testStation" Date: Fri, 18 Oct 2024 17:54:43 -0400 Subject: [PATCH 14/35] bug fix of Scope, only-1-channel for QDC --- Scope.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/Scope.cpp b/Scope.cpp index 372e719..65cde71 100644 --- a/Scope.cpp +++ b/Scope.cpp @@ -372,6 +372,8 @@ void Scope::StartScope(){ digi[ID]->SetBits(DPP::PHA::DPPAlgorithmControl2_G, DPP::PHA::Bit_DPPAlgorithmControl2::LocalShapeTriggerMode, 0, ch); digi[ID]->SetBits(DPP::PHA::DPPAlgorithmControl2_G, DPP::PHA::Bit_DPPAlgorithmControl2::LocalTrigValidMode, 0, ch); + + digi[ID]->WriteRegister(DPP::RegChannelEnableMask, (1 << ch)); } @@ -384,14 +386,17 @@ void Scope::StartScope(){ digi[ID]->SetBits(DPP::PSD::DPPAlgorithmControl2_G, DPP::PSD::Bit_DPPAlgorithmControl2::LocalShapeTriggerMode, 0, ch); digi[ID]->SetBits(DPP::PSD::DPPAlgorithmControl2_G, DPP::PSD::Bit_DPPAlgorithmControl2::LocalTrigValidMode, 0, ch); + + digi[ID]->WriteRegister(DPP::RegChannelEnableMask, (1 << ch)); } if( digi[ID]->GetDPPType() == DPPTypeCode::DPP_QDC_CODE ){ dppAlg = digi[ID]->GetSettingFromMemory(DPP::QDC::DPPAlgorithmControl, ch); digi[ID]->SetBits(DPP::QDC::DPPAlgorithmControl, DPP::QDC::Bit_DPPAlgorithmControl::TriggerMode, 0, ch); //set self-triiger + + digi[ID]->WriteRegister(DPP::RegChannelEnableMask, (1 << ch/8)); } - digi[ID]->WriteRegister(DPP::RegChannelEnableMask, (1 << ch)); //=========== start digi[ID]->WriteRegister(DPP::SoftwareClear_W, 1); -- 2.34.1 From ae567c071431d932ac272d6bb48f4fe0a3736485 Mon Sep 17 00:00:00 2001 From: "Ryan@SOLARIS_testStation" Date: Mon, 21 Oct 2024 15:11:33 -0400 Subject: [PATCH 15/35] improve scope for QDC and PSD, add subChannelMask in Scope --- ClassDigitizer.cpp | 4 ++-- CustomWidgets.h | 4 ++-- README.md | 1 + Scope.cpp | 57 +++++++++++++++++++++++++++++++++------------- Scope.h | 1 + 5 files changed, 47 insertions(+), 20 deletions(-) diff --git a/ClassDigitizer.cpp b/ClassDigitizer.cpp index a2094b0..0095098 100644 --- a/ClassDigitizer.cpp +++ b/ClassDigitizer.cpp @@ -441,7 +441,7 @@ int Digitizer::ProgramBoard_PSD(){ ret |= CAEN_DGTZ_WriteRegister(handle, (uint32_t)(DPP::PSD::DPPAlgorithmControl2_G) + 0x7000 , 0x00000200 ); // use fine time - ret |= CAEN_DGTZ_WriteRegister(handle, (uint32_t)(DPP::DPPAlgorithmControl) + 0x7000 , 0x00100000 ); // baseline 16 sample + ret |= CAEN_DGTZ_WriteRegister(handle, (uint32_t)(DPP::DPPAlgorithmControl) + 0x7000 , 0x00100002 ); // baseline 16 sample, 80fC ret |= CAEN_DGTZ_WriteRegister(handle, (uint32_t)(DPP::PSD::TriggerThreshold) + 0x7000 , 100 ); @@ -1373,7 +1373,7 @@ void Digitizer::SetOptimialAggOrg(){ printf("=================================== Setting related to Buffer\n"); printf(" agg. orgainzation (bit) : 0x%X \n", aggOrgan); - printf(" Channel Mask : %04X \n", chMask); + printf(" Channel Mask : %08X \n", chMask); printf("Max number of Agg per Readout : %u \n", AggRead); printf(" is Extra enabed : %u \n", Ex ); printf(" is Record wave : %u \n", traceOn ); diff --git a/CustomWidgets.h b/CustomWidgets.h index 6d0ccda..ff13ba5 100644 --- a/CustomWidgets.h +++ b/CustomWidgets.h @@ -130,7 +130,7 @@ protected: QAction *selectedAction = menu->exec(event->globalPosition().toPoint()); if( selectedAction == a1 ) { chart()->zoomReset(); - chart()->axes(Qt::Vertical).first()->setRange(-(0x3FFF), 0x3FFF); + // chart()->axes(Qt::Vertical).first()->setRange(-(0x3FFF), 0x3FFF); } } @@ -169,7 +169,7 @@ protected: case Qt::Key_Down: chart()->scroll(0, -10); break; case Qt::Key_R : chart()->zoomReset(); - chart()->axes(Qt::Vertical).first()->setRange(-(0x3FFF), 0x3FFF); + // chart()->axes(Qt::Vertical).first()->setRange(-(0x3FFF), 0x3FFF); break; default: QGraphicsView::keyPressEvent(event); break; } diff --git a/README.md b/README.md index aa95aaa..1aa1703 100644 --- a/README.md +++ b/README.md @@ -188,6 +188,7 @@ second, ensure the core dump file has unlimited size and set the core dump file * Sometimes, the buffer is not in time order, and make the trigger/Accept rate to be nagative. This is nothing to do with the program but the digitizer settings. Recommand reporgram the digitizer. * For 1740 QDC, RecordLenght is board setting, but readout is indivuial group. * For PHA, the trapezoid scaling and fine-gain register are calculated before ACQ start. +* For 1740D QDC, when 1st grouped channel is enabled, the 0th-channel must be enabled, otherwise, there is a ReadData error and the ACQ will stop. # Known Bugs diff --git a/Scope.cpp b/Scope.cpp index 65cde71..9a7d4a3 100644 --- a/Scope.cpp +++ b/Scope.cpp @@ -147,12 +147,39 @@ Scope::Scope(Digitizer ** digi, unsigned int nDigi, ReadDataThread ** readDataTh if( digi[ID]->GetDPPType() == V1730_DPP_PSD_CODE ) SetUpPanel_PSD(); if( digi[ID]->GetDPPType() == V1740_DPP_QDC_CODE ) SetUpPanel_QDC(); + if( digi[ID]->GetDPPType() == V1730_DPP_PHA_CODE ) { + QValueAxis * yaxis = qobject_cast (plot->axes(Qt::Vertical).first()); + yaxis->setRange(-(0x1FFF), 0x1FFF); + } + if( digi[ID]->GetDPPType() == V1730_DPP_PSD_CODE ) { + QValueAxis * yaxis = qobject_cast (plot->axes(Qt::Vertical).first()); + yaxis->setRange(0, 0x3FFF); + } + if( digi[ID]->GetDPPType() == V1740_DPP_QDC_CODE ) { + QValueAxis * yaxis = qobject_cast (plot->axes(Qt::Vertical).first()); + yaxis->setRange(0, 0xFFF); + } + ReadSettingsFromBoard(); if( saveACQStartStatus )StartScope(); }); + if( digi[ID]->GetDPPType() == V1730_DPP_PHA_CODE ) { + QValueAxis * yaxis = qobject_cast (plot->axes(Qt::Vertical).first()); + yaxis->setRange(-(0x1FFF), 0x1FFF); + } + if( digi[ID]->GetDPPType() == V1730_DPP_PSD_CODE ) { + QValueAxis * yaxis = qobject_cast (plot->axes(Qt::Vertical).first()); + yaxis->setRange(0, 0x3FFF); + } + if( digi[ID]->GetDPPType() == V1740_DPP_QDC_CODE ) { + QValueAxis * yaxis = qobject_cast (plot->axes(Qt::Vertical).first()); + yaxis->setRange(0, 0xFFF); + } + + connect(cbScopeCh, &RComboBox::currentIndexChanged, this, [=](){ if( !enableSignalSlot ) return; @@ -264,19 +291,6 @@ Scope::Scope(Digitizer ** digi, unsigned int nDigi, ReadDataThread ** readDataTh UpdatePanelFromMomeory(); - if( digi[ID]->GetDPPType() == V1730_DPP_PHA_CODE ) { - QValueAxis * yaxis = qobject_cast (plot->axes(Qt::Vertical).first()); - yaxis->setRange(-(0x1FFF), 0x1FFF); - } - if( digi[ID]->GetDPPType() == V1730_DPP_PSD_CODE ) { - QValueAxis * yaxis = qobject_cast (plot->axes(Qt::Vertical).first()); - yaxis->setRange(0, 0x3FFF); - } - if( digi[ID]->GetDPPType() == V1740_DPP_QDC_CODE ) { - QValueAxis * yaxis = qobject_cast (plot->axes(Qt::Vertical).first()); - yaxis->setRange(0, 0xFFF); - } - workerThread = new QThread(this); scopeWorker = new ScopeWorker(this); scopeTimer = new QTimer(this); @@ -361,9 +375,9 @@ void Scope::StartScope(){ //save present settings, channleMap, trigger condition traceOn[ID] = digi[ID]->IsRecordTrace(); digi[ID]->SetBits(DPP::BoardConfiguration, DPP::Bit_BoardConfig::RecordTrace, 1, -1); - chMask = digi[ID]->GetSettingFromMemory(DPP::RegChannelEnableMask); if( digi[ID]->GetDPPType() == DPPTypeCode::DPP_PHA_CODE ){ + chMask = digi[ID]->GetSettingFromMemory(DPP::RegChannelEnableMask); dppAlg = digi[ID]->GetSettingFromMemory(DPP::DPPAlgorithmControl, ch); dppAlg2 = digi[ID]->GetSettingFromMemory(DPP::PHA::DPPAlgorithmControl2_G, ch); @@ -378,6 +392,7 @@ void Scope::StartScope(){ } if( digi[ID]->GetDPPType() == DPPTypeCode::DPP_PSD_CODE ){ + chMask = digi[ID]->GetSettingFromMemory(DPP::RegChannelEnableMask); dppAlg = digi[ID]->GetSettingFromMemory(DPP::DPPAlgorithmControl, ch); dppAlg2 = digi[ID]->GetSettingFromMemory(DPP::PSD::DPPAlgorithmControl2_G, ch); @@ -391,10 +406,17 @@ void Scope::StartScope(){ } if( digi[ID]->GetDPPType() == DPPTypeCode::DPP_QDC_CODE ){ + chMask = digi[ID]->GetSettingFromMemory(DPP::QDC::GroupEnableMask); + subChMask = digi[ID]->GetSettingFromMemory(DPP::QDC::SubChannelMask); dppAlg = digi[ID]->GetSettingFromMemory(DPP::QDC::DPPAlgorithmControl, ch); digi[ID]->SetBits(DPP::QDC::DPPAlgorithmControl, DPP::QDC::Bit_DPPAlgorithmControl::TriggerMode, 0, ch); //set self-triiger - digi[ID]->WriteRegister(DPP::RegChannelEnableMask, (1 << ch/8)); + digi[ID]->WriteRegister(DPP::QDC::GroupEnableMask, (1 << (ch/8))); + + uint32_t haha = (1 << (ch%8)); + if( ch/8 == 0 ) haha |= 0x1; //must include the first subchannel + + digi[ID]->WriteRegister(DPP::QDC::SubChannelMask, haha); } @@ -479,20 +501,23 @@ void Scope::StopScope(){ //restore setting digi[ID]->SetBits(DPP::BoardConfiguration, DPP::Bit_BoardConfig::RecordTrace, traceOn[ID], -1); - digi[ID]->WriteRegister(DPP::RegChannelEnableMask, chMask); if( digi[ID]->GetDPPType() == DPPTypeCode::DPP_PHA_CODE ){ digi[ID]->WriteRegister(DPP::DPPAlgorithmControl, dppAlg, oldCh); digi[ID]->WriteRegister(DPP::PHA::DPPAlgorithmControl2_G, dppAlg2, oldCh); + digi[ID]->WriteRegister(DPP::RegChannelEnableMask, chMask); } if( digi[ID]->GetDPPType() == DPPTypeCode::DPP_PSD_CODE ){ digi[ID]->WriteRegister(DPP::DPPAlgorithmControl, dppAlg, oldCh); digi[ID]->WriteRegister(DPP::PSD::DPPAlgorithmControl2_G, dppAlg2, oldCh); + digi[ID]->WriteRegister(DPP::RegChannelEnableMask, chMask); } if( digi[ID]->GetDPPType() == DPPTypeCode::DPP_QDC_CODE ){ digi[ID]->WriteRegister(DPP::QDC::DPPAlgorithmControl, dppAlg, oldCh); + digi[ID]->WriteRegister(DPP::QDC::GroupEnableMask, chMask); + digi[ID]->WriteRegister(DPP::QDC::SubChannelMask, subChMask); } }else{ diff --git a/Scope.h b/Scope.h index be68607..5498a30 100644 --- a/Scope.h +++ b/Scope.h @@ -86,6 +86,7 @@ private: bool traceOn[MaxNDigitizer]; uint32_t dppAlg, dppAlg2, chMask; //for single channel run + uint32_t subChMask; // for QDC unsigned short oldCh, oldDigi; ReadDataThread ** readDataThread; -- 2.34.1 From 4e111085c030babe350a4b2367956c9f803a2922 Mon Sep 17 00:00:00 2001 From: "Ryan@SOLARIS_testStation" Date: Mon, 21 Oct 2024 19:09:44 -0400 Subject: [PATCH 16/35] in ClassDigitizer, get data can use totalIndex, which will % dataSize. simplify HistFilling. Qthread will block mainGUI ? --- ClassData.h | 13 +++++------ ClassDigitizer.cpp | 2 +- SingleSpectra.cpp | 56 +++++++++++++++++++--------------------------- SingleSpectra.h | 4 +--- macro.h | 4 ++++ 5 files changed, 34 insertions(+), 45 deletions(-) diff --git a/ClassData.h b/ClassData.h index 2f2752f..db23353 100644 --- a/ClassData.h +++ b/ClassData.h @@ -16,9 +16,6 @@ #include "macro.h" -//#define MaxNData 10000 /// store 10k events per channels -#define DefaultDataSize 10000 - enum DPPTypeCode{ DPP_PHA_CODE = 0x8B, DPP_PSD_CODE = 0x88, @@ -58,11 +55,11 @@ class Data{ uShort GetDataSize() const {return dataSize;} - ullong GetTimestamp(unsigned short ch, unsigned int index) const {return Timestamp[ch][index];} - uShort GetFineTime(unsigned short ch, unsigned int index) const {return fineTime[ch][index];} - uShort GetEnergy(unsigned short ch, unsigned int index) const {return Energy[ch][index];} - uShort GetEnergy2(unsigned short ch, unsigned int index) const {return Energy2[ch][index];} - bool GetPileUp(unsigned short ch, unsigned int index) const {return PileUp[ch][index];} + ullong GetTimestamp(unsigned short ch, unsigned int index) const {return Timestamp[ch][index % dataSize];} + uShort GetFineTime(unsigned short ch, unsigned int index) const {return fineTime[ch][index % dataSize];} + uShort GetEnergy(unsigned short ch, unsigned int index) const {return Energy[ch][index % dataSize];} + uShort GetEnergy2(unsigned short ch, unsigned int index) const {return Energy2[ch][index % dataSize];} + bool GetPileUp(unsigned short ch, unsigned int index) const {return PileUp[ch][index % dataSize];} uInt GetWordIndex() const {return nw;} diff --git a/ClassDigitizer.cpp b/ClassDigitizer.cpp index 0095098..23c31f4 100644 --- a/ClassDigitizer.cpp +++ b/ClassDigitizer.cpp @@ -441,7 +441,7 @@ int Digitizer::ProgramBoard_PSD(){ ret |= CAEN_DGTZ_WriteRegister(handle, (uint32_t)(DPP::PSD::DPPAlgorithmControl2_G) + 0x7000 , 0x00000200 ); // use fine time - ret |= CAEN_DGTZ_WriteRegister(handle, (uint32_t)(DPP::DPPAlgorithmControl) + 0x7000 , 0x00100002 ); // baseline 16 sample, 80fC + ret |= CAEN_DGTZ_WriteRegister(handle, (uint32_t)(DPP::DPPAlgorithmControl) + 0x7000 , 0x00100003 ); // baseline 16 sample, 320fC ret |= CAEN_DGTZ_WriteRegister(handle, (uint32_t)(DPP::PSD::TriggerThreshold) + 0x7000 , 100 ); diff --git a/SingleSpectra.cpp b/SingleSpectra.cpp index 013cd43..25d08b7 100644 --- a/SingleSpectra.cpp +++ b/SingleSpectra.cpp @@ -13,8 +13,7 @@ SingleSpectra::SingleSpectra(Digitizer ** digi, unsigned int nDigi, QString rawD this->nDigi = nDigi; this->settingPath = rawDataPath + "/HistogramSettings.txt"; - maxFillTimeinMilliSec = 900; - maxFillTimePerDigi = maxFillTimeinMilliSec/nDigi; + maxFillTimeinMilliSec = SingleHistogramFillingTime; isSignalSlotActive = true; @@ -155,11 +154,11 @@ SingleSpectra::SingleSpectra(Digitizer ** digi, unsigned int nDigi, QString rawD histWorker->moveToThread(workerThread); + workerThread->start(); + // connect(timer, &QTimer::timeout, histWorker, &HistWorker::FillHistograms); connect( histWorker, &HistWorker::workDone, this, &SingleSpectra::ReplotHistograms); - // workerThread->start(); - connect(timer, &QTimer::timeout, this, [=](){ if( isFillingHistograms == false){ histWorker->FillHistograms(); @@ -194,7 +193,6 @@ void SingleSpectra::ClearInternalDataCount(){ for( unsigned int i = 0; i < nDigi; i++){ for( int ch = 0; ch < MaxRegChannel ; ch++) { lastFilledIndex[i][ch] = -1; - loopFilledIndex[i][ch] = 0; } } } @@ -273,10 +271,11 @@ void SingleSpectra::FillHistograms(){ clock_gettime(CLOCK_REALTIME, &ta); std::vector digiChList; // (digi*1000 + ch) - std::vector digiChLastIndex; // lastIndex - std::vector digiChLoopIndex; // loopIndex + std::vector digiChLastIndex; // loop * dataSize + index; std::vector digiChAvalibleData; std::vector digiChFilled; + std::vector digiChFilledCount; + for( int ID = 0; ID < nDigi; ID++){ for( int ch = 0; ch < digi[ID]->GetNumInputCh(); ch++){ @@ -284,19 +283,22 @@ void SingleSpectra::FillHistograms(){ int loopIndex = digi[ID]->GetData()->GetLoopIndex(ch); int temp1 = lastIndex + loopIndex * digi[ID]->GetData()->GetDataSize(); - int temp2 = lastFilledIndex[ID][ch] + loopFilledIndex[ID][ch] * digi[ID]->GetData()->GetDataSize() + 1; + int temp2 = lastFilledIndex[ID][ch]; if( temp1 <= temp2 ) continue; digiChList.push_back( ID*1000 + ch ) ; - digiChLastIndex.push_back(lastIndex); - digiChLoopIndex.push_back(loopIndex); + digiChLastIndex.push_back(temp1); digiChAvalibleData.push_back(temp1-temp2); digiChFilled.push_back(false); + digiChFilledCount.push_back(0); } } int nSize = digiChList.size(); + clock_gettime(CLOCK_REALTIME, &tb); + printf("Checking time : %8.3f ms\n", (tb.tv_nsec - ta.tv_nsec)/1e6 + (tb.tv_sec - ta.tv_sec)*1e3 ); + // printf("------------ nSize : %d \n", nSize); if( nSize == 0 ) { @@ -320,28 +322,17 @@ void SingleSpectra::FillHistograms(){ int ch = digiCh % 1000; // printf(" -------------------- %d / %d | %d\n", randomValue, nSize-1, digiCh); - int lastIndex = digiChLastIndex[randomValue]; - int loopIndex = digiChLoopIndex[randomValue]; - - int temp1 = lastIndex + loopIndex * digi[ID]->GetData()->GetDataSize(); - int temp2 = lastFilledIndex[ID][ch] + loopFilledIndex[ID][ch] * digi[ID]->GetData()->GetDataSize() + 1; - - if( temp1 <= temp2 ) { + if( digiChLastIndex[randomValue] <= lastFilledIndex[ID][ch] ) { digiChFilled[randomValue] = true; // printf("Digi-%2d ch-%2d all filled | %zu\n", ID, ch, digiChList.size()); continue; } - if( temp1 - temp2 > digi[ID]->GetData()->GetDataSize() ) { //DefaultDataSize = 10k - temp2 = temp1 - digi[ID]->GetData()->GetDataSize(); - lastFilledIndex[ID][ch] = lastIndex; - loopFilledIndex[ID][ch] = loopIndex - 1; + if( digiChLastIndex[randomValue] - lastFilledIndex[ID][ch] > digi[ID]->GetData()->GetDataSize() ) { //DefaultDataSize = 10k + lastFilledIndex[ID][ch] = digiChLastIndex[randomValue] - digi[ID]->GetData()->GetDataSize() ; } lastFilledIndex[ID][ch] ++; - if( lastFilledIndex[ID][ch] > digi[ID]->GetData()->GetDataSize() ) { - lastFilledIndex[ID][ch] = 0; - loopFilledIndex[ID][ch] ++; - } + digiChFilledCount[randomValue]++; uShort data = digi[ID]->GetData()->GetEnergy(ch, lastFilledIndex[ID][ch]); @@ -352,8 +343,13 @@ void SingleSpectra::FillHistograms(){ } hist2D[ID]->Fill(ch, data); + usleep(10); + clock_gettime(CLOCK_REALTIME, &tb); - }while( isFillingHistograms || (tb.tv_nsec - ta.tv_nsec)/1e6 + (tb.tv_sec - ta.tv_sec)*1e3 < maxFillTimeinMilliSec ); + }while( isFillingHistograms && (tb.tv_nsec - ta.tv_nsec)/1e6 + (tb.tv_sec - ta.tv_sec)*1e3 < maxFillTimeinMilliSec ); + + clock_gettime(CLOCK_REALTIME, &tb); + printf("Filling time : %8.3f ms\n", (tb.tv_nsec - ta.tv_nsec)/1e6 + (tb.tv_sec - ta.tv_sec)*1e3 ); //*--------------- generate fillign report for( size_t i = 0; i < digiChFilled.size() ; i++){ @@ -362,13 +358,7 @@ void SingleSpectra::FillHistograms(){ int ch = digiCh % 1000; // printf(" -------------------- %d / %d | %d\n", randomValue, nSize-1, digiCh); - int lastIndex = digiChLastIndex[i]; - int loopIndex = digiChLoopIndex[i]; - - int temp1 = lastIndex + loopIndex * digi[ID]->GetData()->GetDataSize(); - int temp2 = lastFilledIndex[ID][ch] + loopFilledIndex[ID][ch] * digi[ID]->GetData()->GetDataSize() + 1; - - printf("Digi-%2d ch-%2d | event unfilled %d / %d\n", ID, ch, temp1 - temp2, digiChAvalibleData[i] ); + printf("Digi-%2d ch-%2d | event filled %d / %d\n", ID, ch, digiChFilledCount[i], digiChAvalibleData[i] ); } clock_gettime(CLOCK_REALTIME, &tb); diff --git a/SingleSpectra.h b/SingleSpectra.h index 6fb0aeb..56d9ef8 100644 --- a/SingleSpectra.h +++ b/SingleSpectra.h @@ -64,11 +64,9 @@ private: Digitizer ** digi; unsigned short nDigi; - int lastFilledIndex[MaxNDigitizer][MaxNChannels]; - int loopFilledIndex[MaxNDigitizer][MaxNChannels]; + long lastFilledIndex[MaxNDigitizer][MaxNChannels]; // index * dataSize + index bool histVisibility[MaxNDigitizer][MaxNChannels]; bool hist2DVisibility[MaxNDigitizer]; - unsigned short maxFillTimePerDigi; bool isFillingHistograms; Histogram1D * hist[MaxNDigitizer][MaxNChannels]; diff --git a/macro.h b/macro.h index d734ec6..3aea773 100644 --- a/macro.h +++ b/macro.h @@ -11,8 +11,12 @@ #define MaxRecordLength 0x3fff * 8 #define MaxSaveFileSize 1024 * 1024 * 1024 * 2 +#define DefaultDataSize 10000 /// store 10k events per channels + #define ScalarUpdateinMiliSec 1000 // msec +#define SingleHistogramFillingTime 900 // msec + #define MaxDisplayTraceTimeLength 20000 //ns #define ScopeUpdateMiliSec 200 // msec #define MaxNumberOfTrace 5 // in an event -- 2.34.1 From 804fa07c9cc31b767f26d888b17ad0c5f7337db6 Mon Sep 17 00:00:00 2001 From: "Ryan@SOLARIS_testStation" Date: Mon, 21 Oct 2024 19:11:44 -0400 Subject: [PATCH 17/35] add QCoreApplication::processEvent() to solve the GUI lagging --- SingleSpectra.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SingleSpectra.cpp b/SingleSpectra.cpp index 25d08b7..432561b 100644 --- a/SingleSpectra.cpp +++ b/SingleSpectra.cpp @@ -343,7 +343,7 @@ void SingleSpectra::FillHistograms(){ } hist2D[ID]->Fill(ch, data); - usleep(10); + QCoreApplication::processEvents(); clock_gettime(CLOCK_REALTIME, &tb); }while( isFillingHistograms && (tb.tv_nsec - ta.tv_nsec)/1e6 + (tb.tv_sec - ta.tv_sec)*1e3 < maxFillTimeinMilliSec ); -- 2.34.1 From 39f479534efeaddd442ef39ae46c4ad739541c26 Mon Sep 17 00:00:00 2001 From: "Ryan@SOLARIS_testStation" Date: Mon, 21 Oct 2024 19:25:30 -0400 Subject: [PATCH 18/35] simplify SingleSpectra.cpp --- SingleSpectra.cpp | 39 +++------------------------------------ 1 file changed, 3 insertions(+), 36 deletions(-) diff --git a/SingleSpectra.cpp b/SingleSpectra.cpp index 432561b..1707e9f 100644 --- a/SingleSpectra.cpp +++ b/SingleSpectra.cpp @@ -219,18 +219,6 @@ void SingleSpectra::ChangeHistView(){ hist2DVisibility[oldBd] = false; } - // if( oldCh >= 0 && oldCh < digi[oldBd]->GetNumInputCh()){ - // histLayout->removeWidget(hist[oldBd][oldCh]); - // hist[oldBd][oldCh]->setParent(nullptr); - // histVisibility[oldBd][oldCh] = false; - // } - - // if( oldCh == digi[oldBd]->GetNumInputCh() ){ - // histLayout->removeWidget(hist2D[oldBd]); - // hist2D[oldBd]->setParent(nullptr); - // hist2DVisibility[oldBd] = false; - // } - // Add ch if( ch >=0 && ch < digi[bd]->GetNumInputCh()) { histLayout->addWidget(hist[bd][ch], 0, 0); @@ -247,13 +235,6 @@ void SingleSpectra::ChangeHistView(){ oldBd = bd; oldChComboBoxindex[bd] = cbCh->currentIndex(); - // for( unsigned int i = 0; i < nDigi; i++ ){ - // if( hist2DVisibility[i] ) printf(" hist2D-%d is visible\n", i); - // for( int j = 0; j < digi[i]->GetNumInputCh(); j++){ - // if( histVisibility[i][j] ) printf(" hist-%d-%d is visible\n", i, j); - // } - // } - } void SingleSpectra::FillHistograms(){ @@ -296,11 +277,6 @@ void SingleSpectra::FillHistograms(){ int nSize = digiChList.size(); - clock_gettime(CLOCK_REALTIME, &tb); - printf("Checking time : %8.3f ms\n", (tb.tv_nsec - ta.tv_nsec)/1e6 + (tb.tv_sec - ta.tv_sec)*1e3 ); - - // printf("------------ nSize : %d \n", nSize); - if( nSize == 0 ) { isFillingHistograms = false; return; @@ -317,9 +293,8 @@ void SingleSpectra::FillHistograms(){ int randomValue = QRandomGenerator::global()->bounded(nSize); if( digiChFilled[randomValue] == true ) continue; - int digiCh = digiChList[randomValue]; - int ID = digiCh / 1000; - int ch = digiCh % 1000; + int ID = digiChList[randomValue] / 1000; + int ch = digiChList[randomValue] % 1000; // printf(" -------------------- %d / %d | %d\n", randomValue, nSize-1, digiCh); if( digiChLastIndex[randomValue] <= lastFilledIndex[ID][ch] ) { @@ -348,17 +323,9 @@ void SingleSpectra::FillHistograms(){ clock_gettime(CLOCK_REALTIME, &tb); }while( isFillingHistograms && (tb.tv_nsec - ta.tv_nsec)/1e6 + (tb.tv_sec - ta.tv_sec)*1e3 < maxFillTimeinMilliSec ); - clock_gettime(CLOCK_REALTIME, &tb); - printf("Filling time : %8.3f ms\n", (tb.tv_nsec - ta.tv_nsec)/1e6 + (tb.tv_sec - ta.tv_sec)*1e3 ); - //*--------------- generate fillign report for( size_t i = 0; i < digiChFilled.size() ; i++){ - int digiCh = digiChList[i]; - int ID = digiCh / 1000; - int ch = digiCh % 1000; - // printf(" -------------------- %d / %d | %d\n", randomValue, nSize-1, digiCh); - - printf("Digi-%2d ch-%2d | event filled %d / %d\n", ID, ch, digiChFilledCount[i], digiChAvalibleData[i] ); + printf("Digi-%2d ch-%2d | event filled %d / %d\n", digiChList[i] / 1000, digiChList[i] % 1000, digiChFilledCount[i], digiChAvalibleData[i] ); } clock_gettime(CLOCK_REALTIME, &tb); -- 2.34.1 From ae0e0f2c7b621a7ae773ab39cce90d2b80a1b314 Mon Sep 17 00:00:00 2001 From: "Ryan@SOLARIS_testStation" Date: Mon, 21 Oct 2024 19:47:02 -0400 Subject: [PATCH 19/35] add ClassData::GetAbsDataIndex() --- ClassData.h | 1 + SingleSpectra.cpp | 13 +++++-------- analyzers/NeutronGamma.h | 29 ++++++++--------------------- 3 files changed, 14 insertions(+), 29 deletions(-) diff --git a/ClassData.h b/ClassData.h index db23353..0e0afd5 100644 --- a/ClassData.h +++ b/ClassData.h @@ -52,6 +52,7 @@ class Data{ int GetLoopIndex(unsigned short ch) const {return LoopIndex[ch];} int GetDataIndex(unsigned short ch) const {return DataIndex[ch];} + long GetAbsDataIndex(unsigned short ch) const {return LoopIndex[ch] * dataSize + DataIndex[ch];} uShort GetDataSize() const {return dataSize;} diff --git a/SingleSpectra.cpp b/SingleSpectra.cpp index 1707e9f..962df10 100644 --- a/SingleSpectra.cpp +++ b/SingleSpectra.cpp @@ -252,7 +252,7 @@ void SingleSpectra::FillHistograms(){ clock_gettime(CLOCK_REALTIME, &ta); std::vector digiChList; // (digi*1000 + ch) - std::vector digiChLastIndex; // loop * dataSize + index; + std::vector digiChLastIndex; // loop * dataSize + index; std::vector digiChAvalibleData; std::vector digiChFilled; std::vector digiChFilledCount; @@ -260,10 +260,7 @@ void SingleSpectra::FillHistograms(){ for( int ID = 0; ID < nDigi; ID++){ for( int ch = 0; ch < digi[ID]->GetNumInputCh(); ch++){ - int lastIndex = digi[ID]->GetData()->GetDataIndex(ch); - int loopIndex = digi[ID]->GetData()->GetLoopIndex(ch); - - int temp1 = lastIndex + loopIndex * digi[ID]->GetData()->GetDataSize(); + int temp1 = digi[ID]->GetData()->GetAbsDataIndex(ch); int temp2 = lastFilledIndex[ID][ch]; if( temp1 <= temp2 ) continue; @@ -272,6 +269,9 @@ void SingleSpectra::FillHistograms(){ digiChAvalibleData.push_back(temp1-temp2); digiChFilled.push_back(false); digiChFilledCount.push_back(0); + + if( temp1 - temp2 > digi[ID]->GetData()->GetDataSize() ) lastFilledIndex[ID][ch] = temp1 - digi[ID]->GetData()->GetDataSize() ; + } } @@ -302,9 +302,6 @@ void SingleSpectra::FillHistograms(){ // printf("Digi-%2d ch-%2d all filled | %zu\n", ID, ch, digiChList.size()); continue; } - if( digiChLastIndex[randomValue] - lastFilledIndex[ID][ch] > digi[ID]->GetData()->GetDataSize() ) { //DefaultDataSize = 10k - lastFilledIndex[ID][ch] = digiChLastIndex[randomValue] - digi[ID]->GetData()->GetDataSize() ; - } lastFilledIndex[ID][ch] ++; digiChFilledCount[randomValue]++; diff --git a/analyzers/NeutronGamma.h b/analyzers/NeutronGamma.h index 94b10cf..65996b0 100644 --- a/analyzers/NeutronGamma.h +++ b/analyzers/NeutronGamma.h @@ -74,8 +74,7 @@ private: QGroupBox * histBox; QGridLayout * histLayout; - int lastFilledIndex[MaxNDigitizer][MaxNChannels]; - int loopFilledIndex[MaxNDigitizer][MaxNChannels]; + int lastFilledIndex[MaxNDigitizer][MaxNChannels];// absolute data index = loop * dataSize + index bool fillHistograms; @@ -178,7 +177,6 @@ inline void NeutronGamma::ClearInternalDataCount(){ for( unsigned int i = 0; i < nDigi; i++){ for( int ch = 0; ch < MaxRegChannel ; ch++) { lastFilledIndex[i][ch] = -1; - loopFilledIndex[i][ch] = 0; } } } @@ -190,36 +188,25 @@ inline void NeutronGamma::UpdateHistograms(){ int ID = cbDigi->currentData().toInt(); int ch = cbCh->currentData().toInt(); - int lastIndex = digi[ID]->GetData()->GetDataIndex(ch); - if( lastIndex < 0 ) return; + if( digi[ID]->GetData()->GetDataIndex(ch) < 0 ) return; - int loopIndex = digi[ID]->GetData()->GetLoopIndex(ch); + int dataAvalible = digi[ID]->GetData()->GetAbsDataIndex(ch) - lastFilledIndex[ID][ch]; - int temp1 = lastIndex + loopIndex * digi[ID]->GetData()->GetDataSize(); - int temp2 = lastFilledIndex[ID][ch] + loopFilledIndex[ID][ch] * digi[ID]->GetData()->GetDataSize() + 1; - - if( temp1 - temp2 > digi[ID]->GetData()->GetDataSize() ) { //DefaultDataSize = 10k - temp2 = temp1 - digi[ID]->GetData()->GetDataSize(); - lastFilledIndex[ID][ch] = lastIndex; - lastFilledIndex[ID][ch] = loopIndex - 1; + if( dataAvalible > digi[ID]->GetData()->GetDataSize() ) { //DefaultDataSize = 10k + lastFilledIndex[ID][ch] = digi[ID]->GetData()->GetAbsDataIndex(ch) - digi[ID]->GetData()->GetDataSize(); } - for( int j = 0 ; j <= temp1 - temp2; j ++){ + do{ lastFilledIndex[ID][ch] ++; - if( lastFilledIndex[ID][ch] > digi[ID]->GetData()->GetDataSize() ) { - lastFilledIndex[ID][ch] = 0; - loopFilledIndex[ID][ch] ++; - } uShort data_long = digi[ID]->GetData()->GetEnergy(ch, lastFilledIndex[ID][ch]); uShort data_short = digi[ID]->GetData()->GetEnergy2(ch, lastFilledIndex[ID][ch]); // printf(" ch: %d, last fill idx : %d | %d \n", ch, lastFilledIndex[ID][ch], data); - double psd = (data_long - data_short) *1.0 / data_long; - hist2D->Fill(data_long, psd); - } + + }while(lastFilledIndex[ID][ch] <= digi[ID]->GetData()->GetAbsDataIndex(ch)); hist2D->UpdatePlot(); -- 2.34.1 From 0d379fec9282433ca1d1db596fe06728e9d4c61c Mon Sep 17 00:00:00 2001 From: "Ryan@SOLARIS_testStation" Date: Mon, 21 Oct 2024 19:53:42 -0400 Subject: [PATCH 20/35] use AbsDataIndex in MultiBuilder --- MultiBuilder.cpp | 21 +++++++-------------- MultiBuilder.h | 6 +++--- 2 files changed, 10 insertions(+), 17 deletions(-) diff --git a/MultiBuilder.cpp b/MultiBuilder.cpp index 874db37..2f1ffef 100644 --- a/MultiBuilder.cpp +++ b/MultiBuilder.cpp @@ -58,7 +58,6 @@ void MultiBuilder::ClearEvents(){ for( int i = 0; i < MaxNDigitizer; i++){ for( int j = 0; j < MaxNChannels; j++){ - loopIndex[i][j] = 0; nextIndex[i][j] = -1; chExhaused[i][j] = false; lastBackWardIndex[i][j] = 0; @@ -79,7 +78,7 @@ void MultiBuilder::PrintStat(){ printf("Total number of evet built : %ld\n", totalEventBuilt); for( int i = 0; i < nData ; i++){ for( int ch = 0; ch < data[i]->GetNChannel() ; ch++){ - if( nextIndex[i][ch] >= 0 ) printf("%d %3d %2d | %7d (%d)\n", i, snList[i], ch, nextIndex[i][ch], loopIndex[i][ch]); + if( nextIndex[i][ch] >= 0 ) printf("%d %3d %2d | %7ld (%d)\n", i, snList[i], ch, nextIndex[i][ch]); } } } @@ -117,8 +116,7 @@ void MultiBuilder::FindEarlistTimeAndCh(bool verbose){ continue; } - if( data[i]->GetTimestamp(ch, index) == 0 || - loopIndex[i][ch] * dataSize[i] + nextIndex[i][ch] > data[i]->GetLoopIndex(ch) * dataSize[i] + data[i]->GetDataIndex(ch)) { + if( data[i]->GetTimestamp(ch, index) == 0 || nextIndex[i][ch] > data[i]->GetAbsDataIndex(ch)) { nExhaushedCh ++; chExhaused[i][ch] = true; continue; @@ -197,8 +195,7 @@ void MultiBuilder::BuildEvents(bool isFinal, bool skipTrace, bool verbose){ // printf(" ch : %2d | %d(%d) | %d(%d)\n", ch, loopIndex[bd][ch], nextIndex[bd][ch], data[bd]->GetLoopIndex(ch), data[bd]->GetDataIndex(ch) ); - if( nextIndex[bd][ch] == -1 - || loopIndex[bd][ch] * dataSize[bd] + nextIndex[bd][ch] > data[bd]->GetLoopIndex(ch) * dataSize[bd] + data[bd]->GetDataIndex(ch)) { + if( nextIndex[bd][ch] == -1 || nextIndex[bd][ch] > data[bd]->GetAbsDataIndex(ch)) { nExhaushedCh ++; chExhaused[bd][ch] = true; @@ -223,10 +220,7 @@ void MultiBuilder::BuildEvents(bool isFinal, bool skipTrace, bool verbose){ events[eventIndex].push_back(em); nextIndex[bd][ch]++; - if( nextIndex[bd][ch] >= dataSize[bd]) { - loopIndex[bd][ch] ++; - nextIndex[bd][ch] = 0; - } + }else{ break; } @@ -374,8 +368,7 @@ void MultiBuilder::BuildEventsBackWard(int maxNumEvent, bool verbose){ for( int k = 0; k < nData; k++){ for( int i = 0; i < data[k]->GetNChannel(); i++){ - nextIndex[k][i] = data[k]->GetDataIndex(i); - loopIndex[k][i] = data[k]->GetLoopIndex(i); + nextIndex[k][i] = data[k]->GetAbsDataIndex(i); } } @@ -418,7 +411,7 @@ void MultiBuilder::BuildEventsBackWard(int maxNumEvent, bool verbose){ events[eventIndex].push_back(em); nextIndex[bd][ch]--; - if( nextIndex[bd][ch] < 0 && data[bd]->GetLoopIndex(ch) > 0 ) nextIndex[bd][ch] = dataSize[bd] - 1; + // if( nextIndex[bd][ch] < 0 && data[bd]->GetLoopIndex(ch) > 0 ) nextIndex[bd][ch] = dataSize[bd] - 1; }else{ break; @@ -474,7 +467,7 @@ void MultiBuilder::BuildEventsBackWard(int maxNumEvent, bool verbose){ // 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); + lastBackWardIndex[k][i] = data[k]->GetAbsDataIndex(i); } } diff --git a/MultiBuilder.h b/MultiBuilder.h index 9fa8d13..bcade46 100644 --- a/MultiBuilder.h +++ b/MultiBuilder.h @@ -61,8 +61,8 @@ private: unsigned long long timeJump; //time diff for a time jump, default is 1e8 ns unsigned long long lastEventTime; // timestamp for detect time jump - int loopIndex[MaxNDigitizer][MaxNChannels]; - int nextIndex[MaxNDigitizer][MaxNChannels]; + // int loopIndex[MaxNDigitizer][MaxNChannels]; + long nextIndex[MaxNDigitizer][MaxNChannels]; // loopIndex * dataSize + index int nExhaushedCh; bool chExhaused[MaxNDigitizer][MaxNChannels]; @@ -79,7 +79,7 @@ private: void FindEarlistTimeAmongLastData(bool verbose = false); void FindLatestTimeOfData(bool verbose = false); - int lastBackWardIndex[MaxNDigitizer][MaxNChannels]; + int lastBackWardIndex[MaxNDigitizer][MaxNChannels]; // abs. index bool forceStop; -- 2.34.1 From b8011bc834f1fd4b37e6cf74b49de967a8681a8e Mon Sep 17 00:00:00 2001 From: "Ryan@SOLARIS_testStation" Date: Tue, 22 Oct 2024 12:56:26 -0400 Subject: [PATCH 21/35] [Major] True parallel thread for filling histogram --- FSUDAQ.cpp | 2 ++ MultiBuilder.cpp | 6 +++--- SingleSpectra.cpp | 23 ++++++++++++++--------- SingleSpectra.h | 10 ++++++++-- 4 files changed, 27 insertions(+), 14 deletions(-) diff --git a/FSUDAQ.cpp b/FSUDAQ.cpp index 8d4eb66..d88b8c9 100644 --- a/FSUDAQ.cpp +++ b/FSUDAQ.cpp @@ -1018,6 +1018,8 @@ void FSUDAQ::UpdateScalar(){ DebugPrint("%s", "FSUDAQ"); + // qDebug() << __func__ << "| thread:" << QThread::currentThreadId(); + // printf("================== FSUDAQ::%s\n", __func__); if( digi == nullptr ) return; diff --git a/MultiBuilder.cpp b/MultiBuilder.cpp index 2f1ffef..c71e70d 100644 --- a/MultiBuilder.cpp +++ b/MultiBuilder.cpp @@ -78,7 +78,7 @@ void MultiBuilder::PrintStat(){ printf("Total number of evet built : %ld\n", totalEventBuilt); for( int i = 0; i < nData ; i++){ for( int ch = 0; ch < data[i]->GetNChannel() ; ch++){ - if( nextIndex[i][ch] >= 0 ) printf("%d %3d %2d | %7ld (%d)\n", i, snList[i], ch, nextIndex[i][ch]); + if( nextIndex[i][ch] >= 0 ) printf("%d %3d %2d | %7ld\n", i, snList[i], ch, nextIndex[i][ch]); } } } @@ -277,7 +277,7 @@ void MultiBuilder::BuildEvents(bool isFinal, bool skipTrace, bool verbose){ break; } } - printf("%05d, %02d | %5d | %5d %llu \n", sn, chxxx, nextIndex[bd][chxxx], events[eventIndex][i].energy, events[eventIndex][i].timestamp); + printf("%05d, %02d | %7ld | %5d %llu \n", sn, chxxx, nextIndex[bd][chxxx], events[eventIndex][i].energy, events[eventIndex][i].timestamp); } if( nExhaushedCh == numTotCh ) { @@ -456,7 +456,7 @@ void MultiBuilder::BuildEventsBackWard(int maxNumEvent, bool verbose){ break; } } - printf("%5d, %02d | %5d | %5d %llu \n", sn, chxxx, nextIndex[bd][chxxx], events[eventIndex][i].energy, events[eventIndex][i].timestamp); + printf("%5d, %02d | %7ld | %5d %llu \n", sn, chxxx, nextIndex[bd][chxxx], events[eventIndex][i].energy, events[eventIndex][i].timestamp); } } diff --git a/SingleSpectra.cpp b/SingleSpectra.cpp index 962df10..6b1d366 100644 --- a/SingleSpectra.cpp +++ b/SingleSpectra.cpp @@ -153,18 +153,19 @@ SingleSpectra::SingleSpectra(Digitizer ** digi, unsigned int nDigi, QString rawD timer = new QTimer(this); histWorker->moveToThread(workerThread); + timer->moveToThread(workerThread); - workerThread->start(); - + isFillingHistograms = false; // connect(timer, &QTimer::timeout, histWorker, &HistWorker::FillHistograms); connect( histWorker, &HistWorker::workDone, this, &SingleSpectra::ReplotHistograms); - connect(timer, &QTimer::timeout, this, [=](){ - if( isFillingHistograms == false){ - histWorker->FillHistograms(); - // ReplotHistograms(); - } - }); + connect(timer, &QTimer::timeout, histWorker, &HistWorker::FillHistograms); + + connect(this, &SingleSpectra::startWorkerTimer, timer, static_cast(&QTimer::start)); + connect(this, &SingleSpectra::stopWorkerTimer, timer, &QTimer::stop); + + + workerThread->start(); } @@ -249,6 +250,8 @@ void SingleSpectra::FillHistograms(){ timespec ta, tb; printf("####################### SingleSpectra::%s\n", __func__); + // qDebug() << __func__ << "| thread:" << QThread::currentThreadId(); + clock_gettime(CLOCK_REALTIME, &ta); std::vector digiChList; // (digi*1000 + ch) @@ -315,7 +318,7 @@ void SingleSpectra::FillHistograms(){ } hist2D[ID]->Fill(ch, data); - QCoreApplication::processEvents(); + // QCoreApplication::processEvents(); clock_gettime(CLOCK_REALTIME, &tb); }while( isFillingHistograms && (tb.tv_nsec - ta.tv_nsec)/1e6 + (tb.tv_sec - ta.tv_sec)*1e3 < maxFillTimeinMilliSec ); @@ -334,6 +337,8 @@ void SingleSpectra::FillHistograms(){ void SingleSpectra::ReplotHistograms(){ + // qDebug() << __func__ << "| thread:" << QThread::currentThreadId(); + int ID = cbDigi->currentData().toInt(); int ch = cbCh->currentData().toInt(); diff --git a/SingleSpectra.h b/SingleSpectra.h index 56d9ef8..3cae9d2 100644 --- a/SingleSpectra.h +++ b/SingleSpectra.h @@ -45,16 +45,22 @@ public: void ReplotHistograms(); +signals: + void startWorkerTimer(int interval); + void stopWorkerTimer(); + public slots: void FillHistograms(); void ChangeHistView(); void startTimer(){ // printf("timer start\n"); - timer->start(maxFillTimeinMilliSec); + // timer->start(maxFillTimeinMilliSec); + emit startWorkerTimer(maxFillTimeinMilliSec); } void stopTimer(){ // printf("timer stop\n"); - timer->stop(); + // timer->stop(); + emit stopWorkerTimer(); isFillingHistograms = false; // this will also break the FillHistogram do-loop ClearInternalDataCount(); } -- 2.34.1 From fe6bdb82ff3fce3b111fe27f9e1754aec19ea123 Mon Sep 17 00:00:00 2001 From: "Ryan@SOLARIS_testStation" Date: Tue, 22 Oct 2024 13:56:26 -0400 Subject: [PATCH 22/35] simplify code for multi thread --- SingleSpectra.cpp | 14 ++++++++------ SingleSpectra.h | 12 ++++++------ analyzers/Analyser.cpp | 2 +- analyzers/NeutronGamma.h | 2 ++ 4 files changed, 17 insertions(+), 13 deletions(-) diff --git a/SingleSpectra.cpp b/SingleSpectra.cpp index 6b1d366..adef1b9 100644 --- a/SingleSpectra.cpp +++ b/SingleSpectra.cpp @@ -153,16 +153,18 @@ SingleSpectra::SingleSpectra(Digitizer ** digi, unsigned int nDigi, QString rawD timer = new QTimer(this); histWorker->moveToThread(workerThread); - timer->moveToThread(workerThread); + + // this is another way + // timer = new QTimer(); + // timer->moveToThread(workerThread); + // connect(this, &SingleSpectra::startWorkerTimer, timer, static_cast(&QTimer::start)); + // connect(this, &SingleSpectra::stopWorkerTimer, timer, &QTimer::stop); isFillingHistograms = false; - // connect(timer, &QTimer::timeout, histWorker, &HistWorker::FillHistograms); + connect(timer, &QTimer::timeout, histWorker, &HistWorker::FillHistograms); connect( histWorker, &HistWorker::workDone, this, &SingleSpectra::ReplotHistograms); - connect(timer, &QTimer::timeout, histWorker, &HistWorker::FillHistograms); - connect(this, &SingleSpectra::startWorkerTimer, timer, static_cast(&QTimer::start)); - connect(this, &SingleSpectra::stopWorkerTimer, timer, &QTimer::stop); workerThread->start(); @@ -250,7 +252,7 @@ void SingleSpectra::FillHistograms(){ timespec ta, tb; printf("####################### SingleSpectra::%s\n", __func__); - // qDebug() << __func__ << "| thread:" << QThread::currentThreadId(); + qDebug() << __func__ << "| thread:" << QThread::currentThreadId(); clock_gettime(CLOCK_REALTIME, &ta); diff --git a/SingleSpectra.h b/SingleSpectra.h index 3cae9d2..2808187 100644 --- a/SingleSpectra.h +++ b/SingleSpectra.h @@ -46,21 +46,21 @@ public: void ReplotHistograms(); signals: - void startWorkerTimer(int interval); - void stopWorkerTimer(); + // void startWorkerTimer(int interval); + // void stopWorkerTimer(); public slots: void FillHistograms(); void ChangeHistView(); void startTimer(){ // printf("timer start\n"); - // timer->start(maxFillTimeinMilliSec); - emit startWorkerTimer(maxFillTimeinMilliSec); + timer->start(maxFillTimeinMilliSec); + // emit startWorkerTimer(maxFillTimeinMilliSec); } void stopTimer(){ // printf("timer stop\n"); - // timer->stop(); - emit stopWorkerTimer(); + timer->stop(); + // emit stopWorkerTimer(); isFillingHistograms = false; // this will also break the FillHistogram do-loop ClearInternalDataCount(); } diff --git a/analyzers/Analyser.cpp b/analyzers/Analyser.cpp index bcfd5ed..dad6212 100644 --- a/analyzers/Analyser.cpp +++ b/analyzers/Analyser.cpp @@ -169,7 +169,7 @@ void Analyzer::RedefineEventBuilder(std::vector idList){ } void Analyzer::BuildEvents(bool verbose){ - + // qDebug() << __func__ << "| thread:" << QThread::currentThreadId(); // unsigned int nData = mb->GetNumOfDigitizer(); // std::vector idList = mb->GetDigiIDList(); // for( unsigned int i = 0; i < nData; i++ ) digiMTX[idList[i]].lock(); diff --git a/analyzers/NeutronGamma.h b/analyzers/NeutronGamma.h index 65996b0..850a5b2 100644 --- a/analyzers/NeutronGamma.h +++ b/analyzers/NeutronGamma.h @@ -185,6 +185,8 @@ inline void NeutronGamma::UpdateHistograms(){ if( !fillHistograms ) return; if( this->isVisible() == false ) return; + // qDebug() << __func__ << "| thread:" << QThread::currentThreadId(); + int ID = cbDigi->currentData().toInt(); int ch = cbCh->currentData().toInt(); -- 2.34.1 From 4ab72dc43d411e3a4a36cebb5d6013cd59b5c1fd Mon Sep 17 00:00:00 2001 From: "Ryan@SOLARIS_testStation" Date: Tue, 22 Oct 2024 16:38:01 -0400 Subject: [PATCH 23/35] fix all code with parallel thread --- SingleSpectra.cpp | 5 +---- analyzers/CoincidentAnalyzer.h | 13 ++++++++----- analyzers/NeutronGamma.h | 7 ++++++- analyzers/SplitPoleAnalyzer.h | 12 +++++++----- 4 files changed, 22 insertions(+), 15 deletions(-) diff --git a/SingleSpectra.cpp b/SingleSpectra.cpp index adef1b9..c23461d 100644 --- a/SingleSpectra.cpp +++ b/SingleSpectra.cpp @@ -164,9 +164,6 @@ SingleSpectra::SingleSpectra(Digitizer ** digi, unsigned int nDigi, QString rawD connect(timer, &QTimer::timeout, histWorker, &HistWorker::FillHistograms); connect( histWorker, &HistWorker::workDone, this, &SingleSpectra::ReplotHistograms); - - - workerThread->start(); } @@ -252,7 +249,7 @@ void SingleSpectra::FillHistograms(){ timespec ta, tb; printf("####################### SingleSpectra::%s\n", __func__); - qDebug() << __func__ << "| thread:" << QThread::currentThreadId(); + // qDebug() << __func__ << "| thread:" << QThread::currentThreadId(); clock_gettime(CLOCK_REALTIME, &ta); diff --git a/analyzers/CoincidentAnalyzer.h b/analyzers/CoincidentAnalyzer.h index 44556e1..93476c8 100644 --- a/analyzers/CoincidentAnalyzer.h +++ b/analyzers/CoincidentAnalyzer.h @@ -31,6 +31,7 @@ public: public slots: void UpdateHistograms(); + void ReplotHistograms(); private: @@ -486,11 +487,6 @@ inline void CoincidentAnalyzer::UpdateHistograms(){ } - h2D->UpdatePlot(); - h1->UpdatePlot(); - hMulti->UpdatePlot(); - h1g->UpdatePlot(); - if( influx ){ QList cutNameList = h2D->GetCutNameList(); for( int p = 0; p < cutList.count(); p ++){ @@ -509,6 +505,13 @@ inline void CoincidentAnalyzer::UpdateHistograms(){ } +inline void CoincidentAnalyzer::ReplotHistograms(){ + h2D->UpdatePlot(); + h1->UpdatePlot(); + hMulti->UpdatePlot(); + h1g->UpdatePlot(); +} + inline void CoincidentAnalyzer::SaveSettings(){ QString filePath = QFileDialog::getSaveFileName(this, "Save Settings to File", diff --git a/analyzers/NeutronGamma.h b/analyzers/NeutronGamma.h index 850a5b2..513fbe4 100644 --- a/analyzers/NeutronGamma.h +++ b/analyzers/NeutronGamma.h @@ -59,6 +59,8 @@ public: public slots: void UpdateHistograms(); + void ReplotHistograms(); + private: QVector generateNonRepeatedCombination(int size); void SetUpCanvas(); @@ -210,8 +212,11 @@ inline void NeutronGamma::UpdateHistograms(){ }while(lastFilledIndex[ID][ch] <= digi[ID]->GetData()->GetAbsDataIndex(ch)); - hist2D->UpdatePlot(); +} +inline void NeutronGamma::ReplotHistograms(){ + // qDebug() << __func__ << "| thread:" << QThread::currentThreadId(); + hist2D->UpdatePlot(); } inline QVector NeutronGamma::generateNonRepeatedCombination(int size) { diff --git a/analyzers/SplitPoleAnalyzer.h b/analyzers/SplitPoleAnalyzer.h index 088a1fe..c279084 100644 --- a/analyzers/SplitPoleAnalyzer.h +++ b/analyzers/SplitPoleAnalyzer.h @@ -63,6 +63,7 @@ public: public slots: void UpdateHistograms(); + void ReplotHistograms(); private: @@ -421,11 +422,6 @@ inline void SplitPole::UpdateHistograms(){ } } - hPID->UpdatePlot(); - h1->UpdatePlot(); - hMulti->UpdatePlot(); - h1g->UpdatePlot(); - QList cutNameList = hPID->GetCutNameList(); for( int p = 0; p < cutList.count(); p ++){ if( cutList[p].isEmpty() ) continue; @@ -441,5 +437,11 @@ inline void SplitPole::UpdateHistograms(){ } +inline void SplitPole::ReplotHistograms(){ + hPID->UpdatePlot(); + h1->UpdatePlot(); + hMulti->UpdatePlot(); + h1g->UpdatePlot(); +} #endif \ No newline at end of file -- 2.34.1 From 8b7d93a9fe40c0f0f0a3306a68adc4ecb1dc1ac9 Mon Sep 17 00:00:00 2001 From: "Ryan@SOLARIS_testStation" Date: Mon, 28 Oct 2024 13:24:38 -0400 Subject: [PATCH 24/35] When open digi setting or Scope, update settings from memory --- FSUDAQ.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/FSUDAQ.cpp b/FSUDAQ.cpp index d88b8c9..395992d 100644 --- a/FSUDAQ.cpp +++ b/FSUDAQ.cpp @@ -1791,6 +1791,7 @@ void FSUDAQ::OpenScope(){ scope->show(); }else{ scope->show(); + scope->UpdatePanelFromMomeory(); scope->activateWindow(); } @@ -1815,6 +1816,7 @@ void FSUDAQ::OpenDigiSettings(){ digiSettings->show(); }else{ digiSettings->show(); + digiSettings->UpdatePanelFromMemory(); digiSettings->activateWindow(); } } -- 2.34.1 From c7feaec47113b0b6da0182e8c2c4b2e28a9b40c7 Mon Sep 17 00:00:00 2001 From: "Ryan@SOLARIS_testStation" Date: Mon, 28 Oct 2024 15:12:26 -0400 Subject: [PATCH 25/35] small improvement, Event/Agg for PHA/PSD < 512 --- ClassDigitizer.cpp | 47 +++++++++++++++++++++++++++++++++++++++++-- ClassDigitizer.h | 22 ++++---------------- DigiSettingsPanel.cpp | 2 ++ RegisterAddress.h | 2 +- 4 files changed, 52 insertions(+), 21 deletions(-) diff --git a/ClassDigitizer.cpp b/ClassDigitizer.cpp index 23c31f4..db20bc4 100644 --- a/ClassDigitizer.cpp +++ b/ClassDigitizer.cpp @@ -576,7 +576,7 @@ void Digitizer::StartACQ(){ data->ClearTriggerRate(); data->ClearData(); - if( DPPType == DPPTypeCode::DPP_QDC_CODE ) SetOptimialAggOrg(); + if( DPPType == DPPTypeCode::DPP_QDC_CODE ) SetQDCOptimialAggOrg(); printf(" ACQ mode : %s (%d), TRG-OUT mode : %s (%d) \n", acqStr.c_str(), acqID, trgOutStr.c_str(), trgOutID); @@ -1351,7 +1351,50 @@ void Digitizer::SetBits(Reg address, unsigned int bitValue, unsigned int bitLeng if( ret != 0 ) ErrorMsg(__func__); } -void Digitizer::SetOptimialAggOrg(){ +void Digitizer::AutoSetDPPEventAggregation(){ + //ret = CAEN_DGTZ_SetDPPAcquisitionMode(handle, CAEN_DGTZ_DPP_ACQ_MODE_List, CAEN_DGTZ_DPP_SAVE_PARAM_EnergyAndTime); + + // if( DPPType == DPPTypeCode::DPP_QDC_CODE ){ + + // }else{ + + // for( int ch = 0; ch < GetNumInputCh(); ch += 2 ){ + // uint32_t a1, a2; + // ret |= CAEN_DGTZ_GetRecordLength(handle, &a1, ch); + // ret |= CAEN_DGTZ_GetNumEventsPerAggregate(handle, &a2, ch); + // printf("Ch %2d | RecordLength : %d | Event Agg : %d \n", ch, a1, a2); + // } + + // uint32_t chMask ; + // ret |= CAEN_DGTZ_GetChannelEnableMask(handle, &chMask); + // printf("Ch Mask %0X \n", chMask); + + // } + + ret = 0; + ret |= CAEN_DGTZ_SetDPPEventAggregation(handle, 0, 0); // AutoSet + if( ret != 0 ) { + printf("!!!!!!!! set %s error.\n", __func__); + }else{ + Reg regAdd = DPP::AggregateOrganization; + uint32_t haha = ReadRegister(regAdd); + SetSettingToMemory(regAdd, haha, 0); + SaveSettingToFile(regAdd, haha, 0); + } +} + +uint32_t Digitizer::ReadQDCRecordLength() { + returnData = ReadRegister(DPP::QDC::RecordLength_R); + Reg temp = DPP::QDC::RecordLength_R; + int indexR = temp.Index(0); + temp = DPP::QDC::RecordLength_W; + int indexW = temp.Index(0); + setting[indexW] = setting[indexR]; + //printf("%d %d | %u %u \n", indexR, indexW, setting[indexR], setting[indexW]); + return returnData; +} + +void Digitizer::SetQDCOptimialAggOrg(){ DebugPrint("%s", "Digitizer"); if( DPPType != DPPTypeCode::DPP_QDC_CODE ) { printf("%s | this method only support QDC board.\n", __func__); diff --git a/ClassDigitizer.h b/ClassDigitizer.h index 6087493..7d2ef7e 100644 --- a/ClassDigitizer.h +++ b/ClassDigitizer.h @@ -95,12 +95,8 @@ class Digitizer{ void PrintBoard(); void ProgramBoard(); - void AutoSetDPPEventAggregation(){ - //ret = CAEN_DGTZ_SetDPPAcquisitionMode(handle, CAEN_DGTZ_DPP_ACQ_MODE_List, CAEN_DGTZ_DPP_SAVE_PARAM_EnergyAndTime); - ret |= CAEN_DGTZ_SetNumEventsPerAggregate(handle, 10); - ret |= CAEN_DGTZ_SetDPPEventAggregation(handle, 0, 0); // AutoSet - if( ret != 0 ) { printf("!!!!!!!! set %s error.\n", __func__);} - } + + void AutoSetDPPEventAggregation(); //^================ ACQ control void StopACQ(); @@ -192,19 +188,9 @@ class Digitizer{ bool IsDualTrace_PHA() {return ( (GetSettingFromMemory(DPP::BoardConfiguration) >> 11) & 0x1 );} bool IsRecordTrace() {return ( (GetSettingFromMemory(DPP::BoardConfiguration) >> 16) & 0x1 );} - void SetOptimialAggOrg(); - //QDC read recordLength - uint32_t ReadQDCRecordLength() { - returnData = ReadRegister(DPP::QDC::RecordLength_R); - Reg temp = DPP::QDC::RecordLength_R; - int indexR = temp.Index(0); - temp = DPP::QDC::RecordLength_W; - int indexW = temp.Index(0); - setting[indexW] = setting[indexR]; - //printf("%d %d | %u %u \n", indexR, indexW, setting[indexR], setting[indexW]); - return returnData; - } + uint32_t ReadQDCRecordLength(); + void SetQDCOptimialAggOrg(); void SetTrace(bool onOff){ SetBits(DPP::BoardConfiguration, DPP::Bit_BoardConfig::RecordTrace, onOff, -1); diff --git a/DigiSettingsPanel.cpp b/DigiSettingsPanel.cpp index 04d8dc8..f5b97c9 100644 --- a/DigiSettingsPanel.cpp +++ b/DigiSettingsPanel.cpp @@ -257,6 +257,8 @@ DigiSettingsPanel::DigiSettingsPanel(Digitizer ** digi, unsigned int nDigi, QStr SendLogMsg("Digi-" +QString::number(digi[ID]->GetSerialNumber()) + " : AutoSetDPPEventAggregation()"); digi[ID]->AutoSetDPPEventAggregation(); UpdateBoardAndChannelsStatus(); + UpdatePanelFromMemory(); + emit UpdateOtherPanels(); }); // bnSendSoftwareClockSyncSignal = new QPushButton("Send SW Clock-Sync Signal", this); diff --git a/RegisterAddress.h b/RegisterAddress.h index 619203f..73c554f 100644 --- a/RegisterAddress.h +++ b/RegisterAddress.h @@ -508,7 +508,7 @@ namespace DPP { const Reg RecordLength_G ("RecordLength_G" , 0x1020, RW::ReadWrite, true, 0x3FFF, 8); /// R/W const Reg InputDynamicRange ("InputDynamicRange" , 0x1028, RW::ReadWrite, false, {{"2 Vpp", 0},{"0.5 Vpp", 1}}); /// R/W - const Reg NumberEventsPerAggregate_G ("NumberEventsPerAggregate_G" , 0x1034, RW::ReadWrite, true, 0x3FF, -1); /// R/W + const Reg NumberEventsPerAggregate_G ("NumberEventsPerAggregate_G" , 0x1034, RW::ReadWrite, true, 0x1FF, -1); /// R/W const Reg PreTrigger ("PreTrigger" , 0x1038, RW::ReadWrite, false, 0xFF, 4); /// R/W const Reg TriggerThreshold ("TriggerThreshold" , 0x106C, RW::ReadWrite, false, 0x3FFF, -1); /// R/W const Reg TriggerHoldOffWidth ("TriggerHoldOffWidth" , 0x1074, RW::ReadWrite, false, 0x3FF, 4); /// R/W -- 2.34.1 From e856a1cddff2cb128a2e4ca1a2189a91aa8904f4 Mon Sep 17 00:00:00 2001 From: "Ryan@SOLARIS_testStation" Date: Mon, 28 Oct 2024 15:36:40 -0400 Subject: [PATCH 26/35] fix copy channels --- DigiSettingsPanel.cpp | 26 ++++++++++++++++++++++---- 1 file changed, 22 insertions(+), 4 deletions(-) diff --git a/DigiSettingsPanel.cpp b/DigiSettingsPanel.cpp index f5b97c9..3daaaa1 100644 --- a/DigiSettingsPanel.cpp +++ b/DigiSettingsPanel.cpp @@ -354,6 +354,7 @@ DigiSettingsPanel::DigiSettingsPanel(Digitizer ** digi, unsigned int nDigi, QStr } SetUpInquiryCopyTab(); + CheckRadioAndCheckedButtons(); connect(tabWidget, &QTabWidget::currentChanged, this, [=](int index){ if( index < (int) nDigi) { @@ -1338,8 +1339,13 @@ void DigiSettingsPanel::SetUpInquiryCopyTab(){ if( fromCh == -1 ) return; + printf("Copy Digi-%d, ch %d \n", digi[fromIndex]->GetSerialNumber(), fromCh); + for( int i = 0; i < MaxRegChannel; i++){ - if( ! chkCh[i]->isChecked() ) return; + + if( !chkCh[i]->isChecked() || !chkCh[i]->isEnabled() ) continue; + + printf("... to Digi-%d, ch %d \n", digi[toIndex]->GetSerialNumber(), i); //Copy setting for( int k = 0; k < (int) regList.size(); k ++){ if( regList[k].GetRWType() != RW::ReadWrite ) continue; @@ -4105,17 +4111,29 @@ void DigiSettingsPanel::CheckRadioAndCheckedButtons(){ int id1 = cbFromBoard->currentIndex(); int id2 = cbToBoard->currentIndex(); - for( int i = 0 ; i < MaxRegChannel; i++){ - if( i >= digi[id1]->GetNumRegChannels() ) rbCh[i]->setEnabled(false); - if( i >= digi[id2]->GetNumRegChannels() ) chkCh[i]->setEnabled(false); + if( digi[id1]->GetDPPType() == DPPTypeCode::DPP_QDC_CODE ){ + bnCopyChannel->setText("Copy Group(s)"); + }else{ + bnCopyChannel->setText("Copy Channel(s)"); } if( digi[id1]->GetDPPType() != digi[id2]->GetDPPType() ){ bnCopyBoard->setEnabled(false); bnCopyChannel->setEnabled(false); + + for( int i = 0 ; i < MaxRegChannel; i++){ + rbCh[i]->setEnabled(false); + chkCh[i]->setEnabled(false); + } + return; } + for( int i = 0 ; i < MaxRegChannel; i++){ + rbCh[i]->setEnabled(i < digi[id1]->GetNumRegChannels()); + chkCh[i]->setEnabled(i < digi[id1]->GetNumRegChannels()); + } + if( id1 == id2 ){ bnCopyBoard->setEnabled(false); }else{ -- 2.34.1 From 1562d9cab21e5300dbc2cecd7ba558ea3ae21500 Mon Sep 17 00:00:00 2001 From: "Ryan@SOLARIS_testStation" Date: Mon, 28 Oct 2024 15:41:54 -0400 Subject: [PATCH 27/35] add QDC group copy --- DigiSettingsPanel.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/DigiSettingsPanel.cpp b/DigiSettingsPanel.cpp index 3daaaa1..bbcf641 100644 --- a/DigiSettingsPanel.cpp +++ b/DigiSettingsPanel.cpp @@ -1328,6 +1328,7 @@ void DigiSettingsPanel::SetUpInquiryCopyTab(){ std::vector regList; if( digi[fromIndex]->GetDPPType() == V1730_DPP_PHA_CODE ) regList = RegisterChannelList_PHA; if( digi[fromIndex]->GetDPPType() == V1730_DPP_PSD_CODE ) regList = RegisterChannelList_PSD; + if( digi[fromIndex]->GetDPPType() == V1740_DPP_QDC_CODE ) regList = RegisterChannelList_QDC; int fromCh = -1; for( int i = 0; i < MaxRegChannel; i++) { -- 2.34.1 From 4eca8eb09acf9d62b45dd37b4d25335b02ae0992 Mon Sep 17 00:00:00 2001 From: "Ryan@SOLARIS_testStation" Date: Wed, 30 Oct 2024 15:42:45 -0400 Subject: [PATCH 28/35] fix a bug for PHA --- DigiSettingsPanel.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/DigiSettingsPanel.cpp b/DigiSettingsPanel.cpp index bbcf641..9e85169 100644 --- a/DigiSettingsPanel.cpp +++ b/DigiSettingsPanel.cpp @@ -1811,7 +1811,7 @@ void DigiSettingsPanel::SetUpChannel_PHA(){ QLabel * lb2 = new QLabel("Local Shaped Trig. [G]", this); lb2->setAlignment(Qt::AlignHCenter); tabLayout->addWidget(lb2, 0, 4); QLabel * lb1 = new QLabel("Trig. Counter Flag [G]", this); lb1->setAlignment(Qt::AlignHCenter); tabLayout->addWidget(lb1, 0, 6); } - SetUpSpinBox(sbShapedTrigWidth[ID][ch], "", tabLayout, ch + 1, 1, DPP::PSD::ShapedTriggerWidth, ch); + SetUpSpinBox(sbShapedTrigWidth[ID][ch], "", tabLayout, ch + 1, 1, DPP::PHA::ShapedTriggerWidth, ch); SetUpComboBoxBit(cbLocalShapedTrigger[ID][ch], "", tabLayout, ch + 1, 3, DPP::PHA::Bit_DPPAlgorithmControl2::ListLocalShapeTrigMode, DPP::PHA::DPPAlgorithmControl2_G, DPP::PHA::Bit_DPPAlgorithmControl2::LocalShapeTriggerMode, 1, ch); SetUpComboBoxBit(cbTrigCount[ID][ch], "", tabLayout, ch + 1, 5, DPP::PHA::Bit_DPPAlgorithmControl2::ListTrigCounter, DPP::PHA::DPPAlgorithmControl2_G, DPP::PHA::Bit_DPPAlgorithmControl2::TriggerCounterFlag, 1, ch); SetUpCheckBox(chkTagCorrelation[ID][ch], "Tag Correlated events [G]", tabLayout, ch + 1, 7, DPP::PHA::DPPAlgorithmControl2_G, DPP::PHA::Bit_DPPAlgorithmControl2::TagCorrelatedEvents, ch); -- 2.34.1 From 2be9d3432034077ae174d77dbeff9d2bc20ceb07 Mon Sep 17 00:00:00 2001 From: "Ryan@SOLARIS_testStation" Date: Wed, 30 Oct 2024 18:48:00 -0400 Subject: [PATCH 29/35] UI bugs fix --- DigiSettingsPanel.cpp | 23 ++++++++++++++++------- RegisterAddress.h | 2 +- 2 files changed, 17 insertions(+), 8 deletions(-) diff --git a/DigiSettingsPanel.cpp b/DigiSettingsPanel.cpp index 9e85169..96406a4 100644 --- a/DigiSettingsPanel.cpp +++ b/DigiSettingsPanel.cpp @@ -407,7 +407,13 @@ void DigiSettingsPanel::SetUpCheckBox(QCheckBox * &chkBox, QString label, QGridL if( !enableSignalSlot ) return; int chID = ch < 0 ? chSelection[ID]->currentData().toInt() : ch; - digi[ID]->SetBits(para, bit, state ? 1 : 0, chID); + + if( para == DPP::DisableExternalTrigger ) { + digi[ID]->SetBits(para, bit, state ? 0 : 1, chID); + }else{ + digi[ID]->SetBits(para, bit, state ? 1 : 0, chID); + } + if( para.IsCoupled() == true && chID >= 0 ) digi[ID]->SetBits(para, bit, state ? 1 : 0, chID%2 == 0 ? chID + 1 : chID - 1); UpdatePanelFromMemory(); emit UpdateOtherPanels(); @@ -625,6 +631,11 @@ void DigiSettingsPanel::SetUpGlobalTriggerMaskAndFrontPanelMask(QGridLayout * & }); SetUpCheckBox(chkEnableExternalTrigger[ID], "Enable TRG-IN ", gLayout, 1, 1, DPP::DisableExternalTrigger, {1, 0}); + + connect(chkEnableExternalTrigger[ID], &QCheckBox::stateChanged, this, [=](int state){ + cbTRGINMode[ID]->setEnabled(state); + cbTRINMezzanines[ID]->setEnabled(state); + }); ///============================ Trig In mode QLabel * trgInMode = new QLabel("TRI-In Mode ", this); @@ -660,11 +671,6 @@ void DigiSettingsPanel::SetUpGlobalTriggerMaskAndFrontPanelMask(QGridLayout * & digi[ID]->SetBits(DPP::FrontPanelIOControl, DPP::Bit_FrontPanelIOControl::TRGINMode, index, -1); }); - connect(chkEnableExternalTrigger[ID], &QCheckBox::stateChanged, this, [=](int state){ - cbTRGINMode[ID]->setEnabled(state); - cbTRINMezzanines[ID]->setEnabled(state); - }); - SetUpComboBox(cbAnalogMonitorMode[ID], "Analog Monitor Mode ", gLayout, 4, 0, DPP::AnalogMonitorMode, 0); connect(cbAnalogMonitorMode[ID], &RComboBox::currentIndexChanged, this, [=](int index){ @@ -3390,7 +3396,7 @@ void DigiSettingsPanel::UpdatePanelFromMemory(){ sbAggNum[ID]->setValue(digi[ID]->GetSettingFromMemory(DPP::MaxAggregatePerBlockTransfer)); - chkEnableExternalTrigger[ID]->setChecked( ! ( digi[ID]->GetSettingFromMemory(DPP::DisableExternalTrigger) & 0x1) ); + chkEnableExternalTrigger[ID]->setChecked( !( digi[ID]->GetSettingFromMemory(DPP::DisableExternalTrigger) & 0x1) ); sbRunDelay[ID]->setValue(digi[ID]->GetSettingFromMemory(DPP::RunStartStopDelay) * DPP::RunStartStopDelay.GetPartialStep() * digi[ID]->GetTick2ns()); @@ -3435,6 +3441,9 @@ void DigiSettingsPanel::UpdatePanelFromMemory(){ } } + cbTRGINMode[ID]->setCurrentIndex((frontPanel >> 10 ) & 0x1); + cbTRINMezzanines[ID]->setCurrentIndex((frontPanel >> 11 ) & 0x1); + //*======================================== uint32_t glbTrgMask = digi[ID]->GetSettingFromMemory(DPP::GlobalTriggerMask); diff --git a/RegisterAddress.h b/RegisterAddress.h index 73c554f..f9dd3c6 100644 --- a/RegisterAddress.h +++ b/RegisterAddress.h @@ -545,7 +545,7 @@ namespace DPP { const Reg RegChannelEnableMask ("RegChannelEnableMask" , 0x8120, RW::ReadWrite, false, {}); /// R/W const Reg ROCFPGAFirmwareRevision_R ("ROCFPGAFirmwareRevision_R" , 0x8124, RW::ReadONLY , false, {}); /// R const Reg EventStored_R ("EventStored_R" , 0x812C, RW::ReadONLY , false, {}); /// R - const Reg VoltageLevelModeConfig ("VoltageLevelModeConfig" , 0x8138, RW::ReadWrite, false, {}); /// R/W + const Reg VoltageLevelModeConfig ("VoltageLevelModeConfig" , 0x8138, RW::ReadWrite, false, 0xFFF, -1); /// R/W const Reg SoftwareClockSync_W ("SoftwareClockSync_W" , 0x813C, RW::WriteONLY, false, {}); /// W const Reg BoardInfo_R ("BoardInfo_R" , 0x8140, RW::ReadONLY , false, {}); /// R const Reg AnalogMonitorMode ("AnalogMonitorMode" , 0x8144, RW::ReadWrite, false, {{"Trig. Maj. Mode", 0}, -- 2.34.1 From 81b2fba62346dae7a7d3121d3077e838b1fbe144 Mon Sep 17 00:00:00 2001 From: "Ryan@SOLARIS_testStation" Date: Thu, 31 Oct 2024 18:03:12 -0400 Subject: [PATCH 30/35] Rename trigger : Independent --> Normal, Trig Valid, from Both From Mather Board to Both from TRG_VAL; More GUI bugs fix for trigger related settings --- DigiSettingsPanel.cpp | 16 +++++++++++----- RegisterAddress.h | 10 +++++----- 2 files changed, 16 insertions(+), 10 deletions(-) diff --git a/DigiSettingsPanel.cpp b/DigiSettingsPanel.cpp index 96406a4..e3f48af 100644 --- a/DigiSettingsPanel.cpp +++ b/DigiSettingsPanel.cpp @@ -662,13 +662,13 @@ void DigiSettingsPanel::SetUpGlobalTriggerMaskAndFrontPanelMask(QGridLayout * & cbTRINMezzanines[ID] = new RComboBox(this); gLayout->addWidget(cbTRINMezzanines[ID], 3, 1, 1, 2); - items = DPP::Bit_FrontPanelIOControl::ListTRGIMezzanine; + items = DPP::Bit_FrontPanelIOControl::ListTRGINMezzanine; for(int i = 0; i < (int) items.size(); i++){ cbTRINMezzanines[ID]->addItem(QString::fromStdString(items[i].first), items[i].second); } connect( cbTRINMezzanines[ID], &RComboBox::currentIndexChanged, this, [=](int index){ if( !enableSignalSlot ) return; - digi[ID]->SetBits(DPP::FrontPanelIOControl, DPP::Bit_FrontPanelIOControl::TRGINMode, index, -1); + digi[ID]->SetBits(DPP::FrontPanelIOControl, DPP::Bit_FrontPanelIOControl::TRGINMezzanine, index, -1); }); SetUpComboBox(cbAnalogMonitorMode[ID], "Analog Monitor Mode ", gLayout, 4, 0, DPP::AnalogMonitorMode, 0); @@ -3456,10 +3456,16 @@ void DigiSettingsPanel::UpdatePanelFromMemory(){ } } sbGlbMajLvl[ID]->setValue( Digitizer::ExtractBits(glbTrgMask, DPP::Bit_GlobalTriggerMask::MajorLevel) ); - } - sbGlbMajCoinWin[ID]->setValue( Digitizer::ExtractBits(glbTrgMask, DPP::Bit_GlobalTriggerMask::MajorCoinWin) ); - cbGlbUseOtherTriggers[ID]->setCurrentIndex(Digitizer::ExtractBits(glbTrgMask, {2, 30})); + sbGlbMajCoinWin[ID]->setValue( Digitizer::ExtractBits(glbTrgMask, DPP::Bit_GlobalTriggerMask::MajorCoinWin) * 4 * digi[ID]->GetTick2ns()); + cbGlbUseOtherTriggers[ID]->setCurrentIndex(Digitizer::ExtractBits(glbTrgMask, {2, 30})); + + if( sbGlbMajLvl[ID]->value() > 0 ) { + sbGlbMajCoinWin[ID]->setEnabled(true); + }else{ + sbGlbMajCoinWin[ID]->setEnabled(false); + } + } //*======================================== uint32_t TRGOUTMask = digi[ID]->GetSettingFromMemory(DPP::FrontPanelTRGOUTEnableMask); diff --git a/RegisterAddress.h b/RegisterAddress.h index f9dd3c6..905257b 100644 --- a/RegisterAddress.h +++ b/RegisterAddress.h @@ -314,7 +314,7 @@ namespace DPP { const std::vector> ListPolarity = {{"Positive", 0}, {"Negative", 1}}; - const std::vector> ListTrigMode = {{"Independent", 0}, + const std::vector> ListTrigMode = {{"Normal", 0}, {"Coincident", 1}, {"Anti-Coincident", 3}}; @@ -381,7 +381,7 @@ namespace DPP { const std::vector> ListPolarity = {{"Positive", 0}, {"Negative", 1}}; - const std::vector> ListTrigMode = {{"Independent", 0}, + const std::vector> ListTrigMode = {{"Normal", 0}, {"Coincident ", 1}, {"Anti-Coincident", 3}}; @@ -480,7 +480,7 @@ namespace DPP { {"TTL I/O", 1}}; const std::vector> ListTRGIMode = {{"Edge of TRG-IN", 0}, {"Whole duration of TRG-IN", 1}}; - const std::vector> ListTRGIMezzanine = {{"Pocessed by Motherboard", 0}, + const std::vector> ListTRGINMezzanine = {{"Pocessed by Motherboard", 0}, {"Skip Motherboard", 1}}; const std::vector> ListTRGOUTConfig = {{"Disable", 0x00002}, /// this is TRG_OUT high imped. 0x811C bit[1] @@ -647,7 +647,7 @@ namespace DPP { const std::vector> ListLocalTrigValidMode = {{"Disabled", 0}, {"Crossed Trigger", 4}, - {"Both from Mother board", 5}, + {"Both from TRG_VAL", 5}, {"AND", 6}, {"OR", 7}}; @@ -736,7 +736,7 @@ namespace DPP { const std::vector> ListLocalTrigValidMode = {{"Disabled", 0}, {"Crossed Trigger", 4}, - {"Both from Mother board", 5}, + {"Both from TRG_VAL", 5}, {"AND", 6}, {"OR", 7}}; -- 2.34.1 From 9bdd6b77eb8d07b30adbc536d153fc92310f16fd Mon Sep 17 00:00:00 2001 From: "Ryan@SOLARIS_testStation" Date: Fri, 1 Nov 2024 16:42:31 -0400 Subject: [PATCH 31/35] seperate out ProgramChannel from ProgramBoard in Digitizer Class --- ClassDigitizer.cpp | 293 +++++++++++++++++++++++++-------------------- ClassDigitizer.h | 4 + 2 files changed, 165 insertions(+), 132 deletions(-) diff --git a/ClassDigitizer.cpp b/ClassDigitizer.cpp index db20bc4..34425da 100644 --- a/ClassDigitizer.cpp +++ b/ClassDigitizer.cpp @@ -328,181 +328,173 @@ void Digitizer::ProgramBoard(){ int Digitizer::ProgramBoard_PHA(){ DebugPrint("%s", "Digitizer"); - printf("===== Digitizer::%s\n", __func__); - //ret = CAEN_DGTZ_Reset(handle); - Reset(); - ret = CAEN_DGTZ_WriteRegister(handle, DPP::RecordLength_G + 0x7000, 62); + //*========================== Board + /// change address 0xEF08 (5 bits), this will reflected in the 2nd word of the Board Agg. header. + ret = CAEN_DGTZ_WriteRegister(handle, DPP::BoardID, (DPPType & 0xF)); + //WriteRegister(DPP::BoardID, (DPPType & 0xF)); + //ret = CAEN_DGTZ_WriteRegister(handle, DPP::BoardConfiguration, 0x0F8915); /// has Extra2, dual trace, input and trap-baseline - ret = CAEN_DGTZ_WriteRegister(handle, DPP::BoardConfiguration, 0x0E8915); /// has Extra2, no trace + ret |= CAEN_DGTZ_WriteRegister(handle, DPP::BoardConfiguration, 0x0E8915); /// has Extra2, no trace //ret = CAEN_DGTZ_WriteRegister(handle, DPP::BoardConfiguration, 0x0D8115); /// diable Extra2 //TODO change to write register ret = CAEN_DGTZ_SetAcquisitionMode(handle, CAEN_DGTZ_SW_CONTROLLED); /// software command + ret |= CAEN_DGTZ_SetChannelEnableMask(handle, ModelType == ModelTypeCode::VME ? 0xFFFF : 0x00FF); + ret |= CAEN_DGTZ_SetRunSynchronizationMode(handle, CAEN_DGTZ_RUN_SYNC_Disabled); ret |= CAEN_DGTZ_SetIOLevel(handle, CAEN_DGTZ_IOLevel_NIM); ret |= CAEN_DGTZ_SetExtTriggerInputMode(handle, CAEN_DGTZ_TRGMODE_ACQ_ONLY); + ret |= CAEN_DGTZ_WriteRegister(handle, (int32_t)(DPP::GlobalTriggerMask), 0x0); + ret |= CAEN_DGTZ_WriteRegister(handle, (int32_t)(DPP::FrontPanelTRGOUTEnableMask), 0x0); - ret = CAEN_DGTZ_SetChannelEnableMask(handle, ModelType == ModelTypeCode::VME ? 0xFFFF : 0x00FF); - //ret = CAEN_DGTZ_SetNumEventsPerAggregate(handle, 0); - ret = CAEN_DGTZ_SetRunSynchronizationMode(handle, CAEN_DGTZ_RUN_SYNC_Disabled); if( ret != 0 ) { printf("==== set board error.\n"); return 0;} - uint32_t address; - - address = DPP::PHA::DecayTime; ret |= CAEN_DGTZ_WriteRegister(handle, address + 0x7000 , 5000 ); - address = DPP::PHA::TrapezoidFlatTop; ret |= CAEN_DGTZ_WriteRegister(handle, address + 0x7000 , 0x1A ); - address = DPP::PHA::TrapezoidRiseTime; ret |= CAEN_DGTZ_WriteRegister(handle, address + 0x7000 , 6 ); - address = DPP::PHA::PeakingTime; ret |= CAEN_DGTZ_WriteRegister(handle, address + 0x7000 , 6 ); - address = DPP::PHA::RCCR2SmoothingFactor; ret |= CAEN_DGTZ_WriteRegister(handle, address + 0x7000 , 4 ); - address = DPP::PHA::InputRiseTime; ret |= CAEN_DGTZ_WriteRegister(handle, address + 0x7000 , 6 ); - address = DPP::PHA::TriggerThreshold; ret |= CAEN_DGTZ_WriteRegister(handle, address + 0x7000 , 1000 ); - address = DPP::PHA::PeakHoldOff; ret |= CAEN_DGTZ_WriteRegister(handle, address + 0x7000 , 0x3E ); - address = DPP::PHA::TriggerHoldOffWidth; ret |= CAEN_DGTZ_WriteRegister(handle, address + 0x7000 , 0x3E ); - address = DPP::PHA::RiseTimeValidationWindow;ret |= CAEN_DGTZ_WriteRegister(handle, address + 0x7000 , 0x0 ); - - ret |= CAEN_DGTZ_SetChannelDCOffset(handle, 0x0, 0xAAAA); - ret |= CAEN_DGTZ_SetChannelDCOffset(handle, 0x1, 0xAAAA); - ret |= CAEN_DGTZ_SetChannelDCOffset(handle, 0x2, 0xAAAA); - ret |= CAEN_DGTZ_SetChannelDCOffset(handle, 0x3, 0xAAAA); - ret |= CAEN_DGTZ_SetChannelDCOffset(handle, 0x4, 0xAAAA); - ret |= CAEN_DGTZ_SetChannelDCOffset(handle, 0x5, 0xAAAA); - ret |= CAEN_DGTZ_SetChannelDCOffset(handle, 0x6, 0xAAAA); - ret |= CAEN_DGTZ_SetChannelDCOffset(handle, 0x7, 0xAAAA); - if( ModelType == ModelTypeCode::VME ){ - ret |= CAEN_DGTZ_SetChannelDCOffset(handle, 0x8, 0xAAAA); - ret |= CAEN_DGTZ_SetChannelDCOffset(handle, 0x9, 0xAAAA); - ret |= CAEN_DGTZ_SetChannelDCOffset(handle, 0xA, 0xAAAA); - ret |= CAEN_DGTZ_SetChannelDCOffset(handle, 0xB, 0xAAAA); - ret |= CAEN_DGTZ_SetChannelDCOffset(handle, 0xC, 0xAAAA); - ret |= CAEN_DGTZ_SetChannelDCOffset(handle, 0xD, 0xAAAA); - ret |= CAEN_DGTZ_SetChannelDCOffset(handle, 0xE, 0xAAAA); - ret |= CAEN_DGTZ_SetChannelDCOffset(handle, 0xF, 0xAAAA); - } - - ret |= CAEN_DGTZ_WriteRegister(handle, (uint32_t)(DPP::PreTrigger) + 0x7000 , 32 ); - ret |= CAEN_DGTZ_WriteRegister(handle, (uint32_t)(DPP::InputDynamicRange) + 0x7000 , 0x0 ); - ret |= CAEN_DGTZ_WriteRegister(handle, (int32_t)(DPP::DPPAlgorithmControl) + 0x7000, 0x030200f); - - if( ret != 0 ) { printf("!!!!!!!! set channels error.\n");} - - AutoSetDPPEventAggregation(); - - /// change address 0xEF08 (5 bits), this will reflected in the 2nd word of the Board Agg. header. - ret = CAEN_DGTZ_WriteRegister(handle, DPP::BoardID, (DPPType & 0xF)); - //WriteRegister(DPP::BoardID, (DPPType & 0xF)); + //*========================== Group + ProgramChannel_PHA(-1); isSettingFilledinMemeory = false; /// unlock the ReadAllSettingsFromBoard(); - usleep(1000*300); - ReadAllSettingsFromBoard(); return ret; } +int Digitizer::ProgramChannel_PHA(short ch){ + DebugPrint("%s", "Digitizer"); + printf("===== Digitizer::%s|ch:%d\n", __func__,ch); + + uint32_t channel = (ch << 8); + if( ch < 0 ) channel = 0x7000; + + uint32_t address = (ch << 8); + + address = channel + DPP::RecordLength_G; ret = CAEN_DGTZ_WriteRegister(handle, address, 62); + address = channel + DPP::PHA::DecayTime; ret |= CAEN_DGTZ_WriteRegister(handle, address, 5000 ); + address = channel + DPP::PHA::TrapezoidFlatTop; ret |= CAEN_DGTZ_WriteRegister(handle, address, 0x1A ); + address = channel + DPP::PHA::TrapezoidRiseTime; ret |= CAEN_DGTZ_WriteRegister(handle, address, 6 ); + address = channel + DPP::PHA::PeakingTime; ret |= CAEN_DGTZ_WriteRegister(handle, address, 6 ); + address = channel + DPP::PHA::RCCR2SmoothingFactor; ret |= CAEN_DGTZ_WriteRegister(handle, address, 4 ); + address = channel + DPP::PHA::InputRiseTime; ret |= CAEN_DGTZ_WriteRegister(handle, address, 6 ); + address = channel + DPP::PHA::TriggerThreshold; ret |= CAEN_DGTZ_WriteRegister(handle, address, 1000 ); + address = channel + DPP::PHA::PeakHoldOff; ret |= CAEN_DGTZ_WriteRegister(handle, address, 0x3E ); + address = channel + DPP::PHA::TriggerHoldOffWidth; ret |= CAEN_DGTZ_WriteRegister(handle, address, 0x3E ); + address = channel + DPP::PHA::RiseTimeValidationWindow;ret |= CAEN_DGTZ_WriteRegister(handle, address, 0x0 ); + address = channel + DPP::PreTrigger; ret |= CAEN_DGTZ_WriteRegister(handle, address, 32 ); + address = channel + DPP::InputDynamicRange; ret |= CAEN_DGTZ_WriteRegister(handle, address, 0x0 ); + address = channel + DPP::DPPAlgorithmControl; ret |= CAEN_DGTZ_WriteRegister(handle, address, 0x030200f); + address = channel + DPP::PHA::DPPAlgorithmControl2_G; ret |= CAEN_DGTZ_WriteRegister(handle, address, 0x200); // use fine time + + if( ch >= 0 ) { + ret |= CAEN_DGTZ_SetChannelDCOffset(handle, ch, 0xAAAA); + }else{ + for( int i = 0; i < NumRegChannel; i ++ ){ + ret |= CAEN_DGTZ_SetChannelDCOffset(handle, i, 0xAAAA); + } + } + + if( ret != 0 ) { printf("!!!!!!!! set channels error.\n");} + + AutoSetDPPEventAggregation(); + + if( ch >= 0 ){ + isSettingFilledinMemeory = false; + usleep(1000*300); + ReadAllSettingsFromBoard(); + } + + return ret; +} + int Digitizer::ProgramBoard_PSD(){ + DebugPrint("%s", "Digitizer"); printf("===== Digitizer::%s\n", __func__); //ret = CAEN_DGTZ_Reset(handle); Reset(); - //ret = CAEN_DGTZ_WriteRegister(handle, DPP::BoardConfiguration, 0x0F0115); /// has Extra2, dual trace, input and CFD - ret = CAEN_DGTZ_WriteRegister(handle, DPP::BoardConfiguration, 0x0E0115); /// has Extra2, no trace - - ret = CAEN_DGTZ_SetAcquisitionMode(handle, CAEN_DGTZ_SW_CONTROLLED); /// software command - ret |= CAEN_DGTZ_SetIOLevel(handle, CAEN_DGTZ_IOLevel_NIM); - ret |= CAEN_DGTZ_SetExtTriggerInputMode(handle, CAEN_DGTZ_TRGMODE_ACQ_ONLY); - - ret |= CAEN_DGTZ_SetChannelEnableMask(handle, 0xFFFF); - - ret |= CAEN_DGTZ_SetChannelDCOffset(handle, 0x0, 0xAAAA); - ret |= CAEN_DGTZ_SetChannelDCOffset(handle, 0x1, 0xAAAA); - ret |= CAEN_DGTZ_SetChannelDCOffset(handle, 0x2, 0xAAAA); - ret |= CAEN_DGTZ_SetChannelDCOffset(handle, 0x3, 0xAAAA); - ret |= CAEN_DGTZ_SetChannelDCOffset(handle, 0x4, 0xAAAA); - ret |= CAEN_DGTZ_SetChannelDCOffset(handle, 0x5, 0xAAAA); - ret |= CAEN_DGTZ_SetChannelDCOffset(handle, 0x6, 0xAAAA); - ret |= CAEN_DGTZ_SetChannelDCOffset(handle, 0x7, 0xAAAA); - if( ModelType == ModelTypeCode::VME ){ - ret |= CAEN_DGTZ_SetChannelDCOffset(handle, 0x8, 0xAAAA); - ret |= CAEN_DGTZ_SetChannelDCOffset(handle, 0x9, 0xAAAA); - ret |= CAEN_DGTZ_SetChannelDCOffset(handle, 0xA, 0xAAAA); - ret |= CAEN_DGTZ_SetChannelDCOffset(handle, 0xB, 0xAAAA); - ret |= CAEN_DGTZ_SetChannelDCOffset(handle, 0xC, 0xAAAA); - ret |= CAEN_DGTZ_SetChannelDCOffset(handle, 0xD, 0xAAAA); - ret |= CAEN_DGTZ_SetChannelDCOffset(handle, 0xE, 0xAAAA); - ret |= CAEN_DGTZ_SetChannelDCOffset(handle, 0xF, 0xAAAA); - } - - ret |= CAEN_DGTZ_WriteRegister(handle, (uint32_t)(DPP::PSD::DPPAlgorithmControl2_G) + 0x7000 , 0x00000200 ); // use fine time - - ret |= CAEN_DGTZ_WriteRegister(handle, (uint32_t)(DPP::DPPAlgorithmControl) + 0x7000 , 0x00100003 ); // baseline 16 sample, 320fC - - ret |= CAEN_DGTZ_WriteRegister(handle, (uint32_t)(DPP::PSD::TriggerThreshold) + 0x7000 , 100 ); - - ret |= CAEN_DGTZ_WriteRegister(handle, (uint32_t)(DPP::PreTrigger) + 0x7000 , 20 ); - ret |= CAEN_DGTZ_WriteRegister(handle, (uint32_t)(DPP::RecordLength_G) + 0x7000 , 80 ); - - ret |= CAEN_DGTZ_WriteRegister(handle, (uint32_t)(DPP::PSD::ShortGateWidth) + 0x7000 , 32 ); - ret |= CAEN_DGTZ_WriteRegister(handle, (uint32_t)(DPP::PSD::LongGateWidth) + 0x7000 , 64 ); - ret |= CAEN_DGTZ_WriteRegister(handle, (uint32_t)(DPP::PSD::GateOffset) + 0x7000 , 19 ); - - if( ret != 0 ) { printf("!!!!!!!! set channels error.\n");} - + //*========================== Board /// change address 0xEF08 (5 bits), this will reflected in the 2nd word of the Board Agg. header. ret = CAEN_DGTZ_WriteRegister(handle, DPP::BoardID, (DPPType & 0xF)); //WriteRegister(DPP::BoardID, (DPPType & 0xF)); - AutoSetDPPEventAggregation(); + //ret = CAEN_DGTZ_WriteRegister(handle, DPP::BoardConfiguration, 0x0F0115); /// has Extra2, dual trace, input and CFD + ret |= CAEN_DGTZ_WriteRegister(handle, DPP::BoardConfiguration, 0x0E0115); /// has Extra2, no trace + ret |= CAEN_DGTZ_SetAcquisitionMode(handle, CAEN_DGTZ_SW_CONTROLLED); /// software command + ret |= CAEN_DGTZ_SetIOLevel(handle, CAEN_DGTZ_IOLevel_NIM); + ret |= CAEN_DGTZ_SetExtTriggerInputMode(handle, CAEN_DGTZ_TRGMODE_ACQ_ONLY); + ret |= CAEN_DGTZ_WriteRegister(handle, (int32_t)(DPP::GlobalTriggerMask), 0x0); + ret |= CAEN_DGTZ_WriteRegister(handle, (int32_t)(DPP::FrontPanelTRGOUTEnableMask), 0x0); + + ret |= CAEN_DGTZ_SetChannelEnableMask(handle, 0xFFFF); + + //*========================== Group + ProgramChannel_PSD(-1); isSettingFilledinMemeory = false; /// unlock the ReadAllSettingsFromBoard(); - usleep(1000*300); - ReadAllSettingsFromBoard(); + + return ret; +} + +int Digitizer::ProgramChannel_PSD(short ch){ + DebugPrint("%s", "Digitizer"); + printf("===== Digitizer::%s|ch:%d\n", __func__,ch); + + uint32_t channel = (ch << 8); + if( ch < 0 ) channel = 0x7000; + uint32_t address = (ch << 8); + + address = channel + DPP::PSD::DPPAlgorithmControl2_G; ret = CAEN_DGTZ_WriteRegister(handle, address, 0x00000200 ); // use fine time + address = channel + DPP::DPPAlgorithmControl; ret |= CAEN_DGTZ_WriteRegister(handle, address, 0x00100003 ); // baseline 16 sample, 320fC + address = channel + DPP::PSD::TriggerThreshold; ret |= CAEN_DGTZ_WriteRegister(handle, address, 100 ); + address = channel + DPP::PreTrigger; ret |= CAEN_DGTZ_WriteRegister(handle, address, 20 ); + address = channel + DPP::RecordLength_G; ret |= CAEN_DGTZ_WriteRegister(handle, address, 80 ); + address = channel + DPP::PSD::ShortGateWidth; ret |= CAEN_DGTZ_WriteRegister(handle, address, 32 ); + address = channel + DPP::PSD::LongGateWidth; ret |= CAEN_DGTZ_WriteRegister(handle, address, 64 ); + address = channel + DPP::PSD::GateOffset; ret |= CAEN_DGTZ_WriteRegister(handle, address, 19 ); + + if( ch >= 0 ) { + ret |= CAEN_DGTZ_SetChannelDCOffset(handle, ch, 0xAAAA); + }else{ + for( int i = 0; i < NumRegChannel; i ++ ){ + ret |= CAEN_DGTZ_SetChannelDCOffset(handle, i, 0xAAAA); + } + } + + if( ret != 0 ) { printf("!!!!!!!! set channels error.\n");} + + AutoSetDPPEventAggregation(); + + if( ch >= 0 ){ + isSettingFilledinMemeory = false; + usleep(1000*300); + ReadAllSettingsFromBoard(); + } + return ret; } int Digitizer::ProgramBoard_QDC(){ + DebugPrint("%s", "Digitizer"); printf("===== Digitizer::%s\n", __func__); Reset(); int ret = 0; + //*========================== Board + /// change address 0xEF08 (5 bits), this will reflected in the 2nd word of the Board Agg. header. + ret = CAEN_DGTZ_WriteRegister(handle, DPP::BoardID, (DPPType & 0xF)); + //WriteRegister(DPP::BoardID, (DPPType & 0xF)); + //WriteRegister(DPP::QDC::NumberEventsPerAggregate, 0x10, -1); WriteRegister(DPP::QDC::RecordLength_W, 16, -1); // 128 sample = 2048 ns - WriteRegister(DPP::QDC::PreTrigger, 60, -1); // at 60 sample = 960 ns - - WriteRegister(DPP::QDC::GateWidth, 100/16, -1); - WriteRegister(DPP::QDC::GateOffset, 0, -1); - WriteRegister(DPP::QDC::FixedBaseline, 0, -1); - - //WriteRegister(DPP::QDC::DPPAlgorithmControl, 0x300112); // with test pulse, positive - //WriteRegister(DPP::QDC::DPPAlgorithmControl, 0x300102); // No test pulse, positive - WriteRegister(DPP::QDC::DPPAlgorithmControl, 0x310102); // No test pulse, negative - - WriteRegister(DPP::QDC::TriggerHoldOffWidth, 100/16, -1); - WriteRegister(DPP::QDC::TRGOUTWidth, 100/16, -1); - //WriteRegister(DPP::QDC::OverThresholdWidth, 100/16, -1); - WriteRegister(DPP::QDC::SubChannelMask, 0xFF, -1); - - WriteRegister(DPP::QDC::DCOffset, 0xAAAA, -1); - - WriteRegister(DPP::QDC::TriggerThreshold_sub0, 100, -1); - WriteRegister(DPP::QDC::TriggerThreshold_sub1, 100, -1); - WriteRegister(DPP::QDC::TriggerThreshold_sub2, 100, -1); - WriteRegister(DPP::QDC::TriggerThreshold_sub3, 100, -1); - WriteRegister(DPP::QDC::TriggerThreshold_sub4, 100, -1); - WriteRegister(DPP::QDC::TriggerThreshold_sub5, 100, -1); - WriteRegister(DPP::QDC::TriggerThreshold_sub6, 100, -1); - WriteRegister(DPP::QDC::TriggerThreshold_sub7, 100, -1); - WriteRegister(DPP::BoardConfiguration, 0xE0110); //WriteRegister(DPP::AggregateOrganization, 0x0); //WriteRegister(DPP::MaxAggregatePerBlockTransfer, 100); @@ -512,18 +504,55 @@ int Digitizer::ProgramBoard_QDC(){ WriteRegister(DPP::FrontPanelIOControl, 0x0); WriteRegister(DPP::QDC::GroupEnableMask, 0xFF); - /// change address 0xEF08 (5 bits), this will reflected in the 2nd word of the Board Agg. header. - ret = CAEN_DGTZ_WriteRegister(handle, DPP::BoardID, (DPPType & 0xF)); - //WriteRegister(DPP::BoardID, (DPPType & 0xF)); + //*========================== Group + ProgramChannel_QDC(-1); + + isSettingFilledinMemeory = false; /// unlock the ReadAllSettingsFromBoard(); + usleep(1000*300); + ReadAllSettingsFromBoard(); + + return ret; + +} + +int Digitizer::ProgramChannel_QDC(short group){ + + printf("===== Digitizer::%s|ch:%d\n", __func__,group); + + WriteRegister(DPP::QDC::PreTrigger, 60, group); // at 60 sample = 960 ns + WriteRegister(DPP::QDC::GateWidth, 100/16, group); + WriteRegister(DPP::QDC::GateOffset, 0, group); + WriteRegister(DPP::QDC::FixedBaseline, 0, group); + + //WriteRegister(DPP::QDC::DPPAlgorithmControl, 0x300112); // with test pulse, positive + //WriteRegister(DPP::QDC::DPPAlgorithmControl, 0x300102); // No test pulse, positive + WriteRegister(DPP::QDC::DPPAlgorithmControl, 0x310102); // No test pulse, negative + + WriteRegister(DPP::QDC::TriggerHoldOffWidth, 100/16, group); + WriteRegister(DPP::QDC::TRGOUTWidth, 100/16, group); + //WriteRegister(DPP::QDC::OverThresholdWidth, 100/16, group); + WriteRegister(DPP::QDC::SubChannelMask, 0xFF, group); + + WriteRegister(DPP::QDC::DCOffset, 0xAAAA, group); + + WriteRegister(DPP::QDC::TriggerThreshold_sub0, 100, group); + WriteRegister(DPP::QDC::TriggerThreshold_sub1, 100, group); + WriteRegister(DPP::QDC::TriggerThreshold_sub2, 100, group); + WriteRegister(DPP::QDC::TriggerThreshold_sub3, 100, group); + WriteRegister(DPP::QDC::TriggerThreshold_sub4, 100, group); + WriteRegister(DPP::QDC::TriggerThreshold_sub5, 100, group); + WriteRegister(DPP::QDC::TriggerThreshold_sub6, 100, group); + WriteRegister(DPP::QDC::TriggerThreshold_sub7, 100, group); AutoSetDPPEventAggregation(); - isSettingFilledinMemeory = false; /// unlock the ReadAllSettingsFromBoard(); + if( group >= 0 ){ + isSettingFilledinMemeory = false; + usleep(1000*300); + ReadAllSettingsFromBoard(); + } - usleep(1000*300); - ReadAllSettingsFromBoard(); return ret; - } //========================================================= ACQ control diff --git a/ClassDigitizer.h b/ClassDigitizer.h index 7d2ef7e..5340d26 100644 --- a/ClassDigitizer.h +++ b/ClassDigitizer.h @@ -73,6 +73,10 @@ class Digitizer{ int ProgramBoard_PSD() ; int ProgramBoard_QDC() ; + int ProgramChannel_PHA(short ch) ; /// program a default PHA Channel for Si-detector, ch = -1 for all channel + int ProgramChannel_PSD(short ch) ; /// program a default PSD Channel for Si-detector, ch = -1 for all channel + int ProgramChannel_QDC(short group) ; /// program a default QDC group for Si-detector, ch = -1 for all group + public: Digitizer(); /// no digitizer open Digitizer(int boardID, int portID = 0, bool program = false, bool verbose = false); -- 2.34.1 From c1f223532c4dff108324a002929b473dcd250f81 Mon Sep 17 00:00:00 2001 From: "Ryan@SOLARIS_testStation" Date: Fri, 1 Nov 2024 17:03:10 -0400 Subject: [PATCH 32/35] added a button on the channel setting to set default channel settings for Si-detector --- ClassDigitizer.cpp | 8 +++++++ ClassDigitizer.h | 1 + DigiSettingsPanel.cpp | 50 +++++++++++++++++++++++++++++++++---------- DigiSettingsPanel.h | 1 + 4 files changed, 49 insertions(+), 11 deletions(-) diff --git a/ClassDigitizer.cpp b/ClassDigitizer.cpp index 34425da..80570d1 100644 --- a/ClassDigitizer.cpp +++ b/ClassDigitizer.cpp @@ -326,6 +326,14 @@ void Digitizer::ProgramBoard(){ if( DPPType == DPPTypeCode::DPP_QDC_CODE ) ProgramBoard_QDC(); } +void Digitizer::ProgramChannel(short chOrGroup){ + if( softwareDisable ) return; + if( AcqRun ) return; + if( DPPType == DPPTypeCode::DPP_PHA_CODE ) ProgramChannel_PHA(chOrGroup); + if( DPPType == DPPTypeCode::DPP_PSD_CODE ) ProgramChannel_PSD(chOrGroup); + if( DPPType == DPPTypeCode::DPP_QDC_CODE ) ProgramChannel_QDC(chOrGroup); +} + int Digitizer::ProgramBoard_PHA(){ DebugPrint("%s", "Digitizer"); printf("===== Digitizer::%s\n", __func__); diff --git a/ClassDigitizer.h b/ClassDigitizer.h index 5340d26..af10da9 100644 --- a/ClassDigitizer.h +++ b/ClassDigitizer.h @@ -99,6 +99,7 @@ class Digitizer{ void PrintBoard(); void ProgramBoard(); + void ProgramChannel(short chOrGroup); void AutoSetDPPEventAggregation(); diff --git a/DigiSettingsPanel.cpp b/DigiSettingsPanel.cpp index e3f48af..0377d5a 100644 --- a/DigiSettingsPanel.cpp +++ b/DigiSettingsPanel.cpp @@ -1562,12 +1562,13 @@ void DigiSettingsPanel::SetUpChannel_PHA(){ QWidget * jaja = new QWidget(this); allSettingLayout->addWidget(jaja); - QHBoxLayout * papa = new QHBoxLayout(jaja); - papa->setAlignment(Qt::AlignLeft); const unsigned short numChannel = digi[ID]->GetNumRegChannels(); {//^============================== Channel selection + QHBoxLayout * papa = new QHBoxLayout(jaja); + papa->setAlignment(Qt::AlignLeft); + QLabel * lbChSel = new QLabel ("Channel : ", this); lbChSel->setAlignment(Qt::AlignCenter | Qt::AlignRight); papa->addWidget(lbChSel); @@ -1580,6 +1581,16 @@ void DigiSettingsPanel::SetUpChannel_PHA(){ connect(chSelection[ID], &RComboBox::currentIndexChanged, this, [=](){ SyncAllChannelsTab_PHA(); }); + + bnProgramChannel[ID] = new QPushButton("Program Default Channel Settings",this); + papa->addWidget(bnProgramChannel[ID]); + connect(bnProgramChannel[ID], &QPushButton::clicked, this, [=](){ + short ch = chSelection[ID]->currentData().toInt(); + digi[ID]->ProgramChannel(ch); + digi[ID]->ReadAllSettingsFromBoard(true); + UpdatePanelFromMemory(); + emit UpdateOtherPanels(); + }); } {//*========================= input @@ -2011,12 +2022,12 @@ void DigiSettingsPanel::SetUpChannel_PSD(){ QWidget * jaja = new QWidget(this); allSettingLayout->addWidget(jaja); - QHBoxLayout * papa = new QHBoxLayout(jaja); - papa->setAlignment(Qt::AlignLeft); - const unsigned short numChannel = digi[ID]->GetNumRegChannels(); {//^============================== Channel selection + QHBoxLayout * papa = new QHBoxLayout(jaja); + papa->setAlignment(Qt::AlignLeft); + QLabel * lbChSel = new QLabel ("Ch : ", this); lbChSel->setAlignment(Qt::AlignCenter | Qt::AlignRight); papa->addWidget(lbChSel); @@ -2029,6 +2040,16 @@ void DigiSettingsPanel::SetUpChannel_PSD(){ connect(chSelection[ID], &RComboBox::currentIndexChanged, this, [=](){ SyncAllChannelsTab_PSD(); }); + + bnProgramChannel[ID] = new QPushButton("Program Default Channel Settings",this); + papa->addWidget(bnProgramChannel[ID]); + connect(bnProgramChannel[ID], &QPushButton::clicked, this, [=](){ + short ch = chSelection[ID]->currentData().toInt(); + digi[ID]->ProgramChannel(ch); + digi[ID]->ReadAllSettingsFromBoard(true); + UpdatePanelFromMemory(); + emit UpdateOtherPanels(); + }); } {//*=============== input @@ -2595,12 +2616,12 @@ void DigiSettingsPanel::SetUpChannel_QDC(){ QWidget * jaja = new QWidget(this); allSettingLayout->addWidget(jaja); - QHBoxLayout * papa = new QHBoxLayout(jaja); - papa->setAlignment(Qt::AlignLeft); - const unsigned short numGroup = digi[ID]->GetNumRegChannels(); {//^============================== Group selection + QHBoxLayout * papa = new QHBoxLayout(jaja); + papa->setAlignment(Qt::AlignLeft); + QLabel * lbChSel = new QLabel ("Group : ", this); lbChSel->setAlignment(Qt::AlignCenter | Qt::AlignRight); papa->addWidget(lbChSel); @@ -2612,14 +2633,21 @@ void DigiSettingsPanel::SetUpChannel_QDC(){ connect(chSelection[ID], &RComboBox::currentIndexChanged, this, [=](){ SyncAllChannelsTab_QDC(); - int grpID = chSelection[ID]->currentIndex() - 1; - for( int i = 0; i < 8; i ++){ lbSubCh[ID][i] ->setText((grpID == -1 ? "Sub-Ch:" : "Ch:" )+ QString::number(grpID < 0 ? i : grpID*8 + i)); lbSubCh2[ID][i]->setText((grpID == -1 ? "Sub-Ch:" : "Ch:" )+ QString::number(grpID < 0 ? i : grpID*8 + i)); - } + } + }); + bnProgramChannel[ID] = new QPushButton("Program Default Channel Settings",this); + papa->addWidget(bnProgramChannel[ID]); + connect(bnProgramChannel[ID], &QPushButton::clicked, this, [=](){ + short group = chSelection[ID]->currentData().toInt(); + digi[ID]->ProgramChannel(group); + digi[ID]->ReadAllSettingsFromBoard(true); + UpdatePanelFromMemory(); + emit UpdateOtherPanels(); }); } diff --git a/DigiSettingsPanel.h b/DigiSettingsPanel.h index 779000c..80f6c06 100644 --- a/DigiSettingsPanel.h +++ b/DigiSettingsPanel.h @@ -198,6 +198,7 @@ private: QTabWidget * chTab; RComboBox * chSelection[MaxNDigitizer]; + QPushButton * bnProgramChannel[MaxNDigitizer]; //----------- common for PHA and PSD RSpinBox * sbRecordLength[MaxNDigitizer][MaxRegChannel + 1]; -- 2.34.1 From d3f97358e2e1ad3d9f969459898fe90eece52b20 Mon Sep 17 00:00:00 2001 From: "Ryan@SOLARIS_testStation" Date: Thu, 21 Nov 2024 18:21:32 -0500 Subject: [PATCH 33/35] QDC, Add the OverThresholdWidth setting, but only for ROC > 4.15 and AMC > 135.15 --- ClassDigitizer.cpp | 30 +++++++++++++++++++++++++-- ClassDigitizer.h | 2 ++ DigiSettingsPanel.cpp | 47 ++++++++++++++++++++++++++++++++++--------- DigiSettingsPanel.h | 4 ++-- RegisterAddress.h | 6 +++--- 5 files changed, 72 insertions(+), 17 deletions(-) diff --git a/ClassDigitizer.cpp b/ClassDigitizer.cpp index 80570d1..f15514e 100644 --- a/ClassDigitizer.cpp +++ b/ClassDigitizer.cpp @@ -142,8 +142,31 @@ int Digitizer::OpenDigitizer(int boardID, int portID, bool program, bool verbose NCoupledCh = NumRegChannel; isInputChEqRegCh = false; ModelType = ModelTypeCode::VME; - tick2ns = 16.0; break; ///ns -> 62.5 MSamples/s - } + tick2ns = 16.0; ///ns -> 62.5 MSamples/s + + std::string ROC = BoardInfo.ROC_FirmwareRel; + std::string AMC = BoardInfo.AMC_FirmwareRel; + + std::size_t pos = ROC.find(" - "); + std::string versionROCStr = (pos != std::string::npos) ? ROC.substr(0, pos) : ""; + pos = AMC.find(" - "); + std::string versionAMCStr = (pos != std::string::npos) ? AMC.substr(0, pos) : ""; + + double versionROC = 0.0; + double versionAMC = 0.0; + if (!versionROCStr.empty()) versionROC = std::stod(versionROCStr); + if (!versionAMCStr.empty()) versionAMC = std::stod(versionAMCStr); + + printf(" QDC ROC version : %.2f \n", versionROC); + printf(" QDC AMC version : %.2f \n", versionAMC); + if( versionROC <= 4.25 || versionAMC <= 135.15 ){ + printf(" QDC ROC or AMC version not support OverThreshold Width.\n"); + hasOverThresholdWidth = false; + }else{ + hasOverThresholdWidth = true; + } + + }; break; default : tick2ns = 4.0; break; } @@ -777,6 +800,7 @@ void Digitizer::WriteRegister (Reg registerAddress, uint32_t value, int ch, bool } if( registerAddress.GetRWType() == RW::ReadONLY ) return; + if( !hasOverThresholdWidth && registerAddress == DPP::QDC::OverThresholdWidth ) return ; ret = CAEN_DGTZ_WriteRegister(handle, registerAddress.ActualAddress(ch), value); @@ -821,6 +845,8 @@ uint32_t Digitizer::ReadRegister(Reg registerAddress, unsigned short ch, bool is if( registerAddress.GetRWType() == RW::WriteONLY ) return 0; // if( registerAddress == DPP::QDC::RecordLength_W ) return 0; + if( !hasOverThresholdWidth && registerAddress == DPP::QDC::OverThresholdWidth ) return 0; + ret = CAEN_DGTZ_ReadRegister(handle, registerAddress.ActualAddress(ch), &returnData); if( ret == 0 && isSave2MemAndFile && !AcqRun) { diff --git a/ClassDigitizer.h b/ClassDigitizer.h index af10da9..36bc628 100644 --- a/ClassDigitizer.h +++ b/ClassDigitizer.h @@ -60,6 +60,7 @@ class Digitizer{ bool isSettingFileExist; /// bool isSettingFileUpdate; bool isSettingFilledinMemeory; /// false for disabled ReadAllSettingFromBoard() + bool hasOverThresholdWidth; /// for QDC unsigned int setting[SETTINGSIZE]; /// Setting, 4bytes x 2048 = 8192 bytes //^-------- other protected functions @@ -152,6 +153,7 @@ class Digitizer{ int GetErrorCode() const {return ret;} unsigned int GetChMemSizekSample() const {return MemorySizekSample;} std::string GetFamilyName() const {return familyName;} + bool HasOverThresholdWidth_QDC() const {return hasOverThresholdWidth;} //^================ Setting Reg FindRegister(uint32_t address); diff --git a/DigiSettingsPanel.cpp b/DigiSettingsPanel.cpp index 0377d5a..0c66b11 100644 --- a/DigiSettingsPanel.cpp +++ b/DigiSettingsPanel.cpp @@ -2760,13 +2760,22 @@ void DigiSettingsPanel::SetUpChannel_QDC(){ SetUpCheckBox(chkDisableSelfTrigger[ID][numGroup], "Disable Self Trigger ", triggerLayout, 0, 1, DPP::QDC::DPPAlgorithmControl, DPP::QDC::Bit_DPPAlgorithmControl::DisableSelfTrigger); SetUpCheckBox(chkDisableTriggerHysteresis[ID][numGroup], "Disbale Trig. Hysteresis ", triggerLayout, 2, 1, DPP::QDC::DPPAlgorithmControl, DPP::QDC::Bit_DPPAlgorithmControl::DisableTriggerHysteresis, -1, 2); + SetUpComboBoxBit(cbTrigMode[ID][numGroup], "Trig. Mode : ", triggerLayout, 0, 2, DPP::QDC::Bit_DPPAlgorithmControl::ListTrigMode, DPP::QDC::DPPAlgorithmControl, DPP::QDC::Bit_DPPAlgorithmControl::TriggerMode); SetUpSpinBox(sbTriggerHoldOff[ID][numGroup], "Trig. Holdoff [ns] : ", triggerLayout, 2, 2, DPP::QDC::TriggerHoldOffWidth); SetUpSpinBox(sbShapedTrigWidth[ID][numGroup], "Trig. Out Width [ns] : ", triggerLayout, 3, 2, DPP::QDC::TRGOUTWidth); + + int rowID = 4; + if( digi[ID]->HasOverThresholdWidth_QDC() ){ + SetUpCheckBox(chkOverthreshold[ID][numGroup], "Enable OverThreshold Width ", triggerLayout, rowID, 1, DPP::QDC::DPPAlgorithmControl, DPP::QDC::Bit_DPPAlgorithmControl::OverThresholdWitdhEnable); + SetUpSpinBox(sbOverThresholdWidth[ID][numGroup], "OverThreshold Width [ns] :", triggerLayout, rowID, 2, DPP::QDC::OverThresholdWidth); + rowID ++; + } + /// Trigger Threshold QGroupBox * widget = new QGroupBox("Threshold [LSB]", triggerBox); - triggerLayout->addWidget(widget, 4, 0, 1, 4); + triggerLayout->addWidget(widget, rowID, 0, 1, 4); QGridLayout * dcLayout = new QGridLayout(widget); dcLayout->setSpacing(2); @@ -3025,7 +3034,7 @@ void DigiSettingsPanel::SetUpChannel_QDC(){ QTabWidget * trigTab = new QTabWidget(this); trigLayout->addWidget(trigTab); - QStringList tabName = {"Common Settings", "Threshold", "Others"}; + QStringList tabName = {"Common Settings", "Threshold", "OverThreshold Width", "Others"}; const int nTab = tabName.count(); @@ -3105,6 +3114,20 @@ void DigiSettingsPanel::SetUpChannel_QDC(){ } if( i == 2 ){ + + if( digi[ID]->HasOverThresholdWidth_QDC() ){ + if( ch == 0 ){ + QLabel * lb0 = new QLabel("OverThreshold Width [ns]", this); lb0->setAlignment(Qt::AlignHCenter); tabLayout->addWidget(lb0, 0, 4); + } + SetUpCheckBox(chkOverthreshold[ID][ch], "Enable OverThreshold Width ", tabLayout, ch+1, 1, DPP::QDC::DPPAlgorithmControl, DPP::QDC::Bit_DPPAlgorithmControl::OverThresholdWitdhEnable, ch); + SetUpSpinBox(sbOverThresholdWidth[ID][ch], "", tabLayout, ch+1, 3, DPP::QDC::OverThresholdWidth, ch); + }else{ + QLabel * lb0 = new QLabel("OverThreshold Width not supported.", this); lb0->setAlignment(Qt::AlignHCenter); tabLayout->addWidget(lb0, 0, 1); + } + + } + + if( i == 3 ){ SetUpCheckBox(chkDisableSelfTrigger[ID][ch], "Disable Self Trigger ", tabLayout, ch+1, 1, DPP::QDC::DPPAlgorithmControl, DPP::QDC::Bit_DPPAlgorithmControl::DisableSelfTrigger, ch); SetUpCheckBox(chkDisableTriggerHysteresis[ID][ch], "Disbale Trig. Hysteresis ", tabLayout, ch+1, 3, DPP::QDC::DPPAlgorithmControl, DPP::QDC::Bit_DPPAlgorithmControl::DisableTriggerHysteresis, ch, 2); } @@ -3113,7 +3136,7 @@ void DigiSettingsPanel::SetUpChannel_QDC(){ } } -{//^================================== QDC + {//^================================== QDC QVBoxLayout *trapLayout = new QVBoxLayout(chTrap); @@ -3172,7 +3195,7 @@ void DigiSettingsPanel::SetUpChannel_QDC(){ } } -{//^======================================== Others + {//^======================================== Others QVBoxLayout *otherLayout = new QVBoxLayout(chOthers); QTabWidget * othersTab = new QTabWidget(this); @@ -3972,22 +3995,23 @@ void DigiSettingsPanel::SyncAllChannelsTab_QDC(){ DebugPrint("%s", "DigiSettingsPanel"); if( !enableSignalSlot ) return; - // SyncSpinBox(sbRecordLength); SyncSpinBox(sbPreTrigger); SyncSpinBox(sbDCOffset); SyncSpinBox(sbTriggerHoldOff); SyncSpinBox(sbShapedTrigWidth); - // SyncSpinBox(sbNumEventAgg); SyncSpinBox(sbShortGate); SyncSpinBox(sbGateOffset); - //SyncSpinBox(sbOverThresholdWidth); SyncCheckBox(chkDisableSelfTrigger); SyncCheckBox(chkDisableTriggerHysteresis); - //SyncCheckBox(chkOverthreshold); SyncCheckBox(chkChargePedestal); SyncCheckBox(chkTestPule); + if( digi[ID]->HasOverThresholdWidth_QDC() ){ + SyncSpinBox(sbOverThresholdWidth); + SyncCheckBox(chkOverthreshold); + } + SyncComboBox(cbPolarity); SyncComboBox(cbRCCR2Smoothing); SyncComboBox(cbBaseLineAvg); @@ -4081,7 +4105,7 @@ void DigiSettingsPanel::UpdateSettings_QDC(){ UpdateSpinBox(sbShapedTrigWidth[ID][grp], DPP::QDC::TRGOUTWidth, grp); UpdateSpinBox(sbShortGate[ID][grp], DPP::QDC::GateWidth, grp); UpdateSpinBox(sbGateOffset[ID][grp], DPP::QDC::GateOffset, grp); - //UpdateSpinBox(sbOverThresholdWidth[ID][grp], DPP::QDC::OverThresholdWidth, grp); + uint32_t subChMask = digi[ID]->GetSettingFromMemory(DPP::QDC::SubChannelMask, grp); @@ -4104,10 +4128,13 @@ void DigiSettingsPanel::UpdateSettings_QDC(){ chkDisableSelfTrigger[ID][grp]->setChecked( Digitizer::ExtractBits(dpp, DPP::QDC::Bit_DPPAlgorithmControl::DisableSelfTrigger) ); chkDisableTriggerHysteresis[ID][grp]->setChecked( Digitizer::ExtractBits(dpp, DPP::QDC::Bit_DPPAlgorithmControl::DisableTriggerHysteresis) ); - //chkOverthreshold[ID][grp]->setChecked( Digitizer::ExtractBits(dpp, DPP::QDC::Bit_DPPAlgorithmControl::OverThresholdWitdhEnable) ); chkChargePedestal[ID][grp]->setChecked( Digitizer::ExtractBits(dpp, DPP::QDC::Bit_DPPAlgorithmControl::ChargePedestal)); chkTestPule[ID][grp]->setChecked( Digitizer::ExtractBits(dpp, DPP::QDC::Bit_DPPAlgorithmControl::InternalTestPulse)); + if( digi[ID]->HasOverThresholdWidth_QDC() ) { + UpdateSpinBox(sbOverThresholdWidth[ID][grp], DPP::QDC::OverThresholdWidth, grp); + chkOverthreshold[ID][grp]->setChecked( Digitizer::ExtractBits(dpp, DPP::QDC::Bit_DPPAlgorithmControl::OverThresholdWitdhEnable) ); + } uint32_t dcOffSet_low = digi[ID]->GetSettingFromMemory(DPP::QDC::DCOffset_LowCh, grp); diff --git a/DigiSettingsPanel.h b/DigiSettingsPanel.h index 80f6c06..407aabd 100644 --- a/DigiSettingsPanel.h +++ b/DigiSettingsPanel.h @@ -294,8 +294,8 @@ private: //Trig Hold off with -> sbTriggerHoldOff //Trig out width -> sbShapedTrigWidth - //QCheckBox * chkOverthreshold[MaxNDigitizer][MaxRegChannel+1]; //TODO need firmware version 4.25 & 135.17 - //RSpinBox * sbOverThresholdWidth[MaxNDigitizer][MaxRegChannel + 1]; + QCheckBox * chkOverthreshold[MaxNDigitizer][MaxRegChannel+1]; //TODO need firmware version 4.25 & 135.17 + RSpinBox * sbOverThresholdWidth[MaxNDigitizer][MaxRegChannel + 1]; QPushButton * pbSubChMask[MaxNDigitizer][MaxRegChannel+1][8]; RSpinBox * sbSubChOffset[MaxNDigitizer][MaxRegChannel + 1][8]; RSpinBox * sbSubChThreshold[MaxNDigitizer][MaxRegChannel + 1][8]; diff --git a/RegisterAddress.h b/RegisterAddress.h index 905257b..9be71e9 100644 --- a/RegisterAddress.h +++ b/RegisterAddress.h @@ -795,7 +795,7 @@ namespace DPP { const Reg DPPAlgorithmControl ("DPPAlgorithmControl" , 0x1040, RW::ReadWrite, false, {}); /// R/W const Reg TriggerHoldOffWidth ("Trigger Hold-off width" , 0x1074, RW::ReadWrite, false, 0xFFFF, 1); /// R/W const Reg TRGOUTWidth ("Trigger out width" , 0x1078, RW::ReadWrite, false, 0xFFFF, 1); /// R/W - //const Reg OverThresholdWidth ("Over Threshold width" , 0x107C, RW::ReadWrite, false, 0xFFFF, 1); /// R/W // need firmware version 4.25 & 135.17 + const Reg OverThresholdWidth ("Over Threshold width" , 0x107C, RW::ReadWrite, false, 0xFFFF, 1); /// R/W // need firmware version 4.25 & 135.17 const Reg GroupStatus_R ("Group Status" , 0x1088, RW::ReadONLY, false, {}); /// R/ const Reg AMCFirmwareRevision_R ("AMC firmware version" , 0x108C, RW::ReadONLY, false, {}); /// R/ const Reg DCOffset ("DC offset" , 0x1098, RW::ReadWrite, false, 0xFFFF, -1); /// R/W @@ -821,7 +821,7 @@ namespace DPP { const std::pair ChargeSensitivity = {3, 0} ; /// length, smallest pos const std::pair InternalTestPulse = {1, 4}; const std::pair TestPulseRate = {2, 5}; - //const std::pair OverThresholdWitdhEnable = {1, 7}; ///need firmware version 4.25 & 135.17 + const std::pair OverThresholdWitdhEnable = {1, 7}; ///need firmware version 4.25 & 135.17 const std::pair ChargePedestal = {1, 8}; const std::pair InputSmoothingFactor = {3, 12}; const std::pair Polarity = {1, 16}; @@ -937,7 +937,7 @@ const std::vector RegisterChannelList_QDC = { DPP::QDC::DPPAlgorithmControl, DPP::QDC::TriggerHoldOffWidth, DPP::QDC::TRGOUTWidth, - //DPP::QDC::OverThresholdWidth, + DPP::QDC::OverThresholdWidth, DPP::QDC::GroupStatus_R, DPP::QDC::AMCFirmwareRevision_R, DPP::QDC::DCOffset, -- 2.34.1 From 770d2c5af445f413110a88e44f479a0f3a28ba44 Mon Sep 17 00:00:00 2001 From: "Ryan@SOLARIS_testStation" Date: Thu, 21 Nov 2024 18:40:07 -0500 Subject: [PATCH 34/35] I tested with QDC AMC version 135.17, the Overthreshold is working. --- ClassDigitizer.cpp | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/ClassDigitizer.cpp b/ClassDigitizer.cpp index f15514e..918c0bf 100644 --- a/ClassDigitizer.cpp +++ b/ClassDigitizer.cpp @@ -144,23 +144,23 @@ int Digitizer::OpenDigitizer(int boardID, int portID, bool program, bool verbose ModelType = ModelTypeCode::VME; tick2ns = 16.0; ///ns -> 62.5 MSamples/s - std::string ROC = BoardInfo.ROC_FirmwareRel; - std::string AMC = BoardInfo.AMC_FirmwareRel; + // std::string ROC = BoardInfo.ROC_FirmwareRel; + // std::size_t pos = ROC.find(" - "); + // std::string versionROCStr = (pos != std::string::npos) ? ROC.substr(0, pos) : ""; + // double versionROC = 0.0; + // if (!versionROCStr.empty()) versionROC = std::stod(versionROCStr); + // printf(" QDC ROC version : %.2f \n", versionROC); - std::size_t pos = ROC.find(" - "); - std::string versionROCStr = (pos != std::string::npos) ? ROC.substr(0, pos) : ""; - pos = AMC.find(" - "); + std::string AMC = BoardInfo.AMC_FirmwareRel; + std::size_t pos = AMC.find(" - "); std::string versionAMCStr = (pos != std::string::npos) ? AMC.substr(0, pos) : ""; - double versionROC = 0.0; double versionAMC = 0.0; - if (!versionROCStr.empty()) versionROC = std::stod(versionROCStr); if (!versionAMCStr.empty()) versionAMC = std::stod(versionAMCStr); - printf(" QDC ROC version : %.2f \n", versionROC); printf(" QDC AMC version : %.2f \n", versionAMC); - if( versionROC <= 4.25 || versionAMC <= 135.15 ){ - printf(" QDC ROC or AMC version not support OverThreshold Width.\n"); + if( versionAMC < 135.17 ){ + printf(" QDC AMC version not support OverThreshold Width.\n"); hasOverThresholdWidth = false; }else{ hasOverThresholdWidth = true; -- 2.34.1 From 96818dae99c79eb3032a5ebbf1c558612339e3f1 Mon Sep 17 00:00:00 2001 From: Ryan Tang Date: Sat, 7 Dec 2024 14:29:35 -0500 Subject: [PATCH 35/35] Create LICENSE --- LICENSE | 674 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 674 insertions(+) create mode 100644 LICENSE diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..f288702 --- /dev/null +++ b/LICENSE @@ -0,0 +1,674 @@ + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU General Public License is a free, copyleft license for +software and other kinds of works. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, receive +or can get the source code. And you must show them these terms so they +know their rights. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Use with the GNU Affero General Public License. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +Also add information on how to contact you by electronic and paper mail. + + If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: + + Copyright (C) + This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, your program's commands +might be different; for a GUI interface, you would use an "about box". + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU GPL, see +. + + The GNU General Public License does not permit incorporating your program +into proprietary programs. If your program is a subroutine library, you +may consider it more useful to permit linking proprietary applications with +the library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. But first, please read +. -- 2.34.1