1 #include "StFcsPulseAna.h"
7 if( x[0]<p[1] ){
return p[3];}
8 double xoff2 = (x[0]-p[1])*(x[0]-p[1]);
9 return p[0]*TMath::Sqrt( 2.0/TMath::Pi() )
10 *( xoff2 * exp((-1.0*xoff2)/(2.0*p[2]*p[2])) )
17 mName =
"StFcsPulseAna";
35 if( post_name ){ mName = old.mName+post_name; }
36 else{ mName = old.mName+
"_copy"; }
40 if( old.SignalFit()!=0 ){
mF1_SignalFit = (TF1*)old.SignalFit()->Clone( (mName+
"_F1_SignalFit").c_str() );}
45 if(
this == &rhs ){
return *
this; }
48 mName = rhs.
Name()+
"_copy";
52 if( rhs.SignalFit()!=0 ){
mF1_SignalFit = (TF1*)rhs.SignalFit()->Clone( (mName+
"_F1_SignalFit").c_str() ); }
61 mWindowSum =
false; mSumAdc=0;
62 mFitSum =
false; mSumAdcFit=0.0;
87 TGraph* cloneg = (TGraph*)this->
GetData()->Clone();
90 if( !strlen(newname) ){ ana =
new StFcsPulseAna(cloneg,mName+
"_copy"); }
139 mWindowSum=
false; mSumAdc = 0;
140 mFitSum=
false; mSumAdcFit = 0.0;
149 std::vector<PeakWindow> merged;
164 if( !merged.empty() ){ merged.clear(); }
165 for( UInt_t i=0; i<
mPeaks.size(); ++i){
167 if( merged.empty() ){ merged.push_back(win);
continue; }
168 if( win.
mStartX-merged.back().mEndX > 2.1 ){ merged.push_back(win);
continue;}
171 if( merged.empty() ){ merged.push_back(win);
continue; }
174 merged.back().Combine(win,thisprob<=nextprob?
true:
false);
176 else{ merged.push_back(win); }
185 for(
int ipoint=0; ipoint<this->
GetData()->GetN(); ++ipoint)
187 Double_t tb; Double_t adc;
188 Int_t check = this->
GetData()->GetPoint(ipoint,tb,adc);
189 if( check<0 ){ LOG_WARN <<
"Unable to find point " << ipoint <<
" in Signal graph" << endm;
continue;}
190 if( adc<0.1 ){
continue;}
206 LOG_WARN <<
"Unable to find a proper baseline" << endm;
209 <<
"->Setting baseline to 0 and sigma to 0.75 to prevent T0 algorithm from failing" << endm;}
222 LOG_DEBUG <<
"|BaselineValue:"<<
mBaseline;
232 if(
GetDebug()>2 ){ LOG_DEBUG <<
"|Height:"<<
mH1_Baseline->GetBinContent(XStartVal+1) <<
"|XStartVal:"<< XStartVal <<
"|Range:"<<3 <<
"|StartSigma:"<<0.9 << endm; }
242 if(
GetDebug()>1 ){ LOG_DEBUG <<
"|FitStatus:"<< FitStatus << endm; }
246 if( ratio > 10.0 ){
mBaseline = XStartVal;
return true; }
254 else if( FitStatus > 0 )
259 if(
GetDebug()>1){LOG_WARN <<
"Fit failed to converge setting baseline to mean of histogram and of sigma to 0.75" << endm;}
268 if( counter != 0 ){
return;}
269 unsigned int startpoint = 0;
272 for(
unsigned int ipoint=0;
static_cast<int>(ipoint)<g->GetN() && counter<8; ++ipoint ){
273 g->GetPoint(ipoint,tb,adc);
274 if(
int(tb)>=Start ){ startpoint=ipoint;
break; }
277 if( startpoint==0 || static_cast<Int_t>(startpoint+8)>=g->GetN() ){
return;}
278 while(
int(tb-(Start+counter)) < int(8-counter) ){
279 counter =
static_cast<unsigned short>(tb-Start);
280 adcdata[counter]=adc;
281 g->GetPoint(++startpoint,tb,adc);
288 unsigned short Size = 0;
289 unsigned short AdcData[8] = {0};
291 if( Size==0 ){
return 0;}
298 for(
int tb=0;tb<8;tb++) {
300 unsigned short radc = AdcData[tb] ;
309 if(radc>sum) peak = 1 ;
337 if(radc>=last && peak==0) {
344 if(sum < 0) sum = 0 ;
355 unsigned short Size = 0;
356 unsigned short AdcData[8] = {0};
358 if( Size==0 ){
return 0;}
365 for(
int tb=0;tb<8;tb++) {
367 unsigned short radc = AdcData[tb] ;
376 if(radc>sum) peak = 1 ;
397 if( peak!=0 || radc<last) peak = -1 ;
403 if( peak!=0 || radc<last ) peak = -1 ;
404 if( peak>0 ){ sum=0; }
409 if(sum < 0) sum = 0 ;
423 if( base < -4.0 ){
return SumAdc;}
425 for( Int_t ismp=0; ismp<this->
GetData()->GetN(); ++ismp )
427 Double_t tb; Double_t adc;
428 GetData()->GetPoint(ismp,tb,adc);
429 if( tb < Start ){
continue;}
430 if( tb > End ){
break; }
433 if(
GetDebug()>1 ){LOG_DEBUG <<
"|Start:"<<Start <<
"|End:"<<End <<
"|SumAdcB:"<< SumAdc; }
434 SumAdc -= base*abs(End-Start+1);
435 if(
GetDebug()>1 ){LOG_DEBUG <<
"|SumAdcA:"<< SumAdc <<
"|BaseArea:"<<base*abs(End-Start+1) << endm; }
441 if( mWindowSum ){
return mSumAdc; }
452 void StFcsPulseAna::GetMBPars(
const double& xpeak,
const double& xrise,
const double& yh,
const double& ped,
double& height,
double& scale )
462 scale = (xpeak-xrise)/TMath::Sqrt2();
463 height = ((yh-ped)*TMath::Sqrt(TMath::Pi()/2.0)*scale*TMath::E())/2.0;
476 double scale=0;
double height=0;
490 case 'g':
if( !mFitSum ){
GausFit(); }
break;
491 case 'm':
if( !mFitSum ){
MBFit(); }
break;
492 case 'p':
if( !mFitSum ){
PulseFit(); }
break;
500 if( mFitSum ){
return mSumAdcFit; }
503 if( base < -4.0 ){
return mSumAdcFit; }
512 mF1_SignalFit =
new TF1( (mName+
"_Gaus_"+
"mF1_SignalFit").c_str(),
"gaus(0)+[3]",Start,End);
517 mF1_SignalFit->SetParameter( 2, static_cast<Double_t>(End-Start)*0.2 );
528 if(
GetDebug()>2 ){LOG_DEBUG <<
"|FitStart:"<<FitStart <<
"|FitEnd:"<<FitEnd <<
"|FitSumB:"<<mSumAdcFit; }
529 mSumAdcFit -= ((FitEnd-FitStart)*base);
530 if(
GetDebug()>2 ){LOG_DEBUG <<
"|FitSumA:"<<mSumAdcFit <<
"|BaseArea:"<<((FitEnd-FitStart)*base) << endm; }
534 else{ mFitSum =
true;
return mSumAdcFit; }
539 if( mFitSum ){
return mSumAdcFit; }
542 if( base < -4.0 ){
return mSumAdcFit; }
553 Double_t height=1; Double_t scale=1;
565 char opt[10] =
"BNRQ";
571 if(
GetDebug()>2 ){LOG_DEBUG <<
"|FitStart:"<<Start <<
"|FitEnd:"<<End <<
"|FitSumB:"<<mSumAdcFit; }
572 mSumAdcFit -= ((End-Start)*base);
573 if(
GetDebug()>2 ){LOG_DEBUG <<
"|FitSumA:"<<mSumAdcFit <<
"|BaseArea:"<<((End-Start)*base) << endm; }
577 else{ mFitSum =
true;
return mSumAdcFit; }
582 if( mFitSum ){
return mSumAdcFit; }
584 if(
mDbPulse==0 ){LOG_ERROR <<
"No pulse object"<<endm;
return mSumAdcFit;}
586 if( base < -4.0 ){
return mSumAdcFit; }
600 for(
int i=0; i<npeak; i++){
607 char opt[10] =
"BNRQ";
614 if(
GetDebug()>2 ){LOG_DEBUG <<
"|FitStart:"<<Start <<
"|FitEnd:"<<End <<
"|FitSumB:"<<mSumAdcFit; }
615 mSumAdcFit -= ((End-Start)*base);
616 if(
GetDebug()>2 ){LOG_DEBUG <<
"|FitSumA:"<<mSumAdcFit <<
"|BaseArea:"<<((End-Start)*base) << endm; }
620 else{ mFitSum =
true;
return mSumAdcFit; }
626 func->FixParameter(0,0);
627 func->FixParameter(1,0);
632 if( start>=npeaks ){
return; }
633 if( end>=npeaks ){
return; }
634 if( start<0 ){ start = 0; }
635 if( end<0 ){ end = npeaks-1; }
636 if( start>end ){
return; }
638 npeaks = end-start+1;
642 if( npeaks>33 ){
return;}
643 double para[101] = {0};
646 func->SetParName(0,
"NPeaks");
647 func->SetParName(1,
"Ped");
648 for(
int i=0; i<npeaks; ++i ){
651 sprintf(name,
"P%d_A",start+i);
652 func->SetParName(j,name);
654 sprintf(name,
"P%d_M",start+i);
655 func->SetParName(j,name);
657 sprintf(name,
"P%d_S",start+i);
658 func->SetParName(j,name);
661 func->SetParameters(para);
663 func->FixParameter(0,npeaks);
665 for(
int i=0; i<npeaks; i++){
667 func->SetParLimits(j++,0.0,50000.0);
668 func->SetParLimits(j,para[j]-2.0,para[j]+2.0);
669 func->SetParLimits(++j,0.5,10.0);
676 ana->SetBit(kCanDelete);
687 std::cout <<
"|Name:"<<mName;
689 if( option.Contains(
"debug") ){
690 std::cout <<
"|P::Graph:"<<this->
GetData();
694 std::cout <<
"|P::DbPulse:"<<
mDbPulse;
696 std::cout <<
"|Flag::WindowSum:"<<mWindowSum;
697 std::cout <<
"|Flag::FitSum:"<<mFitSum;
702 std::cout <<
"|AdcSum:"<<mSumAdc;
703 std::cout <<
"|FitSum:"<<mSumAdcFit;
704 std::cout << std::endl;
virtual Int_t SearchForPeak(const std::vector< PeakWindow > &PossiblePeaks)
searches a vector of PeakWindow's for a specific peak based on input search criteria ...
Int_t mComputedIndex
Index in mPeaks where a peak was found.
virtual TGraphAsymmErrors * GetData() const
Overwrite from PeakAna to type convert for StFcsWaveformFitMaker.
void SignalMBPars(double &height, double &scale)
Figure out the height and scale of a Maxwell-Boltzmann distribution that approximates the signal...
StFcsDbPulse * mDbPulse
Pointer to StFcsDbPulse.
virtual TObject * Clone(const char *newname) const
Clones internal graph as opposed to just copying the pointer.
static int SumDep0Mod(TGraphAsymmErrors *gdata, int Start, int ped=0)
Test my modified sum method to DEP board.
TF1 * createPulse(double xlow=0, double xhigh=1, int npars=5)
Function to create pulse shape for FCS, 5 parameters is minimum.
Double_t MBFit(Int_t Start=0, Int_t End=0)
Fit a Maxwell-Boltzmann distribution to mFoundPeak and return the integral minus the baseline...
Double_t mBaselineSigma
Error on PeakAna::mBaseline.
const PeakWindow & GetPeak(UInt_t peakidx) const
Int_t FoundPeakIndex() const
Double_t PeakY()
y-value of found signal peak
void SetWindow(Double_t s, Double_t e)
virtual void SetData(TGraph *graph)
sets new data for PeakAna
virtual void MergeByProbability(std::vector< PeakWindow > &merged) const
Overwritten from PeakAna::MergeByProbability() to change merge criteria.
void ResetSum()
Only resets variables related to finding the sum.
TGraph * mG_Data
TGraph that stores the x,y data.
Double_t PeakX()
x-value of found signal peak
TF1 * mF1_BaselineFit
Gaussian function to fit to mH1_Baseline to determine baseline.
Double_t mXRangeMax
Absolute possible x-value maximum of data.
Double_t PulseFit(Int_t Start=0, Int_t End=0)
Fit the pulse shape defined in StFcsDbPulse::multiPulseShape() to all peaks and return the integral o...
Double_t PeakEnd()
Found Signal ending x-value.
Double_t GausFit(Int_t Start=0, Int_t End=0)
Do a Gaussian fit on mFoundPeak and return the integral subtracted by the baseline.
PeakWindow mFoundPeak
Copy of found peak in mPeaks.
virtual void Copy(TObject &obj) const
Internal method use Clone instead.
void AnalyzeForPedestal()
Analyze graph data to determine baseline internally.
static void GetMBPars(const double &xpeak, const double &xrise, const double &yh, const double &ped, double &height, double &scale)
Get parameters for a Maxwell Boltzmann distribution from above based on the 4 const parameters...
Double_t mPeakX
x-value of peak position as determined by SetPeak()
Double_t mTunnelSigma
Sigma for Gaussian for determining tunneling probability (default is 1) see #PeakWindow::PeakTunelPro...
static void FillAdc(TGraphAsymmErrors *g, unsigned short &counter, int Start, unsigned short *adcdata)
Needed for SumDep0, et al. It basically fills in tb vs. adc sequentially so all timebins from a given...
virtual void Copy(TObject &obj) const
Internal method use Clone instead.
virtual Int_t AnalyzeForPeak()
Main analysis method for finding peaks.
virtual void Print(Option_t *opt="") const
Prints information about PeakWindow.
virtual StFcsPulseAna * DrawCopy(Option_t *opt="", const char *name_postfix="_copy", TGraph *graph=0) const
Clone and draw, see PeakAna::Draw() for options.
Double_t PeakStart()
Found Signal starting x-value.
void ResetFinder()
Resets all histograms and values.
Int_t SumWindow()
Sum the ADC in the peak defined by mFoundPeak and subtract the baseline.
void Init()
Initialize everything to zero except signal and background histograms.
virtual void Print(Option_t *opt="") const
Print peak information.
void SetFitPars(TF1 *&func, int start=-1, int end=-1)
Set the parameters of an external TF1 function that has the form of StFcsDbPulse::multiPulseShape(), optionally only set fit paramaters for peaks from index start up to and including end.
virtual ~StFcsPulseAna()
Destructor.
bool FindBaseline()
Does Gaussian fitting to mH1_Baseline to determine baseline.
TH1F * BaselineHist() const
virtual void Print(Option_t *opt="") const
Print class variables.
double multiPulseShape(double *x, double *p)
Multi-pulse shape function constant+gaus+xexp+xexp for many pulses.
static int SumDep0(TGraphAsymmErrors *gdata, int Start, int ped=0)
Test of sum method in DEP board.
std::vector< PeakWindow > mPeaks
vector that stores all the found peaks in the data
Double_t mStartX
x value for start of the peak window
StFcsPulseAna()
Default constructor.
bool PeakTunnel(const PeakWindow &window) const
test whether a given peak satisifies peak tunnel parameters
TF1 * mF1_SignalFit
Function to fit to the data.
virtual Int_t AnalyzeForPeak()
Overwritten from PeakAna to process peak tunneling after finding all peaks.
Double_t Baseline() const
Double_t mTunnelScale
Scale on exponential for determining tunneling probability (default is 1) see #PeakWindow::PeakTunelP...
void ResetBaseline()
Resets baseline values.
StFcsPulseAna & operator=(const StFcsPulseAna &rhs)
Assignment operator.
TF1 * BaselineFit() const
Double_t mBaseline
Minimum threshold to search for a peak.
Double_t mTunnelThreshold
Cutoff probability for peak tunneling method. If threshold less than 0 (default) then skip peak tunne...
PeakAna & operator=(const PeakAna &rhs)
Assignment operator doesn't clone graph.
double SumMB()
Integral of an approximated Maxwell-Boltzmann distribution minus the baseline.
Double_t mPeakY
y-value at mP_Peak
TH1F * mH1_Baseline
Histogram that holds projection of mG_Data for baseline determination.
Int_t Sum(Int_t Start, Int_t End)
Add raw ADC within a given range and subtract the baseline.
virtual Double_t PeakTunnelProb(TGraph *graph, Double_t scale=1.0, Double_t sigma=1.0) const
Compute probablity that a given PeakWindow is a real peak.
Double_t mXRangeMin
Absolute possible x-value minimum of data.
PeakWindow mSearch
Variable that defines peak search parameters.
bool GoodWindow()
Check if found peak is inside mXRangeMin, mYRangeMin, mXRangeMax, mYRangeMax and has logical values...
static double MaxwellBoltzmannDist(double *x, double *p)
Maxwell Boltzmann Distribution function.