From d246bb8dcf31d6609107459911ef1ba2c14a2e01 Mon Sep 17 00:00:00 2001 From: splitPoleDAQ Date: Tue, 20 Jun 2023 11:57:39 -0400 Subject: [PATCH] testes many things with pulser (except backward event building). All parts looks good at 10 Hz --- Analyser.cpp | 11 +- Analyser.h | 11 +- ClassData.h | 12 +- ClassDigitizer.cpp | 16 +- ClassDigitizer.h | 4 +- DigiSettingsPanel.cpp | 24 +- Histogram2D.h | 719 ++++++++++++++++++++++-------------------- MultiBuilder.cpp | 5 +- MultiBuilder.h | 9 +- RegisterAddress.h | 2 +- Scope.cpp | 36 +-- Scope.h | 2 +- SplitPoleAnalyzer.h | 61 +++- test.cpp | 4 +- test_indep.cpp | 40 +-- 15 files changed, 514 insertions(+), 442 deletions(-) diff --git a/Analyser.cpp b/Analyser.cpp index 693fee6..2df0f2e 100644 --- a/Analyser.cpp +++ b/Analyser.cpp @@ -11,6 +11,9 @@ Analyzer::Analyzer(Digitizer ** digi, unsigned int nDigi, QMainWindow * parent ) setWindowTitle("Online Analyzer"); setGeometry(0, 0, 1000, 800); + influx = nullptr; + dataBaseName = ""; + mb = new MultiBuilder(digi, nDigi); buildTimerThread = new TimingThread(this); @@ -28,7 +31,7 @@ Analyzer::Analyzer(Digitizer ** digi, unsigned int nDigi, QMainWindow * parent ) } Analyzer::~Analyzer(){ - + delete influx; delete mb; } @@ -51,15 +54,15 @@ void Analyzer::StopThread(){ -void Analyzer::BuildEvents(){ +void Analyzer::BuildEvents(bool verbose){ unsigned int nData = mb->GetNumOfDigitizer(); std::vector idList = mb->GetDigiIDList(); for( unsigned int i = 0; i < nData; i++ ) digiMTX[idList[i]].lock(); if( isBuildBackward ){ - mb->BuildEventsBackWard(0); + mb->BuildEventsBackWard(maxNumEventBuilt, verbose); }else{ - mb->BuildEvents(0, 0, 0); + mb->BuildEvents(0, 0, verbose); } for( unsigned int i = 0; i < nData; i++ ) digiMTX[idList[i]].unlock(); diff --git a/Analyser.h b/Analyser.h index 68254bb..f6fb2c5 100644 --- a/Analyser.h +++ b/Analyser.h @@ -15,8 +15,8 @@ #include "ClassDigitizer.h" #include "CustomThreads.h" #include "CustomWidgets.h" -//#include "OnlineEventBuilder.h" #include "MultiBuilder.h" +#include "influxdb.h" /************************************** @@ -46,7 +46,7 @@ public: MultiBuilder * GetEventBuilder() { return mb;} void RedefineEventBuilder(std::vector idList); - void SetBackwardBuild(bool TF) { isBuildBackward = TF;} + void SetBackwardBuild(bool TF, int maxNumEvent = 100) { isBuildBackward = TF; maxNumEventBuilt = maxNumEvent;} public slots: void StartThread(); @@ -58,9 +58,12 @@ private slots: protected: QGridLayout * layout; - void BuildEvents(); + void BuildEvents(bool verbose = false); void SetUpdateTimeInSec(double sec = 1.0) {waitTimeinSec = sec; buildTimerThread->SetWaitTimeinSec(waitTimeinSec);} + InfluxDB * influx; + std::string dataBaseName; + private: Digitizer ** digi; unsigned short nDigi; @@ -69,7 +72,9 @@ private: MultiBuilder * mb; bool isBuildBackward; + int maxNumEventBuilt; TimingThread * buildTimerThread; + }; #endif \ No newline at end of file diff --git a/ClassData.h b/ClassData.h index 515ca06..6a481d7 100644 --- a/ClassData.h +++ b/ClassData.h @@ -23,7 +23,7 @@ class Data{ int DPPType; std::string DPPTypeStr; unsigned short boardSN; - float ch2ns; /// only use in TriggerRate calculation + float tick2ns; /// only use in TriggerRate calculation unsigned int nByte; /// number of byte from read buffer uint32_t AllocatedSize; @@ -42,7 +42,7 @@ class Data{ int DataIndex[MaxNChannels]; unsigned long long Timestamp[MaxNChannels][MaxNData]; /// 47 bit - unsigned short fineTime[MaxNChannels][MaxNData]; /// 10 bits, in unit of ch2ns / 1000 = ps + unsigned short fineTime[MaxNChannels][MaxNData]; /// 10 bits, in unit of tick2ns / 1000 = ps unsigned short Energy[MaxNChannels][MaxNData]; /// 15 bit unsigned short Energy2[MaxNChannels][MaxNData]; /// 15 bit, in PSD, Energy = Qshort, Energy2 = Qlong bool PileUp[MaxNChannels][MaxNData]; /// pile up flag @@ -113,7 +113,7 @@ class Data{ //========================================== inline Data::Data(){ - ch2ns = 2.0; + tick2ns = 2.0; boardSN = 0; DPPType = V1730_DPP_PHA_CODE; DPPTypeStr = ""; @@ -414,7 +414,7 @@ inline void Data::DecodeBuffer(bool fastDecode, int verbose){ //printf("%d %d| %d %d \n", DataIndex[ch], NumEventsDecoded[ch], indexStart, DataIndex[ch] ); unsigned long long dTime = Timestamp[ch][DataIndex[ch]] - Timestamp[ch][indexStart]; - double sec = dTime * ch2ns / 1e9; + double sec = dTime * tick2ns / 1e9; TriggerRate[ch] = NumEventsDecoded[ch]/sec; NonPileUpRate[ch] = NumNonPileUpDecoded[ch]/sec; @@ -430,9 +430,9 @@ inline void Data::DecodeBuffer(bool fastDecode, int verbose){ if( calIndexes[ch][0] > -1 && calIndexes[ch][1] > -1 && nEvent > 10 ){ unsigned long long dTime = Timestamp[ch][calIndexes[ch][1]] - Timestamp[ch][calIndexes[ch][0]]; - double sec = dTime * ch2ns / 1e9; + double sec = dTime * tick2ns / 1e9; - //printf(" %10llu %10llu, %f = %f sec, rate = %f \n", Timestamp[ch][calIndexes[ch][0]], Timestamp[ch][calIndexes[ch][1]], ch2ns, sec, nEvent / sec); + //printf(" %10llu %10llu, %f = %f sec, rate = %f \n", Timestamp[ch][calIndexes[ch][0]], Timestamp[ch][calIndexes[ch][1]], tick2ns, sec, nEvent / sec); TriggerRate[ch] = nEvent / sec; diff --git a/ClassDigitizer.cpp b/ClassDigitizer.cpp index 3ea6b25..aae516e 100644 --- a/ClassDigitizer.cpp +++ b/ClassDigitizer.cpp @@ -25,7 +25,7 @@ void Digitizer::Initalization(){ ADCbits = 1; DPPType = 0; ADCFullSize = 0; - ch2ns = 0; + tick2ns = 0; BoardInfo = {}; channelMask = 0xFFFF; @@ -59,7 +59,7 @@ void Digitizer::Reset(){ void Digitizer::PrintBoard (){ printf("Connected to Model %s with handle %d using %s\n", BoardInfo.ModelName, handle, LinkType == CAEN_DGTZ_USB ? "USB" : "Optical Link"); - printf("Sampling rate : %.0f MHz = %.1f ns \n", 1000/ch2ns, ch2ns); + printf("Sampling rate : %.0f MHz = %.1f ns \n", 1000/tick2ns, tick2ns); printf("Number of Channels : %d = 0x%X\n", NChannel, channelMask); printf("SerialNumber :\e[1m\e[33m %d\e[0m\n", BoardInfo.SerialNumber); printf("DPPType : %d (%s)\n", DPPType, GetDPPString().c_str()); @@ -103,11 +103,11 @@ int Digitizer::OpenDigitizer(int boardID, int portID, bool program, bool verbose NChannel = BoardInfo.Channels; channelMask = pow(2, NChannel)-1; switch(BoardInfo.Model){ - case CAEN_DGTZ_V1730: ch2ns = 2.0; break; ///ns -> 500 MSamples/s - case CAEN_DGTZ_V1725: ch2ns = 4.0; break; ///ns -> 250 MSamples/s - default : ch2ns = 4.0; break; + case CAEN_DGTZ_V1730: tick2ns = 2.0; break; ///ns -> 500 MSamples/s + case CAEN_DGTZ_V1725: tick2ns = 4.0; break; ///ns -> 250 MSamples/s + default : tick2ns = 4.0; break; } - data->ch2ns = ch2ns; + data->tick2ns = tick2ns; data->boardSN = BoardInfo.SerialNumber; ADCbits = BoardInfo.ADC_NBits; ADCFullSize = (unsigned int)( pow(2, ADCbits) -1 ); @@ -739,8 +739,8 @@ int Digitizer::LoadSettingBinaryToMemory(std::string fileName){ if( dummy != 0 ) printf("reach the end of file (read %ld).\n", dummy); uint32_t boardInfo = GetSettingFromMemory(DPP::BoardInfo_R); - if( (boardInfo & 0xFF) == 0x0E ) ch2ns = 4.0; - if( (boardInfo & 0xFF) == 0x0B ) ch2ns = 2.0; + if( (boardInfo & 0xFF) == 0x0E ) tick2ns = 4.0; + if( (boardInfo & 0xFF) == 0x0B ) tick2ns = 2.0; ///Should seperate file<->memory, memory<->board ///ProgramSettingsToBoard(); /// do nothing if not connected. diff --git a/ClassDigitizer.h b/ClassDigitizer.h index 255e27b..3b74dcd 100644 --- a/ClassDigitizer.h +++ b/ClassDigitizer.h @@ -31,7 +31,7 @@ class Digitizer{ int ADCbits; /// ADC bit int DPPType; /// DPP verion unsigned int ADCFullSize; /// pow(2, ADCbits) - 1 - float ch2ns; /// channel to ns + float tick2ns; /// channel to ns CAEN_DGTZ_BoardInfo_t BoardInfo; //^----- adjustable parameters @@ -105,7 +105,7 @@ class Digitizer{ int GetSerialNumber() const {return BoardInfo.SerialNumber;} int GetChannelMask() { channelMask = GetSettingFromMemory(DPP::ChannelEnableMask); return channelMask;} bool GetChannelOnOff(unsigned ch) { channelMask = GetSettingFromMemory(DPP::ChannelEnableMask); return (channelMask & ( 1 << ch) );} - float GetCh2ns() const {return ch2ns;} + float GetTick2ns() const {return tick2ns;} int GetNChannels() const {return NChannel;} int GetHandle() const {return handle;} int GetDPPType() const {return DPPType;} diff --git a/DigiSettingsPanel.cpp b/DigiSettingsPanel.cpp index 526809a..a43e887 100644 --- a/DigiSettingsPanel.cpp +++ b/DigiSettingsPanel.cpp @@ -74,7 +74,7 @@ DigiSettingsPanel::DigiSettingsPanel(Digitizer ** digi, unsigned int nDigi, QStr SetUpInfo( "S/N No. ", std::to_string(digi[ID]->GetSerialNumber()), infoLayout[ID], 1, 0); SetUpInfo( "No. Ch. ", std::to_string(digi[ID]->GetNChannels()), infoLayout[ID], 1, 2); - SetUpInfo("Sampling Rate ", std::to_string((int) digi[ID]->GetCh2ns()) + " ns = " + std::to_string( (int) (1000/digi[ID]->GetCh2ns())) + " MHz" , infoLayout[ID], 1, 4); + SetUpInfo("Sampling Rate ", std::to_string((int) digi[ID]->GetTick2ns()) + " ns = " + std::to_string( (int) (1000/digi[ID]->GetTick2ns())) + " MHz" , infoLayout[ID], 1, 4); SetUpInfo("ADC bit ", std::to_string(digi[ID]->GetADCBits()), infoLayout[ID], 2, 0); SetUpInfo("ROC version ", digi[ID]->GetROCVersion(), infoLayout[ID], 2, 2); @@ -733,8 +733,8 @@ void DigiSettingsPanel::SetUpSpinBox(RSpinBox * &sb, QString label, QGridLayout sb->setSingleStep(1); sb->setMaximum(para.GetMaxBit()); }else{ - sb->setMaximum(para.GetMaxBit() * para.GetPartialStep() * digi[ID]->GetCh2ns()); - sb->setSingleStep(para.GetPartialStep() * digi[ID]->GetCh2ns()); + sb->setMaximum(para.GetMaxBit() * para.GetPartialStep() * digi[ID]->GetTick2ns()); + sb->setSingleStep(para.GetPartialStep() * digi[ID]->GetTick2ns()); } if( para == DPP::DPPAlgorithmControl ) { @@ -770,7 +770,7 @@ void DigiSettingsPanel::SetUpSpinBox(RSpinBox * &sb, QString label, QGridLayout } if( para == DPP::PSD::CFDSetting ){ - digi[ID]->SetBits(para, DPP::PSD::Bit_CFDSetting::CFDDealy, sb->value()/digi[ID]->GetCh2ns(), chID); + digi[ID]->SetBits(para, DPP::PSD::Bit_CFDSetting::CFDDealy, sb->value()/digi[ID]->GetTick2ns(), chID); UpdatePanelFromMemory(); emit UpdateOtherPanels(); return; @@ -783,7 +783,7 @@ void DigiSettingsPanel::SetUpSpinBox(RSpinBox * &sb, QString label, QGridLayout return; } - uint32_t bit = para.GetPartialStep() == -1 ? sb->value() : sb->value() / para.GetPartialStep() / digi[ID]->GetCh2ns(); + uint32_t bit = para.GetPartialStep() == -1 ? sb->value() : sb->value() / para.GetPartialStep() / digi[ID]->GetTick2ns(); digi[ID]->WriteRegister(para, bit, chID); if( para.IsCoupled() == true && chID >= 0 ) digi[ID]->WriteRegister(para, bit, chID%2 == 0 ? chID + 1 : chID - 1); @@ -964,8 +964,8 @@ void DigiSettingsPanel::SetUpGlobalTriggerMaskAndFrontPanelMask(QGridLayout * & sbGlbMajCoinWin[ID] = new RSpinBox(this); sbGlbMajCoinWin[ID]->setMinimum(0); - sbGlbMajCoinWin[ID]->setMaximum(0xF * 4 * digi[ID]->GetCh2ns() ); - sbGlbMajCoinWin[ID]->setSingleStep(4 * digi[ID]->GetCh2ns()); + sbGlbMajCoinWin[ID]->setMaximum(0xF * 4 * digi[ID]->GetTick2ns() ); + sbGlbMajCoinWin[ID]->setSingleStep(4 * digi[ID]->GetTick2ns()); maskLayout->addWidget(sbGlbMajCoinWin[ID], 1, 10); connect(sbGlbMajCoinWin[ID], &RSpinBox::valueChanged, this, [=](){ if( !enableSignalSlot ) return; @@ -982,7 +982,7 @@ void DigiSettingsPanel::SetUpGlobalTriggerMaskAndFrontPanelMask(QGridLayout * & } sbGlbMajCoinWin[ID]->setStyleSheet(""); - digi[ID]->SetBits(DPP::GlobalTriggerMask, DPP::Bit_GlobalTriggerMask::MajorCoinWin, sbGlbMajCoinWin[ID]->value() / 4 / digi[ID]->GetCh2ns(), -1); + digi[ID]->SetBits(DPP::GlobalTriggerMask, DPP::Bit_GlobalTriggerMask::MajorCoinWin, sbGlbMajCoinWin[ID]->value() / 4 / digi[ID]->GetTick2ns(), -1); }); //*============================================ @@ -2581,7 +2581,7 @@ void DigiSettingsPanel::UpdatePanelFromMemory(){ //&########################################################### void DigiSettingsPanel::UpdateSpinBox(RSpinBox * &sb, Reg para, int ch){ - int ch2ns = digi[ID]->GetCh2ns(); + int tick2ns = digi[ID]->GetTick2ns(); int pStep = para.GetPartialStep(); uint32_t value = digi[ID]->GetSettingFromMemory(para, ch); @@ -2593,7 +2593,7 @@ void DigiSettingsPanel::UpdateSpinBox(RSpinBox * &sb, Reg para, int ch){ } if( para == DPP::PSD::CFDSetting ){ - sb->setValue( ( value & DPP::PSD::CFDSetting.GetMaxBit() ) * ch2ns ); + sb->setValue( ( value & DPP::PSD::CFDSetting.GetMaxBit() ) * tick2ns ); return; } @@ -2602,9 +2602,9 @@ void DigiSettingsPanel::UpdateSpinBox(RSpinBox * &sb, Reg para, int ch){ return; } - sb->setValue( pStep > 0 ? value * pStep * ch2ns : value); + sb->setValue( pStep > 0 ? value * pStep * tick2ns : value); - //printf("%d, %s | %d %d %u, %f\n", para.GetNameChar(), ch, ch2ns, pStep, value, sb->value()); + //printf("%d, %s | %d %d %u, %f\n", para.GetNameChar(), ch, tick2ns, pStep, value, sb->value()); } diff --git a/Histogram2D.h b/Histogram2D.h index e9bfd8b..97a790e 100644 --- a/Histogram2D.h +++ b/Histogram2D.h @@ -136,143 +136,7 @@ public: } //^================= right click - if (event->button() == Qt::RightButton) { - usingMenu = true; - setSelectionRectMode(QCP::SelectionRectMode::srmNone); - - QMenu *menu = new QMenu(this); - menu->setAttribute(Qt::WA_DeleteOnClose); - - QAction * a1 = menu->addAction("UnZoom"); - QAction * a2 = menu->addAction("Clear hist."); - QAction * a3 = menu->addAction("Toggle Stat."); - QAction * a4 = menu->addAction("Rebin (clear histogram)"); - QAction * a5 = menu->addAction("Create a Cut"); - if( numCut > 0 ) { - menu->addSeparator(); - menu->addAction("Add/Edit names to Cuts"); - menu->addAction("Clear all Cuts"); - } - for( int i = 0; i < cutList.size(); i++){ - if( cutList[i].isEmpty()) continue; - QString haha = ""; - menu->addAction("Delete " + cutNameList[i] + " ["+ colorCycle[cutIDList[i]%colorCycle.count()].second+"]"); - } - - QAction *selectedAction = menu->exec(event->globalPosition().toPoint()); - - 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 ){ - for( int i = 0; i < 3; i ++ ){ - for( int j = 0; j < 3; j ++ ){ - box[i][j]->setVisible( !box[i][j]->visible()); - txt[i][j]->setVisible( !txt[i][j]->visible()); - } - } - 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 && numCut > 0 && selectedAction->text().contains("Delete ") ){ - - QString haha = selectedAction->text(); - int index1 = haha.indexOf("-"); - int index2 = haha.indexOf("["); - int cutID = haha.mid(index1+1, index2-index1-1).remove(' ').toInt(); - - removeItem(cutTextIDList[cutID]); - removePlottable(plottableIDList[cutID]); - replot(); - - numCut --; - cutList[cutID].clear(); - cutIDList[cutID] = -1; - cutTextIDList[cutID] = -1; - plottableIDList[cutID] = -1; - cutNameList[cutID] = ""; - cutEntryList[cutID] = -1; - - for( int i = cutID + 1; i < cutTextIDList.count() ; i++){ - cutTextIDList[i] --; - plottableIDList[i] --; - } - - if( numCut == 0 ){ - tempCutID = -1; - lastPlottableID = -1; - cutList.clear(); - cutIDList.clear(); - cutTextIDList.clear(); - plottableIDList.clear(); - 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; - } - - }///================= end of right click + if (event->button() == Qt::RightButton) rightMouseClickMenu(event); }); //connect( this, &QCustomPlot::mouseDoubleClick, this, [=](QMouseEvent *event){ @@ -310,134 +174,26 @@ public: connect(this, &QCustomPlot::mouseRelease, this, [=](){ - }); } //^=================================== - void Rebin(int xbin, double xmin, double xmax, int ybin, double ymin, double ymax){ - xMin = xmin; - xMax = xmax; - yMin = ymin; - yMax = ymax; - xBin = xbin; - yBin = ybin; + void Rebin(int xbin, double xmin, double xmax, int ybin, double ymin, double ymax); - colorMap->data()->clear(); - colorMap->data()->setSize(xBin, yBin); - colorMap->data()->setRange(QCPRange(xMin, xMax), QCPRange(yMin, yMax)); + void UpdatePlot(){ colorMap->rescaleDataRange(); replot(); } - for( int i = 0; i < 3; i ++){ - for( int j = 0; j < 3; j ++){ - entry[i][j] = 0; - if( txt[i][j] ) txt[i][j]->setText("0"); - } - } + void Clear(); // Clear Data and histrogram - } + void Fill(double x, double y); - void UpdatePlot(){ - colorMap->rescaleDataRange(); - //rescaleAxes(); - replot(); - } - - void Clear(){ - - for( int i = 0; i < 3; i ++){ - for( int j = 0; j < 3; j ++){ - entry[i][j] = 0; - txt[i][j]->setText("0"); - } - } - colorMap->data()->clear(); - UpdatePlot(); - } - - void Fill(double x, double y){ - if( isBusy ) return; - int xIndex, yIndex; - colorMap->data()->coordToCell(x, y, &xIndex, &yIndex); - //printf("%f, %d %d| %f, %d %d\n", x, xIndex, xBin, y, yIndex, yBin); - - int xk = 1, yk = 1; - if( xIndex < 0 ) xk = 0; - if( xIndex >= xBin ) xk = 2; - if( yIndex < 0 ) yk = 0; - if( yIndex >= yBin ) yk = 2; - entry[xk][yk] ++; - - txt[xk][yk]->setText(QString::number(entry[xk][yk])); - - if( xk == 1 && yk == 1 ) { - double value = colorMap->data()->cell(xIndex, yIndex); - colorMap->data()->setCell(xIndex, yIndex, value + 1); - - for( int i = 0; i < cutList.count(); i++){ - if( cutList[i].isEmpty() ) continue; - if( cutList[i].containsPoint(QPointF(x,y), Qt::OddEvenFill) ) cutEntryList[i] ++; - } - } - } - - void DrawCut(){ - - //The histogram is the 1st plottable. - // the lastPlottableID should be numCut+ 1 - if( lastPlottableID != numCut ){ - removePlottable(lastPlottableID); - } - - if(tempCut.size() > 0) { - QCPCurve *polygon = new QCPCurve(xAxis, yAxis); - lastPlottableID = plottableCount() - 1; - - int colorID = tempCutID% colorCycle.count(); - QPen pen(colorCycle[colorID].first); - pen.setWidth(1); - polygon->setPen(pen); - - QVector dataPoints; - for (const QPointF& point : tempCut) { - dataPoints.append(QCPCurveData(dataPoints.size(), point.x(), point.y())); - } - polygon->data()->set(dataPoints, false); - } - replot(); - - //qDebug() << "Plottable count : " << plottableCount() << ", cutList.count :" << cutList.count() << ", cutID :" << lastPlottableID; - } - - void ClearAllCuts(){ - numCut = 0; - tempCutID = -1; - lastPlottableID = -1; - cutList.clear(); - cutIDList.clear(); - for( int i = cutTextIDList.count() - 1; i >= 0 ; i--){ - if( cutTextIDList[i] < 0 ) continue; - removeItem(cutTextIDList[i]); - removePlottable(plottableIDList[i]); - } - replot(); - - cutTextIDList.clear(); - plottableIDList.clear(); - cutNameList.clear(); - cutEntryList.clear(); - } + void DrawCut(); + void ClearAllCuts(); QList GetCutList() const{return cutList;} // this list may contain empty element QList GetCutEntryList() const{ return cutEntryList;} - void PrintCutEntry() const{ - if( numCut == 0 ) return; - printf("=============== There are %d cuts.\n", numCut); - for( int i = 0; i < cutList.count(); i++){ - if( cutList[i].isEmpty() ) continue; - printf("%10s | %d \n", cutNameList[i].toStdString().c_str(), cutEntryList[i]); - } - } + QList GetCutNameList() const { return cutNameList;} + void PrintCutEntry() const; private: double xMin, xMax, yMin, yMax; @@ -470,104 +226,367 @@ private: bool isBusy; - //^======================== Right Mouse click action - void rightMouseClickRebin(){ - QDialog dialog(this); - dialog.setWindowTitle("Rebin histogram"); - - QFormLayout layout(&dialog); - - QLabel * info = new QLabel(&dialog); - info->setStyleSheet("color:red;"); - info->setText("This will also clear histogram!!"); - layout.addRow(info); - - QStringList nameListX = {"Num. x-Bin", "x-Min", "x-Max"}; - QLineEdit* lineEditX[3]; - for (int i = 0; i < 3; ++i) { - lineEditX[i] = new QLineEdit(&dialog); - layout.addRow(nameListX[i] + " : ", lineEditX[i]); - } - lineEditX[0]->setText(QString::number(xBin)); - lineEditX[1]->setText(QString::number(xMin)); - lineEditX[2]->setText(QString::number(xMax)); - - QStringList nameListY = {"Num. y-Bin", "y-Min", "y-Max"}; - QLineEdit* lineEditY[3]; - for (int i = 0; i < 3; ++i) { - lineEditY[i] = new QLineEdit(&dialog); - layout.addRow(nameListY[i] + " : ", lineEditY[i]); - } - lineEditY[0]->setText(QString::number(yBin)); - lineEditY[1]->setText(QString::number(yMin)); - lineEditY[2]->setText(QString::number(yMax)); - - QLabel * msg = new QLabel(&dialog); - msg->setStyleSheet("color:red;"); - layout.addRow(msg); - - QDialogButtonBox buttonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel, Qt::Horizontal, &dialog); - layout.addRow(&buttonBox); - - double number[3][2]; - - QObject::connect(&buttonBox, &QDialogButtonBox::accepted, [&]() { - int OKcount = 0; - bool conversionOk = true; - for( int i = 0; i < 3; i++ ){ - number[i][0] = lineEditX[i]->text().toDouble(&conversionOk); - if( conversionOk ){ - OKcount++; - }else{ - msg->setText(nameListX[i] + " is invalid."); - return; - } - } - for( int i = 0; i < 3; i++ ){ - number[i][1] = lineEditY[i]->text().toDouble(&conversionOk); - if( conversionOk ){ - OKcount++; - }else{ - msg->setText(nameListY[i] + " is invalid."); - return; - } - } - - if( OKcount == 6 ) { - if( number[0][0] <= 0 ) { - msg->setText( nameListX[0] + " is zero or negative" ); - return; - } - if( number[0][0] <= 0 ) { - msg->setText( nameListX[0] + " is zero or negative" ); - return; - } - - if( number[2][0] > number[1][0] && number[2][1] > number[1][1] ) { - dialog.accept(); - }else{ - if( number[2][0] > number[1][0] ){ - msg->setText(nameListX[2] + " is smaller than " + nameListX[1]); - } - if( number[2][1] > number[1][1] ){ - msg->setText(nameListY[2] + " is smaller than " + nameListY[1]); - } - } - } - }); - - QObject::connect(&buttonBox, &QDialogButtonBox::rejected, [&]() { dialog.reject();}); - - if( dialog.exec() == QDialog::Accepted ){ - isBusy = true; - Rebin((int)number[0][0], number[1][0], number[2][0], (int)number[0][1], number[1][1], number[2][1]); - rescaleAxes(); - UpdatePlot(); - isBusy = false; - } - - } + void rightMouseClickMenu(QMouseEvent * event); + void rightMouseClickRebin(); }; +//^############################################### +//^############################################### + +inline void Histogram2D::Fill(double x, double y){ + if( isBusy ) return; + int xIndex, yIndex; + colorMap->data()->coordToCell(x, y, &xIndex, &yIndex); + //printf("%f, %d %d| %f, %d %d\n", x, xIndex, xBin, y, yIndex, yBin); + + int xk = 1, yk = 1; + if( xIndex < 0 ) xk = 0; + if( xIndex >= xBin ) xk = 2; + if( yIndex < 0 ) yk = 0; + if( yIndex >= yBin ) yk = 2; + entry[xk][yk] ++; + + txt[xk][yk]->setText(QString::number(entry[xk][yk])); + + if( xk == 1 && yk == 1 ) { + double value = colorMap->data()->cell(xIndex, yIndex); + colorMap->data()->setCell(xIndex, yIndex, value + 1); + + for( int i = 0; i < cutList.count(); i++){ + if( cutList[i].isEmpty() ) continue; + if( cutList[i].containsPoint(QPointF(x,y), Qt::OddEvenFill) ) cutEntryList[i] ++; + } + } +} + +inline void Histogram2D::Rebin(int xbin, double xmin, double xmax, int ybin, double ymin, double ymax){ + xMin = xmin; + xMax = xmax; + yMin = ymin; + yMax = ymax; + xBin = xbin; + yBin = ybin; + + colorMap->data()->clear(); + colorMap->data()->setSize(xBin, yBin); + colorMap->data()->setRange(QCPRange(xMin, xMax), QCPRange(yMin, yMax)); + + for( int i = 0; i < 3; i ++){ + for( int j = 0; j < 3; j ++){ + entry[i][j] = 0; + if( txt[i][j] ) txt[i][j]->setText("0"); + } + } + +} + +inline void Histogram2D::Clear(){ + for( int i = 0; i < 3; i ++){ + for( int j = 0; j < 3; j ++){ + entry[i][j] = 0; + txt[i][j]->setText("0"); + } + } + colorMap->data()->clear(); + colorMap->data()->setSize(xBin, yBin); + colorMap->data()->setRange(QCPRange(xMin, xMax), QCPRange(yMin, yMax)); + + UpdatePlot(); +} + + +inline void Histogram2D::ClearAllCuts(){ + numCut = 0; + tempCutID = -1; + lastPlottableID = -1; + cutList.clear(); + cutIDList.clear(); + for( int i = cutTextIDList.count() - 1; i >= 0 ; i--){ + if( cutTextIDList[i] < 0 ) continue; + removeItem(cutTextIDList[i]); + removePlottable(plottableIDList[i]); + } + replot(); + + cutTextIDList.clear(); + plottableIDList.clear(); + cutNameList.clear(); + cutEntryList.clear(); +} + +inline void Histogram2D::PrintCutEntry() const{ + if( numCut == 0 ) return; + printf("=============== There are %d cuts.\n", numCut); + for( int i = 0; i < cutList.count(); i++){ + if( cutList[i].isEmpty() ) continue; + printf("%10s | %d \n", cutNameList[i].toStdString().c_str(), cutEntryList[i]); + } +} + +inline void Histogram2D::DrawCut(){ + + //The histogram is the 1st plottable. + // the lastPlottableID should be numCut+ 1 + if( lastPlottableID != numCut ){ + removePlottable(lastPlottableID); + } + + if(tempCut.size() > 0) { + QCPCurve *polygon = new QCPCurve(xAxis, yAxis); + lastPlottableID = plottableCount() - 1; + + int colorID = tempCutID% colorCycle.count(); + QPen pen(colorCycle[colorID].first); + pen.setWidth(1); + polygon->setPen(pen); + + QVector dataPoints; + for (const QPointF& point : tempCut) { + dataPoints.append(QCPCurveData(dataPoints.size(), point.x(), point.y())); + } + polygon->data()->set(dataPoints, false); + } + replot(); + + //qDebug() << "Plottable count : " << plottableCount() << ", cutList.count :" << cutList.count() << ", cutID :" << lastPlottableID; +} + +inline void Histogram2D::rightMouseClickMenu(QMouseEvent * event){ + usingMenu = true; + setSelectionRectMode(QCP::SelectionRectMode::srmNone); + + QMenu *menu = new QMenu(this); + menu->setAttribute(Qt::WA_DeleteOnClose); + + QAction * a1 = menu->addAction("UnZoom"); + QAction * a2 = menu->addAction("Clear hist."); + QAction * a3 = menu->addAction("Toggle Stat."); + QAction * a4 = menu->addAction("Rebin (clear histogram)"); + QAction * a5 = menu->addAction("Create a Cut"); + if( numCut > 0 ) { + menu->addSeparator(); + menu->addAction("Add/Edit names to Cuts"); + menu->addAction("Clear all Cuts"); + } + for( int i = 0; i < cutList.size(); i++){ + if( cutList[i].isEmpty()) continue; + QString haha = ""; + menu->addAction("Delete " + cutNameList[i] + " ["+ colorCycle[cutIDList[i]%colorCycle.count()].second+"]"); + } + + QAction *selectedAction = menu->exec(event->globalPosition().toPoint()); + + 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 ){ + for( int i = 0; i < 3; i ++ ){ + for( int j = 0; j < 3; j ++ ){ + box[i][j]->setVisible( !box[i][j]->visible()); + txt[i][j]->setVisible( !txt[i][j]->visible()); + } + } + 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 && numCut > 0 && selectedAction->text().contains("Delete ") ){ + + QString haha = selectedAction->text(); + int index1 = haha.indexOf("-"); + int index2 = haha.indexOf("["); + int cutID = haha.mid(index1+1, index2-index1-1).remove(' ').toInt(); + + removeItem(cutTextIDList[cutID]); + removePlottable(plottableIDList[cutID]); + replot(); + + numCut --; + cutList[cutID].clear(); + cutIDList[cutID] = -1; + cutTextIDList[cutID] = -1; + plottableIDList[cutID] = -1; + cutNameList[cutID] = ""; + cutEntryList[cutID] = -1; + + for( int i = cutID + 1; i < cutTextIDList.count() ; i++){ + cutTextIDList[i] --; + plottableIDList[i] --; + } + + if( numCut == 0 ){ + tempCutID = -1; + lastPlottableID = -1; + cutList.clear(); + cutIDList.clear(); + cutTextIDList.clear(); + plottableIDList.clear(); + 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; + } + + +} + +inline void Histogram2D::rightMouseClickRebin(){ + QDialog dialog(this); + dialog.setWindowTitle("Rebin histogram"); + + QFormLayout layout(&dialog); + + QLabel * info = new QLabel(&dialog); + info->setStyleSheet("color:red;"); + info->setText("This will also clear histogram!!"); + layout.addRow(info); + + QStringList nameListX = {"Num. x-Bin", "x-Min", "x-Max"}; + QLineEdit* lineEditX[3]; + for (int i = 0; i < 3; ++i) { + lineEditX[i] = new QLineEdit(&dialog); + layout.addRow(nameListX[i] + " : ", lineEditX[i]); + } + lineEditX[0]->setText(QString::number(xBin)); + lineEditX[1]->setText(QString::number(xMin)); + lineEditX[2]->setText(QString::number(xMax)); + + QStringList nameListY = {"Num. y-Bin", "y-Min", "y-Max"}; + QLineEdit* lineEditY[3]; + for (int i = 0; i < 3; ++i) { + lineEditY[i] = new QLineEdit(&dialog); + layout.addRow(nameListY[i] + " : ", lineEditY[i]); + } + lineEditY[0]->setText(QString::number(yBin)); + lineEditY[1]->setText(QString::number(yMin)); + lineEditY[2]->setText(QString::number(yMax)); + + QLabel * msg = new QLabel(&dialog); + msg->setStyleSheet("color:red;"); + layout.addRow(msg); + + QDialogButtonBox buttonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel, Qt::Horizontal, &dialog); + layout.addRow(&buttonBox); + + double number[3][2]; + + QObject::connect(&buttonBox, &QDialogButtonBox::accepted, [&]() { + int OKcount = 0; + bool conversionOk = true; + for( int i = 0; i < 3; i++ ){ + number[i][0] = lineEditX[i]->text().toDouble(&conversionOk); + if( conversionOk ){ + OKcount++; + }else{ + msg->setText(nameListX[i] + " is invalid."); + return; + } + } + for( int i = 0; i < 3; i++ ){ + number[i][1] = lineEditY[i]->text().toDouble(&conversionOk); + if( conversionOk ){ + OKcount++; + }else{ + msg->setText(nameListY[i] + " is invalid."); + return; + } + } + + if( OKcount == 6 ) { + if( number[0][0] <= 0 ) { + msg->setText( nameListX[0] + " is zero or negative" ); + return; + } + if( number[0][0] <= 0 ) { + msg->setText( nameListX[0] + " is zero or negative" ); + return; + } + + if( number[2][0] > number[1][0] && number[2][1] > number[1][1] ) { + dialog.accept(); + }else{ + if( number[2][0] > number[1][0] ){ + msg->setText(nameListX[2] + " is smaller than " + nameListX[1]); + } + if( number[2][1] > number[1][1] ){ + msg->setText(nameListY[2] + " is smaller than " + nameListY[1]); + } + } + } + }); + + QObject::connect(&buttonBox, &QDialogButtonBox::rejected, [&]() { dialog.reject();}); + + if( dialog.exec() == QDialog::Accepted ){ + isBusy = true; + Rebin((int)number[0][0], number[1][0], number[2][0], (int)number[0][1], number[1][1], number[2][1]); + rescaleAxes(); + UpdatePlot(); + isBusy = false; + } + +} + + #endif \ No newline at end of file diff --git a/MultiBuilder.cpp b/MultiBuilder.cpp index 69eede3..f15e62c 100644 --- a/MultiBuilder.cpp +++ b/MultiBuilder.cpp @@ -92,6 +92,7 @@ void MultiBuilder::ClearEvents(){ nExhaushedCh = 0; } + } void MultiBuilder::PrintStat(){ @@ -292,7 +293,7 @@ void MultiBuilder::BuildEvents(bool isFinal, bool skipTrace, bool verbose){ } -void MultiBuilder::BuildEventsBackWard(bool verbose){ +void MultiBuilder::BuildEventsBackWard(int maxNumEvent, bool verbose){ //skip trace, and only build for 100 events max @@ -375,7 +376,7 @@ void MultiBuilder::BuildEventsBackWard(bool verbose){ } - }while(nExhaushedCh < nData * MaxNChannels && eventBuilt < 100); + }while(nExhaushedCh < nData * MaxNChannels && eventBuilt <= maxNumEvent); // // remember the end of DataIndex, prevent over build // for( int k = 0; k < nData; k++){ diff --git a/MultiBuilder.h b/MultiBuilder.h index 542dba7..ae2fa44 100644 --- a/MultiBuilder.h +++ b/MultiBuilder.h @@ -32,10 +32,13 @@ public: fineTime = 0; trace.clear(); } + + void Print(){ + printf("(%2d, %2d)[%3d] %6d %10llu, %5ld\n", bd, ch, sn, energy, timestamp, trace.size()); + } + }; - - class MultiBuilder { public: @@ -56,7 +59,7 @@ public: std::vector GetDigiIDList() const {return idList;} void BuildEvents(bool isFinal = false, bool skipTrace = false, bool verbose = false); - void BuildEventsBackWard(bool verbose = false); // always skip trace, for faster online building + void BuildEventsBackWard(int maxNumEvent = 100, bool verbose = false); // always skip trace, for faster online building void ClearEvents(); void PrintStat(); diff --git a/RegisterAddress.h b/RegisterAddress.h index a43bedc..bb83175 100644 --- a/RegisterAddress.h +++ b/RegisterAddress.h @@ -63,7 +63,7 @@ class Reg{ RW GetType() const {return type;} bool IsCoupled() const {return group;} unsigned int GetMaxBit() const {return maxBit;} - int GetPartialStep() const {return partialStep;} /// step = partialStep * ch2ns, -1 : step = 1 + int GetPartialStep() const {return partialStep;} /// step = partialStep * tick2ns, -1 : step = 1 void Print() const ; std::vector> GetComboList() const {return comboList;} diff --git a/Scope.cpp b/Scope.cpp index 37ff8a1..5f163e0 100644 --- a/Scope.cpp +++ b/Scope.cpp @@ -101,12 +101,12 @@ Scope::Scope(Digitizer ** digi, unsigned int nDigi, ReadDataThread ** readDataTh ID = 0; cbScopeDigi->setCurrentIndex(0); for( int i = 0; i < digi[0]->GetNChannels(); i++) cbScopeCh->addItem("Ch-" + QString::number(i)); - ch2ns = digi[ID]->GetCh2ns(); + tick2ns = digi[ID]->GetTick2ns(); connect(cbScopeDigi, &RComboBox::currentIndexChanged, this, [=](int index){ if( !enableSignalSlot ) return; ID = index; - ch2ns = digi[ID]->GetCh2ns(); + tick2ns = digi[ID]->GetTick2ns(); //---setup cbScopeCh cbScopeCh->clear(); for( int i = 0; i < digi[ID]->GetNChannels(); i++) cbScopeCh->addItem("Ch-" + QString::number(i)); @@ -310,7 +310,7 @@ void Scope::UpdateScope(){ if( digi[ID]->GetChannelOnOff(ch) == false) return; - int ch2ns = digi[ID]->GetCh2ns(); + int tick2ns = digi[ID]->GetTick2ns(); int factor = digi[ID]->IsDualTrace_PHA() ? 2 : 1; digiMTX[ID].lock(); @@ -329,19 +329,19 @@ void Scope::UpdateScope(){ QVector points[4]; if( digi[ID]->GetDPPType() == V1730_DPP_PHA_CODE ) { for( int i = 0; i < (int) (data->Waveform1[ch][index]).size() ; i++ ) { - points[0].append(QPointF(ch2ns * i * factor, (data->Waveform1[ch][index])[i])); - if( i < (int) data->Waveform2[ch][index].size() ) points[1].append(QPointF(ch2ns * i * factor, (data->Waveform2[ch][index])[i])); - if( i < (int) data->DigiWaveform1[ch][index].size() ) points[2].append(QPointF(ch2ns * i * factor, (data->DigiWaveform1[ch][index])[i] * 1000)); - if( i < (int) data->DigiWaveform2[ch][index].size() ) points[3].append(QPointF(ch2ns * i * factor, (data->DigiWaveform2[ch][index])[i] * 1000 + 500)); + points[0].append(QPointF(tick2ns * i * factor, (data->Waveform1[ch][index])[i])); + if( i < (int) data->Waveform2[ch][index].size() ) points[1].append(QPointF(tick2ns * i * factor, (data->Waveform2[ch][index])[i])); + if( i < (int) data->DigiWaveform1[ch][index].size() ) points[2].append(QPointF(tick2ns * i * factor, (data->DigiWaveform1[ch][index])[i] * 1000)); + if( i < (int) data->DigiWaveform2[ch][index].size() ) points[3].append(QPointF(tick2ns * i * factor, (data->DigiWaveform2[ch][index])[i] * 1000 + 500)); } } if( digi[ID]->GetDPPType() == V1730_DPP_PSD_CODE ) { for( int i = 0; i < (int) (data->DigiWaveform1[ch][index]).size() ; i++ ) { - points[0].append(QPointF(ch2ns * i * factor, (data->Waveform1[ch][index])[i])); - if( i < (int) data->Waveform2[ch][index].size() ) points[1].append(QPointF(ch2ns * i * factor, (data->Waveform2[ch][index])[i])); - if( i < (int) data->DigiWaveform1[ch][index].size() ) points[2].append(QPointF(ch2ns * i, (data->DigiWaveform1[ch][index])[i] * 1000)); - if( i < (int) data->DigiWaveform2[ch][index].size() ) points[3].append(QPointF(ch2ns * i, (data->DigiWaveform2[ch][index])[i] * 1000 + 500)); + points[0].append(QPointF(tick2ns * i * factor, (data->Waveform1[ch][index])[i])); + if( i < (int) data->Waveform2[ch][index].size() ) points[1].append(QPointF(tick2ns * i * factor, (data->Waveform2[ch][index])[i])); + if( i < (int) data->DigiWaveform1[ch][index].size() ) points[2].append(QPointF(tick2ns * i, (data->DigiWaveform1[ch][index])[i] * 1000)); + if( i < (int) data->DigiWaveform2[ch][index].size() ) points[3].append(QPointF(tick2ns * i, (data->DigiWaveform2[ch][index])[i] * 1000 + 500)); } } dataTrace[0]->replace(points[0]); @@ -351,7 +351,7 @@ void Scope::UpdateScope(){ } digiMTX[ID].unlock(); - plot->axes(Qt::Horizontal).first()->setRange(0, ch2ns * traceLength * factor); + plot->axes(Qt::Horizontal).first()->setRange(0, tick2ns * traceLength * factor); emit UpdateScaler(); @@ -412,8 +412,8 @@ void Scope::SetUpSpinBox(RSpinBox * &sb, QString str, int row, int col, const Re sb = new RSpinBox(settingGroup); if( para.GetPartialStep() != 0 ){ sb->setMinimum(0); - sb->setMaximum(para.GetMaxBit() * para.GetPartialStep() * ch2ns); - if( para.GetPartialStep() > 0 ) sb->setSingleStep(para.GetPartialStep() * ch2ns); + sb->setMaximum(para.GetMaxBit() * para.GetPartialStep() * tick2ns); + if( para.GetPartialStep() > 0 ) sb->setSingleStep(para.GetPartialStep() * tick2ns); if( para.GetPartialStep() == -1 ) sb->setSingleStep(1); } settingLayout->addWidget(sb, row, col + 1); @@ -438,7 +438,7 @@ void Scope::SetUpSpinBox(RSpinBox * &sb, QString str, int row, int col, const Re msg = QString::fromStdString(para.GetName()) + "|DIG:"+ QString::number(digi[ID]->GetSerialNumber()) + ",CH:" + (ch == -1 ? "All" : QString::number(ch)); msg += " = " + QString::number(sb->value()); - uint32_t value = sb->value() / ch2ns / abs(para.GetPartialStep()); + uint32_t value = sb->value() / tick2ns / abs(para.GetPartialStep()); if( para == DPP::RecordLength_G){ int factor = digi[ID]->IsDualTrace_PHA() ? 2 : 1; @@ -694,7 +694,7 @@ void Scope::UpdateSpinBox(RSpinBox * &sb, const Reg para){ enableSignalSlot = false; unsigned int haha = digi[ID]->GetSettingFromMemory(para, ch); - if( para.GetPartialStep() > 0 ) sb->setValue(haha * para.GetPartialStep() * ch2ns); + if( para.GetPartialStep() > 0 ) sb->setValue(haha * para.GetPartialStep() * tick2ns); if( para.GetPartialStep() == -1 ) sb->setValue(haha); //enableSignalSlot = true; } @@ -708,11 +708,11 @@ void Scope::UpdatePanelFromMomeory(){ int ch = cbScopeCh->currentIndex(); unsigned int haha = digi[ID]->GetSettingFromMemory(DPP::RecordLength_G, ch); - sbReordLength->setValue(haha * DPP::RecordLength_G.GetPartialStep() * ch2ns); + sbReordLength->setValue(haha * DPP::RecordLength_G.GetPartialStep() * tick2ns); // if( digi[ID]->GetDPPType() == V1730_DPP_PHA_CODE ){ // int factor = digi[ID]->IsDualTrace() ? 2 : 1; // if dual trace, - // sbReordLength->setValue(haha * DPP::RecordLength_G.GetPartialStep() * ch2ns / factor); + // sbReordLength->setValue(haha * DPP::RecordLength_G.GetPartialStep() * tick2ns / factor); // }else{ // } diff --git a/Scope.h b/Scope.h index 013fee9..b482ee2 100644 --- a/Scope.h +++ b/Scope.h @@ -71,7 +71,7 @@ private: Digitizer ** digi; unsigned short nDigi; unsigned short ID; // the id of digi, index of cbScopeDigi - int ch2ns; + int tick2ns; bool traceOn[MaxNDigitizer]; ReadDataThread ** readDataThread; diff --git a/SplitPoleAnalyzer.h b/SplitPoleAnalyzer.h index 29dec70..1b39075 100644 --- a/SplitPoleAnalyzer.h +++ b/SplitPoleAnalyzer.h @@ -26,9 +26,15 @@ public: SetUpdateTimeInSec(1.0); - RedefineEventBuilder({0}); // only build for the 0-th digitizer; + RedefineEventBuilder({0}); // only build for the 0-th digitizer, otherwise, it will build event accross all digitizers + tick2ns = digi[0]->GetTick2ns(); + SetBackwardBuild(false, 500); // using normal building (acceding in time) or backward building, int the case of backward building, default events to be build is 100. evtbder = GetEventBuilder(); + //========== use the influx from the Analyzer + influx = new InfluxDB("https://fsunuc.physics.fsu.edu/influx/"); + dataBaseName = "testing"; + SetUpCanvas(); } @@ -47,6 +53,8 @@ private: Histogram2D * h2; Histogram1D * h1; + int tick2ns; + }; @@ -55,12 +63,13 @@ inline void SplitPole::SetUpCanvas(){ setGeometry(0, 0, 1600, 800); // the "this" make the histogram a child of the SplitPole class. When SplitPole destory, all childs destory as well. - h2 = new Histogram2D("Split Pole PID", "x", "y", 400, 0, 10000, 400, 0, 10000, this); + h2 = new Histogram2D("Split Pole PID", "x", "y", 100, 0, 10000, 100, 0, 10000, this); //layout is inheriatge from Analyzer layout->addWidget(h2, 0, 0); h1 = new Histogram1D("Spectrum", "x", 400, 0, 10000, this); layout->addWidget(h1, 0, 1); + } @@ -72,29 +81,61 @@ inline void SplitPole::UpdateHistograms(){ long eventBuilt = evtbder->eventBuilt; if( eventBuilt == 0 ) return; + //============ Get the cut list, if any + QList cutList = h2->GetCutList(); + const int nCut = cutList.count(); + unsigned long long tMin[nCut] = {0xFFFFFFFFFFFFFFFF}, tMax[nCut] = {0}; + unsigned int count[nCut]={0}; + + //============ Processing data and fill histograms long eventIndex = evtbder->eventIndex; long eventStart = eventIndex - eventBuilt + 1; if(eventStart < 0 ) eventStart += MaxNEvent; - - //============ Processing data and fill histograms - unsigned short e1 = 0, e2 = 0; - + for( long i = eventStart ; i <= eventIndex; i ++ ){ + unsigned short e1 = 0, e2 = 0; + unsigned long long t1 = 0, t2 = 0; std::vector event = evtbder->events[i]; - + //printf("-------------- %ld\n", i); for( int k = 0; k < (int) event.size(); k++ ){ - if( event[k].ch == 9 ) e1 = event[k].energy; - if( event[k].ch == 10 ) e2 = event[k].energy; + //event[k].Print(); + if( event[k].ch == 9 ) {e1 = event[k].energy; t1 = event[k].timestamp;} + if( event[k].ch == 10 ) {e2 = event[k].energy; t2 = event[k].timestamp;} } + if( e1 == 0 ) continue; + if( e2 == 0 ) continue; + h2->Fill(e1, e2); h1->Fill(e1); + + //check events inside any Graphical cut and extract the rate, using t1 only + for(int p = 0; p < cutList.count(); p++ ){ + if( cutList[p].isEmpty() ) continue; + if( cutList[p].containsPoint(QPointF(e1, e2), Qt::OddEvenFill) ){ + if( t1 < tMin[p] ) tMin[p] = t1; + if( t1 > tMax[p] ) tMax[p] = t1; + count[p] ++; + //printf(".... %d \n", count[p]); + } + } } h2->UpdatePlot(); h1->UpdatePlot(); - h2->PrintCutEntry(); + QList cutNameList = h2->GetCutNameList(); + for( int p = 0; p < cutList.count(); p ++){ + if( cutList[p].isEmpty() ) continue; + double dT = (tMax[p]-tMin[p]) * tick2ns / 1e9; // tick to sec + double rate = count[p]*1.0/(dT); + //printf("%llu %llu, %f %d\n", tMin[p], tMax[p], dT, count[p]); + //printf("%10s | %d | %f Hz \n", cutNameList[p].toStdString().c_str(), count[p], rate); + + influx->AddDataPoint("Cut,name=" + cutNameList[p].toStdString()+ " value=" + std::to_string(rate)); + influx->WriteData(dataBaseName); + influx->ClearDataPointsBuffer(); + } } diff --git a/test.cpp b/test.cpp index 99adc7b..8196183 100644 --- a/test.cpp +++ b/test.cpp @@ -41,7 +41,7 @@ int main(int argc, char* argv[]){ // dig[0]->ProgramBoard(); // dig[0]->ProgramPSDBoard(); - // const float ch2ns = dig[0]->GetCh2ns(); + // const float tick2ns = dig[0]->GetTick2ns(); Data * data = dig[0]->GetData(); data->ClearData(); @@ -117,7 +117,7 @@ int main(int argc, char* argv[]){ unsigned short nData = data->DataIndex[0]; //channel-0 haha = data->Waveform1[0][nData-1]; - for( int i = 0; i < waveFormLength; i++) g1->SetPoint(i, i*ch2ns, haha[i]); + for( int i = 0; i < waveFormLength; i++) g1->SetPoint(i, i*tick2ns, haha[i]); canvas->cd(3); g1->Draw("AP"); diff --git a/test_indep.cpp b/test_indep.cpp index 99f20dd..aabb612 100644 --- a/test_indep.cpp +++ b/test_indep.cpp @@ -13,7 +13,7 @@ using namespace std; -void PrintChannelSettingFromDigitizer(int handle, int ch, float ch2ns){ +void PrintChannelSettingFromDigitizer(int handle, int ch, float tick2ns){ printf("\e[33m================================================\n"); printf("================ Setting for channel %d \n", ch); @@ -48,11 +48,11 @@ void PrintChannelSettingFromDigitizer(int handle, int ch, float ch2ns){ default: extra2WordOptStr = "Reserved"; break; } - printf(" ch2ns : %.0f ns\n", ch2ns); + printf(" tick2ns : %.0f ns\n", tick2ns); printf("==========----- input \n"); - CAEN_DGTZ_ReadRegister(handle, DPP::RecordLength_G + (ch << 8), value); printf("%24s %5d samples = %5.0f ns \n", "Record Length", ((value[0] * 8) & MaxRecordLength), ((value[0] * 8) & MaxRecordLength) * ch2ns); ///Record length - CAEN_DGTZ_ReadRegister(handle, DPP::PreTrigger + (ch << 8), value); printf("%24s %5d samples = %5.0f ns \n", "Pre-tigger", value[0] * 4, value[0] * 4 * ch2ns); ///Pre-trigger + CAEN_DGTZ_ReadRegister(handle, DPP::RecordLength_G + (ch << 8), value); printf("%24s %5d samples = %5.0f ns \n", "Record Length", ((value[0] * 8) & MaxRecordLength), ((value[0] * 8) & MaxRecordLength) * tick2ns); ///Record length + CAEN_DGTZ_ReadRegister(handle, DPP::PreTrigger + (ch << 8), value); printf("%24s %5d samples = %5.0f ns \n", "Pre-tigger", value[0] * 4, value[0] * 4 * tick2ns); ///Pre-trigger printf("%24s %5.0f samples, DPP-[20:22]\n", "baseline mean", pow(4, 1 + baseline)); ///Ns baseline CAEN_DGTZ_ReadRegister(handle, DPP::ChannelDCOffset + (ch << 8), value); printf("%24s %.2f %% \n", "DC offset", 100.0 - value[0] * 100./ 0xFFFF); ///DC offset CAEN_DGTZ_ReadRegister(handle, DPP::InputDynamicRange + (ch << 8), value); printf("%24s %.1f Vpp \n", "input Dynamic", value[0] == 0 ? 2 : 0.5); ///InputDynamic @@ -60,27 +60,27 @@ void PrintChannelSettingFromDigitizer(int handle, int ch, float ch2ns){ printf("==========----- discriminator \n"); CAEN_DGTZ_ReadRegister(handle, DPP::PHA::TriggerThreshold + (ch << 8), value); printf("%24s %4d LSB\n", "Threshold", value[0]); ///Threshold - CAEN_DGTZ_ReadRegister(handle, DPP::PHA::TriggerHoldOffWidth + (ch << 8), value); printf("%24s %4d samples, %5.0f ns \n", "trigger hold off", value[0], value[0] * 4 * ch2ns); ///Trigger Hold off - CAEN_DGTZ_ReadRegister(handle, DPP::PHA::RCCR2SmoothingFactor + (ch << 8), value); printf("%24s %4d samples, %5.0f ns \n", "Fast Dis. smoothing", (value[0] & 0x1f) * 2, (value[0] & 0x1f) * 2 * ch2ns ); ///Fast Discriminator smoothing - CAEN_DGTZ_ReadRegister(handle, DPP::PHA::ShapedTriggerWidth + (ch << 8), value); printf("%24s %4d samples, %5.0f ns \n", "Fast Dis. output width", value[0], value[0] * 4 * ch2ns); ///Fast Dis. output width - CAEN_DGTZ_ReadRegister(handle, DPP::PHA::InputRiseTime + (ch << 8), value); printf("%24s %4d samples, %5.0f ns \n", "Input rise time ", value[0], value[0] * 4 * ch2ns); ///Input rise time + CAEN_DGTZ_ReadRegister(handle, DPP::PHA::TriggerHoldOffWidth + (ch << 8), value); printf("%24s %4d samples, %5.0f ns \n", "trigger hold off", value[0], value[0] * 4 * tick2ns); ///Trigger Hold off + CAEN_DGTZ_ReadRegister(handle, DPP::PHA::RCCR2SmoothingFactor + (ch << 8), value); printf("%24s %4d samples, %5.0f ns \n", "Fast Dis. smoothing", (value[0] & 0x1f) * 2, (value[0] & 0x1f) * 2 * tick2ns ); ///Fast Discriminator smoothing + CAEN_DGTZ_ReadRegister(handle, DPP::PHA::ShapedTriggerWidth + (ch << 8), value); printf("%24s %4d samples, %5.0f ns \n", "Fast Dis. output width", value[0], value[0] * 4 * tick2ns); ///Fast Dis. output width + CAEN_DGTZ_ReadRegister(handle, DPP::PHA::InputRiseTime + (ch << 8), value); printf("%24s %4d samples, %5.0f ns \n", "Input rise time ", value[0], value[0] * 4 * tick2ns); ///Input rise time printf("==========----- Trapezoid \n"); - CAEN_DGTZ_ReadRegister(handle, DPP::PHA::TrapezoidRiseTime + (ch << 8), value); printf("%24s %4d samples, %5.0f ns \n", "Trap. rise time", value[0], value[0] * 4 * ch2ns); ///Trap. rise time, 2 for 1 ch to 2ns - int riseTime = value[0] * 4 * ch2ns; - CAEN_DGTZ_ReadRegister(handle, DPP::PHA::TrapezoidFlatTop + (ch << 8), value); printf("%24s %4d samples, %5.0f ns \n", "Trap. flat time", value[0], value[0] * 4 * ch2ns); ///Trap. flat time - int flatTopTime = value[0] * 4 * ch2ns; + CAEN_DGTZ_ReadRegister(handle, DPP::PHA::TrapezoidRiseTime + (ch << 8), value); printf("%24s %4d samples, %5.0f ns \n", "Trap. rise time", value[0], value[0] * 4 * tick2ns); ///Trap. rise time, 2 for 1 ch to 2ns + int riseTime = value[0] * 4 * tick2ns; + CAEN_DGTZ_ReadRegister(handle, DPP::PHA::TrapezoidFlatTop + (ch << 8), value); printf("%24s %4d samples, %5.0f ns \n", "Trap. flat time", value[0], value[0] * 4 * tick2ns); ///Trap. flat time + int flatTopTime = value[0] * 4 * tick2ns; double shift = log(riseTime * flatTopTime ) / log(2) - 2; printf("%24s %4d bit =? %.1f = Ceil( Log(rise [ns] x decay [ns])/Log(2) ), DPP-[0:5]\n", "Trap. Rescaling", trapRescaling, shift ); ///Trap. Rescaling Factor - CAEN_DGTZ_ReadRegister(handle, DPP::PHA::DecayTime + (ch << 8), value); printf("%24s %4d samples, %5.0f ns \n", "Decay time", value[0], value[0] * 4 * ch2ns); ///Trap. pole zero - CAEN_DGTZ_ReadRegister(handle, DPP::PHA::PeakingTime + (ch << 8), value); printf("%24s %4d samples, %5.0f ns = %.2f %% of FlatTop\n", "Peaking time", value[0], value[0] * 4 * ch2ns, value[0] * 400. * ch2ns / flatTopTime ); ///Peaking time - CAEN_DGTZ_ReadRegister(handle, DPP::PHA::PeakHoldOff + (ch << 8), value); printf("%24s %4d samples, %5.0f ns \n", "Peak hole off", value[0], value[0] * 4 *ch2ns ); ///Peak hold off + CAEN_DGTZ_ReadRegister(handle, DPP::PHA::DecayTime + (ch << 8), value); printf("%24s %4d samples, %5.0f ns \n", "Decay time", value[0], value[0] * 4 * tick2ns); ///Trap. pole zero + CAEN_DGTZ_ReadRegister(handle, DPP::PHA::PeakingTime + (ch << 8), value); printf("%24s %4d samples, %5.0f ns = %.2f %% of FlatTop\n", "Peaking time", value[0], value[0] * 4 * tick2ns, value[0] * 400. * tick2ns / flatTopTime ); ///Peaking time + CAEN_DGTZ_ReadRegister(handle, DPP::PHA::PeakHoldOff + (ch << 8), value); printf("%24s %4d samples, %5.0f ns \n", "Peak hole off", value[0], value[0] * 4 *tick2ns ); ///Peak hold off printf("%24s %4.0f samples, DPP-[12:13]\n", "Peak mean", pow(4, NsPeak)); ///Ns peak printf("==========----- Other \n"); CAEN_DGTZ_ReadRegister(handle, DPP::PHA::FineGain + (ch << 8), value); printf("%24s %d = 0x%x\n", "Energy fine gain", value[0], value[0]); ///Energy fine gain CAEN_DGTZ_ReadRegister(handle, DPP::ChannelADCTemperature_R + (ch << 8), value); printf("%24s %d C\n", "Temperature", value[0]); ///Temperature - CAEN_DGTZ_ReadRegister(handle, DPP::PHA::RiseTimeValidationWindow + (ch << 8), value); printf("%24s %.0f ns \n", "RiseTime Vaild Win.", value[0] * ch2ns); + CAEN_DGTZ_ReadRegister(handle, DPP::PHA::RiseTimeValidationWindow + (ch << 8), value); printf("%24s %.0f ns \n", "RiseTime Vaild Win.", value[0] * tick2ns); CAEN_DGTZ_ReadRegister(handle, DPP::PHA::ChannelStopAcquisition + (ch << 8), value); printf("%24s %d = %s \n", "Stop Acq bit", value[0] & 1 , (value[0] & 1 ) == 0 ? "Run" : "Stop"); CAEN_DGTZ_ReadRegister(handle, DPP::ChannelStatus_R + (ch << 8), value); printf("%24s 0x%x \n", "Status bit", (value[0] & 0xff) ); CAEN_DGTZ_ReadRegister(handle, DPP::AMCFirmwareRevision_R + (ch << 8), value); printf("%24s 0x%x \n", "AMC firmware rev.", value[0] ); @@ -181,10 +181,10 @@ int main(int argc, char* argv[]){ ret = (int) CAEN_DGTZ_GetInfo(handle, &BoardInfo); int NChannel = BoardInfo.Channels; uint32_t channelMask = 0xFFFF; - float ch2ns = 4.0; + float tick2ns = 4.0; switch(BoardInfo.Model){ - case CAEN_DGTZ_V1730: ch2ns = 2.0; break; ///ns -> 500 MSamples/s - case CAEN_DGTZ_V1725: ch2ns = 4.0; break; ///ns -> 250 MSamples/s + case CAEN_DGTZ_V1730: tick2ns = 2.0; break; ///ns -> 500 MSamples/s + case CAEN_DGTZ_V1725: tick2ns = 4.0; break; ///ns -> 250 MSamples/s } unsigned int ADCbits = BoardInfo.ADC_NBits; @@ -309,7 +309,7 @@ int main(int argc, char* argv[]){ if( ret != 0 ) { printf("==== memory allocation error.\n"); return 0;} PrintBoardConfiguration(handle); - PrintChannelSettingFromDigitizer(handle, 4, ch2ns); + PrintChannelSettingFromDigitizer(handle, 4, tick2ns); printf("============ Start ACQ \n"); CAEN_DGTZ_SWStartAcquisition(handle);