diff --git a/FSUDAQ.cpp b/FSUDAQ.cpp index 5fc8b16..6bafa8a 100644 --- a/FSUDAQ.cpp +++ b/FSUDAQ.cpp @@ -16,6 +16,9 @@ #include "analyzers/SplitPoleAnalyzer.h" #include "analyzers/EncoreAnalyzer.h" +#include "analyzers/RAISOR.h" + +std::vector onlineAnalyzerList = {"Splie-Pole", "Encore", "RAISOR"}; MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent){ @@ -66,8 +69,7 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent){ cbAnalyzer = new RComboBox(this); layout->addWidget(cbAnalyzer, 0, 2); cbAnalyzer->addItem("Choose Online Analyzer", -1); - cbAnalyzer->addItem("Split-Pole", 0); - cbAnalyzer->addItem("Encore", 1); + for( int i = 0; i < (int) onlineAnalyzerList.size() ; i++) cbAnalyzer->addItem(onlineAnalyzerList[i].c_str(), i); connect(cbAnalyzer, &RComboBox::currentIndexChanged, this, &MainWindow::OpenAnalyzer); bnCanvas = new QPushButton("Online 1D Histograms", this); @@ -1497,6 +1499,7 @@ void MainWindow::OpenAnalyzer(){ //onlineAnalyzer = new Analyzer(digi, nDigi); if( id == 0 ) onlineAnalyzer = new SplitPole(digi, nDigi); if( id == 1 ) onlineAnalyzer = new Encore(digi, nDigi); + if( id == 2 ) onlineAnalyzer = new RAISOR(digi, nDigi); if( id >= 0 ) onlineAnalyzer->show(); }else{ @@ -1504,6 +1507,7 @@ void MainWindow::OpenAnalyzer(){ if( id == 0 ) onlineAnalyzer = new SplitPole(digi, nDigi); if( id == 1 ) onlineAnalyzer = new Encore(digi, nDigi); + if( id == 2 ) onlineAnalyzer = new RAISOR(digi, nDigi); if( id >= 0 ){ onlineAnalyzer->show(); diff --git a/FSUDAQ_Qt6.pro b/FSUDAQ_Qt6.pro index 46cef57..17dbcb7 100644 --- a/FSUDAQ_Qt6.pro +++ b/FSUDAQ_Qt6.pro @@ -42,6 +42,7 @@ HEADERS += ClassData.h \ analyzers/Analyser.h \ analyzers/SplitPoleAnalyzer.h \ analyzers/EncoreAnalyzer.h + analyzers/RAISOR.h SOURCES += ClassDigitizer.cpp \ DigiSettingsPanel.cpp \ FSUDAQ.cpp \ diff --git a/analyzers/RAISOR.h b/analyzers/RAISOR.h new file mode 100644 index 0000000..4a4d932 --- /dev/null +++ b/analyzers/RAISOR.h @@ -0,0 +1,132 @@ +#ifndef RASIOR_h +#define RASIOR_h + +/********************************************* + * This is online analyzer for RASIOR, ANL + * + * Created by Ryan @ 2023-10-16 + * + * ******************************************/ +#include "Analyser.h" + + +class RAISOR : public Analyzer{ + +public: + RAISOR(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); + + //========== use the influx from the Analyzer + influx = new InfluxDB("https://fsunuc.physics.fsu.edu/influx/"); + dataBaseName = "testing"; + + SetUpCanvas(); // see below + + }; + + void SetUpCanvas(); + +public slots: + void UpdateHistograms(); + + +private: + + MultiBuilder *evtbder; + + Histogram2D * hPID; + + int tick2ns; + + float dE, E; + unsigned long long dE_t, E_t; + +}; + + +inline void RAISOR::SetUpCanvas(){ + + setGeometry(0, 0, 500, 500); + + //============ histograms + hPID = new Histogram2D("RAISOR", "E", "dE", 100, 0, 5000, 100, 0, 5000, this); + layout->addWidget(hPID, 0, 0); + +} + +inline void RAISOR::UpdateHistograms(){ + + if( this->isVisible() == false ) return; + + BuildEvents(); // 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 cutList = hPID->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; + + for( long i = eventStart ; i <= eventIndex; i ++ ){ + std::vector event = evtbder->events[i]; + //printf("-------------- %ld\n", i); + + if( event.size() == 0 ) return; + + for( int k = 0; k < (int) event.size(); k++ ){ + //event[k].Print(); + if( event[k].ch == 0 ) {dE = event[k].energy; dE_t = event[k].timestamp;} + if( event[k].ch == 1 ) {E = event[k].energy; E_t = event[k].timestamp;} + + } + + hPID->Fill(E, dE); // x, y + + //check events inside any Graphical cut and extract the rate + for(int p = 0; p < cutList.count(); p++ ){ + if( cutList[p].isEmpty() ) continue; + if( cutList[p].containsPoint(QPointF(E, dE), Qt::OddEvenFill) ){ + if( dE_t < tMin[p] ) tMin[p] = dE_t; + if( dE_t > tMax[p] ) tMax[p] = dE_t; + count[p] ++; + //printf(".... %d \n", count[p]); + } + } + } + + hPID->UpdatePlot(); + + //========== output to Influx + QList cutNameList = hPID->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(); + } +} + + +#endif \ No newline at end of file diff --git a/analyzers/SplitPoleAnalyzer.h b/analyzers/SplitPoleAnalyzer.h index 31d7d91..f8b42dc 100644 --- a/analyzers/SplitPoleAnalyzer.h +++ b/analyzers/SplitPoleAnalyzer.h @@ -49,23 +49,26 @@ // } // } -namespace ChMap{ +namespace SPS{ + namespace ChMap{ - const short ScinR = 0; - const short ScinL = 1; - const short dFR = 9; - const short dFL = 8; - const short dBR = 10; - const short dBL = 11; - const short Cathode = 7; - const short AnodeF = 13; - const short AnodeB = 15; + const short ScinR = 0; + const short ScinL = 1; + const short dFR = 9; + const short dFL = 8; + const short dBR = 10; + const short dBL = 11; + const short Cathode = 7; + const short AnodeF = 13; + const short AnodeB = 15; -}; + }; -const double c = 299.792458; // mm/ns -const double pi = M_PI; -const double deg2rad = pi/180.; + const double c = 299.792458; // mm/ns + const double pi = M_PI; + const double deg2rad = pi/180.; + +} class SplitPoleHit{ @@ -105,7 +108,7 @@ public: double Q = target.Mass + beam.Mass - recoil.Mass - heavyRecoil.Mass; - double haha1 = sqrt(beam.Mass + beamKE + recoil.Mass)/(recoil.Mass + heavyRecoil.Mass) / cos(angleDegree * deg2rad); + double haha1 = sqrt(beam.Mass + beamKE + recoil.Mass)/(recoil.Mass + heavyRecoil.Mass) / cos(angleDegree * SPS::deg2rad); double haha2 = ( beamKE * ( heavyRecoil.Mass + beam.Mass) + heavyRecoil.Mass * Q) / (recoil.Mass + heavyRecoil.Mass); double recoilKE = pow(haha1 + sqrt(haha1*haha1 + haha2), 2); @@ -114,9 +117,9 @@ public: printf("proton enegry : %f \n", recoilKE); double recoilP = sqrt( recoilKE* ( recoilKE + 2*recoil.Mass)); - double rho = recoilP/(target.Z * Bfield * c); // in m + double rho = recoilP/(target.Z * Bfield * SPS::c); // in m double haha = sqrt( recoil.Mass * beam.Mass * beamKE / recoilKE ); - double k = haha * sin(angleDegree * deg2rad) / ( recoil.Mass + heavyRecoil.Mass - haha * cos(angleDegree * deg2rad)); + double k = haha * sin(angleDegree * SPS::deg2rad) / ( recoil.Mass + heavyRecoil.Mass - haha * cos(angleDegree * SPS::deg2rad)); const double SPS_DISPERSION = 1.96; // x-position/rho const double SPS_MAGNIFICATION = 0.39; // in x-position @@ -159,9 +162,9 @@ public: if( x2 > x1 ) { theta = atan((x2-x1)/36.0); }else if(x2 < x1){ - theta = pi + atan((x2-x1)/36.0); + theta = SPS::pi + atan((x2-x1)/36.0); }else{ - theta = pi * 0.5; + theta = SPS::pi * 0.5; } double w1 = 0.5 - zOffset/4.28625; @@ -440,15 +443,15 @@ inline void SplitPole::UpdateHistograms(){ for( int k = 0; k < (int) event.size(); k++ ){ //event[k].Print(); - if( event[k].ch == ChMap::ScinR ) {hit.eSR = event[k].energy; hit.tSR = event[k].timestamp;} - if( event[k].ch == ChMap::ScinL ) {hit.eSL = event[k].energy; hit.tSL = event[k].timestamp;} - if( event[k].ch == ChMap::dFR ) {hit.eFR = event[k].energy; hit.tFR = event[k].timestamp;} - if( event[k].ch == ChMap::dFL ) {hit.eFL = event[k].energy; hit.tFL = event[k].timestamp;} - if( event[k].ch == ChMap::dBR ) {hit.eBL = event[k].energy; hit.tBL = event[k].timestamp;} - if( event[k].ch == ChMap::dBL ) {hit.eBL = event[k].energy; hit.tBL = event[k].timestamp;} - if( event[k].ch == ChMap::Cathode ) {hit.eCath = event[k].energy; hit.tCath = event[k].timestamp;} - if( event[k].ch == ChMap::AnodeF ) {hit.eAF = event[k].energy; hit.tAF = event[k].timestamp;} - if( event[k].ch == ChMap::AnodeB ) {hit.eAB = event[k].energy; hit.tAB = event[k].timestamp;} + if( event[k].ch == SPS::ChMap::ScinR ) {hit.eSR = event[k].energy; hit.tSR = event[k].timestamp;} + if( event[k].ch == SPS::ChMap::ScinL ) {hit.eSL = event[k].energy; hit.tSL = event[k].timestamp;} + if( event[k].ch == SPS::ChMap::dFR ) {hit.eFR = event[k].energy; hit.tFR = event[k].timestamp;} + if( event[k].ch == SPS::ChMap::dFL ) {hit.eFL = event[k].energy; hit.tFL = event[k].timestamp;} + if( event[k].ch == SPS::ChMap::dBR ) {hit.eBL = event[k].energy; hit.tBL = event[k].timestamp;} + if( event[k].ch == SPS::ChMap::dBL ) {hit.eBL = event[k].energy; hit.tBL = event[k].timestamp;} + if( event[k].ch == SPS::ChMap::Cathode ) {hit.eCath = event[k].energy; hit.tCath = event[k].timestamp;} + if( event[k].ch == SPS::ChMap::AnodeF ) {hit.eAF = event[k].energy; hit.tAF = event[k].timestamp;} + if( event[k].ch == SPS::ChMap::AnodeB ) {hit.eAB = event[k].energy; hit.tAB = event[k].timestamp;} } hit.CalData();