2023-06-12 16:32:01 -04:00
# ifndef SPLITPOLEANLAYZER_H
# define SPLITPOLEANLAYZER_H
/*********************************************
* This is online analyzer for Split - Pole at FSU
*
* It is a template for other analyzer .
*
* Any new analyzer add to added to FSUDAQ . cpp
2023-06-12 16:41:03 -04:00
* 1 ) add include header
* 2 ) in OpenAnalyzer ( ) , change the new
2023-06-12 16:32:01 -04:00
*
2023-06-12 16:41:03 -04:00
* add the source file in FSUDAQ_Qt6 . pro then compile
2023-06-12 16:32:01 -04:00
* > qmake6 FSUDAQ_Qt6 . pro
* > make
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2023-10-20 17:57:03 -04:00
# include "SplitPoleHit.h"
2023-06-23 13:50:21 -04:00
# include "Analyser.h"
//^===========================================
//^===========================================
2023-06-12 16:32:01 -04:00
class SplitPole : public Analyzer {
Q_OBJECT
public :
2023-06-12 16:41:03 -04:00
SplitPole ( Digitizer * * digi , unsigned int nDigi , QMainWindow * parent = nullptr ) : Analyzer ( digi , nDigi , parent ) {
SetUpdateTimeInSec ( 1.0 ) ;
2023-06-20 11:57:39 -04:00
RedefineEventBuilder ( { 0 } ) ; // only build for the 0-th digitizer, otherwise, it will build event accross all digitizers
tick2ns = digi [ 0 ] - > GetTick2ns ( ) ;
2023-06-20 16:18:02 -04:00
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.
2023-06-14 15:41:26 -04:00
evtbder = GetEventBuilder ( ) ;
2023-06-20 16:18:02 -04:00
evtbder - > SetTimeWindow ( 500 ) ;
2023-06-20 11:57:39 -04:00
//========== use the influx from the Analyzer
influx = new InfluxDB ( " https://fsunuc.physics.fsu.edu/influx/ " ) ;
dataBaseName = " testing " ;
2023-06-12 16:41:03 -04:00
SetUpCanvas ( ) ;
2023-06-27 15:47:34 -04:00
leTarget - > setText ( " 12C " ) ;
leBeam - > setText ( " d " ) ;
leRecoil - > setText ( " p " ) ;
sbBfield - > setValue ( 0.76 ) ;
sbAngle - > setValue ( 20 ) ;
sbEnergy - > setValue ( 16 ) ;
2023-10-20 17:57:03 -04:00
hit . CalConstants ( leTarget - > text ( ) . toStdString ( ) ,
leBeam - > text ( ) . toStdString ( ) ,
leRecoil - > text ( ) . toStdString ( ) , sbEnergy - > value ( ) , sbAngle - > value ( ) ) ;
2023-06-27 15:47:34 -04:00
2023-10-20 16:17:50 -04:00
hit . CalZoffset ( sbBfield - > value ( ) ) ;
2023-06-23 13:50:21 -04:00
hit . Clear ( ) ;
2023-06-12 16:41:03 -04:00
}
/// ~SplitPole(); // comment out = defalt destructor
2023-06-12 16:32:01 -04:00
void SetUpCanvas ( ) ;
2023-10-20 16:17:50 -04:00
void FillConstants ( ) ;
2023-06-12 16:32:01 -04:00
public slots :
void UpdateHistograms ( ) ;
private :
2023-06-14 15:41:26 -04:00
MultiBuilder * evtbder ;
2023-06-12 16:32:01 -04:00
2023-06-12 16:41:03 -04:00
// declaie histograms
2023-06-23 13:50:21 -04:00
Histogram2D * hPID ;
2023-06-12 16:32:01 -04:00
Histogram1D * h1 ;
2023-06-23 13:50:21 -04:00
Histogram1D * h1g ;
Histogram1D * hMulti ;
2023-06-12 16:32:01 -04:00
2023-06-20 11:57:39 -04:00
int tick2ns ;
2023-06-23 13:50:21 -04:00
SplitPoleHit hit ;
2023-06-27 15:47:34 -04:00
RSpinBox * sbBfield ;
QLineEdit * leTarget ;
QLineEdit * leBeam ;
QLineEdit * leRecoil ;
RSpinBox * sbEnergy ;
RSpinBox * sbAngle ;
2023-08-28 15:02:56 -04:00
QCheckBox * runAnalyzer ;
2023-10-20 16:17:50 -04:00
QLineEdit * leMassTablePath ;
QLineEdit * leQValue ;
QLineEdit * leGSRho ;
QLineEdit * leZoffset ;
2023-06-12 16:32:01 -04:00
} ;
2023-10-20 16:17:50 -04:00
inline void SplitPole : : FillConstants ( ) {
leQValue - > setText ( QString : : number ( hit . GetQ0 ( ) ) ) ;
leGSRho - > setText ( QString : : number ( hit . GetRho0 ( ) ) ) ;
leZoffset - > setText ( QString : : number ( hit . GetZoffset ( ) ) ) ;
}
2023-06-12 16:32:01 -04:00
2023-06-12 16:41:03 -04:00
inline void SplitPole : : SetUpCanvas ( ) {
2023-06-23 13:50:21 -04:00
setGeometry ( 0 , 0 , 1600 , 1000 ) ;
2023-06-12 16:41:03 -04:00
2023-06-27 15:47:34 -04:00
{ //^====== magnet and reaction setting
QGroupBox * box = new QGroupBox ( " Configuration " , this ) ;
layout - > addWidget ( box , 0 , 0 ) ;
QGridLayout * boxLayout = new QGridLayout ( box ) ;
boxLayout - > setAlignment ( Qt : : AlignTop | Qt : : AlignLeft ) ;
box - > setLayout ( boxLayout ) ;
QLabel * lbBfield = new QLabel ( " B-field [T] " , box ) ;
lbBfield - > setAlignment ( Qt : : AlignRight | Qt : : AlignCenter ) ;
boxLayout - > addWidget ( lbBfield , 0 , 2 ) ;
sbBfield = new RSpinBox ( box ) ;
sbBfield - > setDecimals ( 3 ) ;
sbBfield - > setSingleStep ( 0.05 ) ;
boxLayout - > addWidget ( sbBfield , 0 , 3 ) ;
QLabel * lbTarget = new QLabel ( " Target " , box ) ;
lbTarget - > setAlignment ( Qt : : AlignRight | Qt : : AlignCenter ) ;
boxLayout - > addWidget ( lbTarget , 0 , 0 ) ;
leTarget = new QLineEdit ( box ) ;
boxLayout - > addWidget ( leTarget , 0 , 1 ) ;
QLabel * lbBeam = new QLabel ( " Beam " , box ) ;
lbBeam - > setAlignment ( Qt : : AlignRight | Qt : : AlignCenter ) ;
boxLayout - > addWidget ( lbBeam , 1 , 0 ) ;
leBeam = new QLineEdit ( box ) ;
boxLayout - > addWidget ( leBeam , 1 , 1 ) ;
QLabel * lbRecoil = new QLabel ( " Recoil " , box ) ;
lbRecoil - > setAlignment ( Qt : : AlignRight | Qt : : AlignCenter ) ;
boxLayout - > addWidget ( lbRecoil , 2 , 0 ) ;
leRecoil = new QLineEdit ( box ) ;
boxLayout - > addWidget ( leRecoil , 2 , 1 ) ;
QLabel * lbEnergy = new QLabel ( " Beam Energy [MeV] " , box ) ;
lbEnergy - > setAlignment ( Qt : : AlignRight | Qt : : AlignCenter ) ;
boxLayout - > addWidget ( lbEnergy , 1 , 2 ) ;
sbEnergy = new RSpinBox ( box ) ;
sbEnergy - > setDecimals ( 3 ) ;
sbEnergy - > setSingleStep ( 1.0 ) ;
boxLayout - > addWidget ( sbEnergy , 1 , 3 ) ;
QLabel * lbAngle = new QLabel ( " SPS Angle [Deg] " , box ) ;
lbAngle - > setAlignment ( Qt : : AlignRight | Qt : : AlignCenter ) ;
boxLayout - > addWidget ( lbAngle , 2 , 2 ) ;
sbAngle = new RSpinBox ( box ) ;
sbAngle - > setDecimals ( 3 ) ;
sbAngle - > setSingleStep ( 1.0 ) ;
boxLayout - > addWidget ( sbAngle , 2 , 3 ) ;
boxLayout - > setColumnStretch ( 0 , 1 ) ;
boxLayout - > setColumnStretch ( 1 , 2 ) ;
boxLayout - > setColumnStretch ( 2 , 1 ) ;
boxLayout - > setColumnStretch ( 3 , 2 ) ;
connect ( leTarget , & QLineEdit : : returnPressed , this , [ = ] ( ) {
2023-10-20 17:57:03 -04:00
hit . CalConstants ( leTarget - > text ( ) . toStdString ( ) ,
leBeam - > text ( ) . toStdString ( ) ,
leRecoil - > text ( ) . toStdString ( ) , sbAngle - > value ( ) , sbEnergy - > value ( ) ) ;
2023-10-20 16:17:50 -04:00
hit . CalZoffset ( sbBfield - > value ( ) ) ;
FillConstants ( ) ;
2023-06-27 15:47:34 -04:00
} ) ;
connect ( leBeam , & QLineEdit : : returnPressed , this , [ = ] ( ) {
2023-10-20 17:57:03 -04:00
hit . CalConstants ( leTarget - > text ( ) . toStdString ( ) ,
leBeam - > text ( ) . toStdString ( ) ,
leRecoil - > text ( ) . toStdString ( ) , sbAngle - > value ( ) , sbEnergy - > value ( ) ) ;
2023-10-20 16:17:50 -04:00
hit . CalZoffset ( sbBfield - > value ( ) ) ;
FillConstants ( ) ;
2023-06-27 15:47:34 -04:00
} ) ;
connect ( leRecoil , & QLineEdit : : returnPressed , this , [ = ] ( ) {
2023-10-20 17:57:03 -04:00
hit . CalConstants ( leTarget - > text ( ) . toStdString ( ) ,
leBeam - > text ( ) . toStdString ( ) ,
leRecoil - > text ( ) . toStdString ( ) , sbAngle - > value ( ) , sbEnergy - > value ( ) ) ;
2023-10-20 16:17:50 -04:00
hit . CalZoffset ( sbBfield - > value ( ) ) ;
FillConstants ( ) ;
2023-06-27 15:47:34 -04:00
} ) ;
connect ( sbBfield , & RSpinBox : : returnPressed , this , [ = ] ( ) {
2023-10-20 17:57:03 -04:00
hit . CalConstants ( leTarget - > text ( ) . toStdString ( ) ,
leBeam - > text ( ) . toStdString ( ) ,
leRecoil - > text ( ) . toStdString ( ) , sbAngle - > value ( ) , sbEnergy - > value ( ) ) ;
2023-10-20 16:17:50 -04:00
hit . CalZoffset ( sbBfield - > value ( ) ) ;
FillConstants ( ) ;
2023-06-27 15:47:34 -04:00
} ) ;
connect ( sbAngle , & RSpinBox : : returnPressed , this , [ = ] ( ) {
2023-10-20 17:57:03 -04:00
hit . CalConstants ( leTarget - > text ( ) . toStdString ( ) ,
leBeam - > text ( ) . toStdString ( ) ,
leRecoil - > text ( ) . toStdString ( ) , sbAngle - > value ( ) , sbEnergy - > value ( ) ) ;
2023-10-20 16:17:50 -04:00
hit . CalZoffset ( sbBfield - > value ( ) ) ;
FillConstants ( ) ;
2023-06-27 15:47:34 -04:00
} ) ;
connect ( sbEnergy , & RSpinBox : : returnPressed , this , [ = ] ( ) {
2023-10-20 17:57:03 -04:00
hit . CalConstants ( leTarget - > text ( ) . toStdString ( ) ,
leBeam - > text ( ) . toStdString ( ) ,
leRecoil - > text ( ) . toStdString ( ) , sbAngle - > value ( ) , sbEnergy - > value ( ) ) ;
2023-10-20 16:17:50 -04:00
hit . CalZoffset ( sbBfield - > value ( ) ) ;
FillConstants ( ) ;
2023-06-27 15:47:34 -04:00
} ) ;
2023-08-28 15:02:56 -04:00
runAnalyzer = new QCheckBox ( " Run Analyzer " , this ) ;
boxLayout - > addWidget ( runAnalyzer , 4 , 1 ) ;
2023-10-20 16:17:50 -04:00
QLabel * lbMassTablePath = new QLabel ( " Mass Table Path : " , box ) ;
lbMassTablePath - > setAlignment ( Qt : : AlignRight | Qt : : AlignCenter ) ;
boxLayout - > addWidget ( lbMassTablePath , 5 , 0 ) ;
leMassTablePath = new QLineEdit ( QString : : fromStdString ( massData ) , box ) ;
leMassTablePath - > setEnabled ( false ) ;
boxLayout - > addWidget ( leMassTablePath , 5 , 1 , 1 , 3 ) ;
QLabel * lbQValue = new QLabel ( " Q-Value [MeV] " , box ) ;
lbQValue - > setAlignment ( Qt : : AlignRight | Qt : : AlignCenter ) ;
boxLayout - > addWidget ( lbQValue , 6 , 0 ) ;
leQValue = new QLineEdit ( box ) ;
leQValue - > setEnabled ( false ) ;
boxLayout - > addWidget ( leQValue , 6 , 1 ) ;
QLabel * lbGDRho = new QLabel ( " G.S. Rho [mm] " , box ) ;
lbGDRho - > setAlignment ( Qt : : AlignRight | Qt : : AlignCenter ) ;
boxLayout - > addWidget ( lbGDRho , 6 , 2 ) ;
leGSRho = new QLineEdit ( box ) ;
leGSRho - > setEnabled ( false ) ;
boxLayout - > addWidget ( leGSRho , 6 , 3 ) ;
QLabel * lbZoffset = new QLabel ( " Z-offset [mm] " , box ) ;
lbZoffset - > setAlignment ( Qt : : AlignRight | Qt : : AlignCenter ) ;
boxLayout - > addWidget ( lbZoffset , 7 , 0 ) ;
leZoffset = new QLineEdit ( box ) ;
leZoffset - > setEnabled ( false ) ;
boxLayout - > addWidget ( leZoffset , 7 , 1 ) ;
2023-06-27 15:47:34 -04:00
}
//============ histograms
hMulti = new Histogram1D ( " Multiplicity " , " " , 10 , 0 , 10 , this ) ;
layout - > addWidget ( hMulti , 0 , 1 ) ;
2023-06-12 16:41:03 -04:00
// the "this" make the histogram a child of the SplitPole class. When SplitPole destory, all childs destory as well.
2023-08-14 11:26:52 -04:00
hPID = new Histogram2D ( " Split Pole PID " , " Scin-L " , " Anode-Font " , 100 , 0 , 5000 , 100 , 0 , 5000 , this ) ;
2023-06-12 16:41:03 -04:00
//layout is inheriatge from Analyzer
2023-06-27 15:47:34 -04:00
layout - > addWidget ( hPID , 1 , 0 , 2 , 1 ) ;
2023-06-12 16:41:03 -04:00
2023-08-14 11:26:52 -04:00
h1 = new Histogram1D ( " Spectrum " , " x " , 300 , 30 , 70 , this ) ;
2023-06-23 13:50:21 -04:00
h1 - > SetColor ( Qt : : darkGreen ) ;
h1 - > AddDataList ( " Test " , Qt : : red ) ; // add another histogram in h1, Max Data List is 10
2023-06-27 15:47:34 -04:00
layout - > addWidget ( h1 , 1 , 1 ) ;
2023-06-20 11:57:39 -04:00
2023-08-14 11:26:52 -04:00
h1g = new Histogram1D ( " Spectrum (gated) " , " x " , 300 , 30 , 70 , this ) ;
2023-06-27 15:47:34 -04:00
layout - > addWidget ( h1g , 2 , 1 ) ;
layout - > setColumnStretch ( 0 , 1 ) ;
layout - > setColumnStretch ( 1 , 1 ) ;
2023-06-12 16:41:03 -04:00
}
inline void SplitPole : : UpdateHistograms ( ) {
2023-08-28 15:02:56 -04:00
if ( this - > isVisible ( ) = = false ) return ;
if ( runAnalyzer - > isChecked ( ) = = false ) return ;
2023-06-12 16:41:03 -04:00
BuildEvents ( ) ; // call the event builder to build events
//============ Get events, and do analysis
2023-06-14 15:41:26 -04:00
long eventBuilt = evtbder - > eventBuilt ;
2023-06-12 16:41:03 -04:00
if ( eventBuilt = = 0 ) return ;
2023-06-20 11:57:39 -04:00
//============ Get the cut list, if any
2023-06-23 13:50:21 -04:00
QList < QPolygonF > cutList = hPID - > GetCutList ( ) ;
2023-06-20 11:57:39 -04:00
const int nCut = cutList . count ( ) ;
unsigned long long tMin [ nCut ] = { 0xFFFFFFFFFFFFFFFF } , tMax [ nCut ] = { 0 } ;
unsigned int count [ nCut ] = { 0 } ;
//============ Processing data and fill histograms
2023-06-14 15:41:26 -04:00
long eventIndex = evtbder - > eventIndex ;
2023-06-12 16:41:03 -04:00
long eventStart = eventIndex - eventBuilt + 1 ;
if ( eventStart < 0 ) eventStart + = MaxNEvent ;
2023-06-20 11:57:39 -04:00
2023-06-12 16:41:03 -04:00
for ( long i = eventStart ; i < = eventIndex ; i + + ) {
2023-06-23 13:50:21 -04:00
std : : vector < Hit > event = evtbder - > events [ i ] ;
2023-06-20 11:57:39 -04:00
//printf("-------------- %ld\n", i);
2023-06-23 13:50:21 -04:00
hMulti - > Fill ( ( int ) event . size ( ) ) ;
//if( event.size() < 9 ) return;
if ( event . size ( ) = = 0 ) return ;
hit . Clear ( ) ;
2023-06-12 16:41:03 -04:00
for ( int k = 0 ; k < ( int ) event . size ( ) ; k + + ) {
2023-06-20 11:57:39 -04:00
//event[k].Print();
2023-10-16 16:07:14 -04:00
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 ; }
2023-06-12 16:41:03 -04:00
}
2023-06-23 13:50:21 -04:00
hit . CalData ( ) ;
2023-06-20 11:57:39 -04:00
2023-06-23 13:50:21 -04:00
hPID - > Fill ( hit . eSL , hit . eSR ) ; // x, y
2023-06-20 11:57:39 -04:00
2023-06-23 13:50:21 -04:00
h1 - > Fill ( hit . eSL ) ;
h1 - > Fill ( hit . eSR , 1 ) ;
//check events inside any Graphical cut and extract the rate, using tSR only
2023-06-20 11:57:39 -04:00
for ( int p = 0 ; p < cutList . count ( ) ; p + + ) {
if ( cutList [ p ] . isEmpty ( ) ) continue ;
2023-06-23 13:50:21 -04:00
if ( cutList [ p ] . containsPoint ( QPointF ( hit . eSL , hit . eSR ) , Qt : : OddEvenFill ) ) {
if ( hit . tSR < tMin [ p ] ) tMin [ p ] = hit . tSR ;
if ( hit . tSR > tMax [ p ] ) tMax [ p ] = hit . tSR ;
2023-06-20 11:57:39 -04:00
count [ p ] + + ;
//printf(".... %d \n", count[p]);
2023-06-23 13:50:21 -04:00
if ( p = = 0 ) h1g - > Fill ( hit . eSR ) ;
2023-06-20 11:57:39 -04:00
}
}
2023-06-12 16:41:03 -04:00
}
2023-06-23 13:50:21 -04:00
hPID - > UpdatePlot ( ) ;
2023-06-12 16:41:03 -04:00
h1 - > UpdatePlot ( ) ;
2023-06-23 13:50:21 -04:00
hMulti - > UpdatePlot ( ) ;
h1g - > UpdatePlot ( ) ;
2023-06-12 16:41:03 -04:00
2023-06-23 13:50:21 -04:00
QList < QString > cutNameList = hPID - > GetCutNameList ( ) ;
2023-06-20 11:57:39 -04:00
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 ( ) ;
}
2023-06-12 16:41:03 -04:00
}
2023-06-12 16:32:01 -04:00
# endif