From cd5df8686bd067f545e8789b7b0ad53e0ba330d5 Mon Sep 17 00:00:00 2001 From: flavigny <flavigny@lpccaen.in2p3.fr> Date: Tue, 22 Feb 2022 14:35:08 +0100 Subject: [PATCH] * Update 3-alpha source fit functions and procedure --- NPLib/Calibration/NPCalibrationSource.cxx | 243 +++++++++++++++++++--- NPLib/Calibration/NPCalibrationSource.h | 9 + NPLib/Calibration/NPSiliconCalibrator.cxx | 190 ++++++++++++++++- NPLib/Calibration/NPSiliconCalibrator.h | 2 +- 4 files changed, 409 insertions(+), 35 deletions(-) diff --git a/NPLib/Calibration/NPCalibrationSource.cxx b/NPLib/Calibration/NPCalibrationSource.cxx index e0a342291..482747079 100644 --- a/NPLib/Calibration/NPCalibrationSource.cxx +++ b/NPLib/Calibration/NPCalibrationSource.cxx @@ -7,6 +7,7 @@ //////////////////////////////////////////////////////////////////////////////// NPL::CalibrationSource::CalibrationSource(){ m_SourceSignal = 0 ; +m_FitFunctionType = 1 ; } //////////////////////////////////////////////////////////////////////////////// @@ -15,36 +16,224 @@ NPL::CalibrationSource::~CalibrationSource(){ //////////////////////////////////////////////////////////////////////////////// void NPL::CalibrationSource::ComputeSourceSignal(){ - TString contribution; - unsigned int arg_number = 0; - - for(unsigned int i = 0 ; i < m_Energies.size() ; i++){ - for(unsigned int j = 0 ; j < m_Energies[i].size() ; j++){ - contribution += - Form("(%f)*[%i]*exp(-(x-[%i]*%f)*(x-[%i]*%f)/(2*[%i]*[%i]))", - m_BranchingRatio[i][j]/m_BranchingRatio[i][0], arg_number, - arg_number+1, m_Energies[i][j]/m_Energies[i][0], - arg_number+1, m_Energies[i][j]/m_Energies[i][0], - arg_number+2,arg_number+2); - - if(j!=m_Energies[i].size()-1) contribution+="+"; - } - - arg_number+=3; - if(i!=m_Energies.size()-1) contribution+="+"; - } - - m_SourceSignal = new TF1("np_source_signal",contribution,0,1e9); - m_SourceSignal->SetNpx(20000); - arg_number = 0; - for(unsigned int i = 0 ; i < m_Energies.size() ; i++){ - m_SourceSignal->SetParameter(arg_number++,1000); - m_SourceSignal->SetParameter(arg_number++,5000+i*1000); - m_SourceSignal->SetParameter(arg_number++,20); - } + + + if (m_FitFunctionType == 0){ //3-alpha source golobal (8 gaussians) + m_SourceSignal = new TF1("AlphaSourceGauss",AlphaSourceGaus,0,1e9,23); + m_SourceSignal->SetNpx(20000); + + unsigned int arg_number = 0; + m_SourceSignal->SetParameter(arg_number++,10); + + for(unsigned int i = 0 ; i < m_Energies.size() ; i++){ + m_SourceSignal->SetParameter(arg_number++, 1000); //main peak amp + m_SourceSignal->SetParameter(arg_number++, 5000+i*1000); //main peak mean + for(unsigned int j = 0 ; j < m_Energies[i].size() ; j++){ + m_SourceSignal->SetParameter(arg_number++,m_BranchingRatio[i][j]/m_BranchingRatio[i][0]); + m_SourceSignal->SetParameter(arg_number++,m_Energies[i][j]/m_Energies[i][0]); + } + } + + } else if(m_FitFunctionType==1){// triplet of alpha peaks (3 gaussian with tail) + + //m_SourceSignal = new TF1("AlphaTriplet",AlphaTriplet,0,1e9,9); + m_SourceSignal = new TF1("AlphaTripletWithTail",AlphaTripletWithTwoTail,0,1e9,12); + m_SourceSignal->SetNpx(20000); + + unsigned int arg_number = 0; + + m_SourceSignal->SetParameter(arg_number++,1000); + m_SourceSignal->SetParameter(arg_number++,5000+1*1000); + m_SourceSignal->SetParameter(arg_number++,20); + m_SourceSignal->SetParameter(arg_number++,20); + m_SourceSignal->FixParameter(arg_number++,m_BranchingRatio[1][0]/m_BranchingRatio[1][0]); + m_SourceSignal->FixParameter(arg_number++,m_BranchingRatio[1][1]/m_BranchingRatio[1][0]); + m_SourceSignal->SetParameter(arg_number++,m_BranchingRatio[1][2]/m_BranchingRatio[1][0]); + m_SourceSignal->SetParameter(arg_number++,m_Energies[1][0]/m_Energies[1][0]); + m_SourceSignal->SetParameter(arg_number++,m_Energies[1][1]/m_Energies[1][0]); + m_SourceSignal->SetParameter(arg_number++,m_Energies[1][2]/m_Energies[1][0]); + m_SourceSignal->SetParLimits(9,0.95*m_Energies[1][2]/m_Energies[1][0],1.05*m_Energies[1][2]/m_Energies[1][0]); + m_SourceSignal->SetParameter(arg_number++,100); + //m_SourceSignal->SetParLimits(11,10,1000); + m_SourceSignal->FixParameter(arg_number++,0.4); + //m_SourceSignal->SetParLimits(11,0.35,0.45); + } + else if (m_FitFunctionType == 2){//old way, inline i definition, 8 gaussians. + TString contribution; + unsigned int arg_number = 0; + + for(unsigned int i = 0 ; i < m_Energies.size() ; i++){ + for(unsigned int j = 0 ; j < m_Energies[i].size() ; j++){ + contribution += + Form("(%f)*[%i]*exp(-(x-[%i]*%f)*(x-[%i]*%f)/(2*[%i]*[%i]))", + m_BranchingRatio[i][j]/m_BranchingRatio[i][0], arg_number, + arg_number+1, m_Energies[i][j]/m_Energies[i][0], + arg_number+1, m_Energies[i][j]/m_Energies[i][0], + arg_number+2,arg_number+2); + if(j!=m_Energies[i].size()-1) contribution+="+"; + } + + arg_number+=3; + if(i!=m_Energies.size()-1) contribution+="+"; + } + + m_SourceSignal = new TF1("np_source_signal",contribution,0,1e9); + m_SourceSignal->SetNpx(20000); + arg_number = 0; + for(unsigned int i = 0 ; i < m_Energies.size() ; i++){ + m_SourceSignal->SetParameter(arg_number++,1000); + m_SourceSignal->SetParameter(arg_number++,5000+i*1000); + m_SourceSignal->SetParameter(arg_number++,20); + } + } } +//////////////////////////////////////////////////////////////////////////////// +double AlphaSourceGaus(double *x,double *p) +{ + // eight gaussians: (3 for 239Pu, 3 for 241Am, 2 for Cm244) + // same sigma for all gaussians + + //p0 = sigma of all peaks + + //239 Pu + //p1 = amplitude of most intense peak + //p2 = mean of most intense peak + //p3 = relative scaling in amplitude + //p4 = relative scaling in mean for main peak + //p5 = relative scaling in amplitude for second peak + //p6 = relative scaling in mean for second peak + //p7 = relative scaling in amplitude for third peak + //p8 = relative scaling in mean for third peak + //241 Am + //p9 = amplitude of most intense peak + //p10 = mean of most intense peak + //p2 = sigma of most intense peak + //p11 = relative scaling in amplitude + //p12 = relative scaling in mean for main peak + //p13 = relative scaling in amplitude for second peak + //p14 = relative scaling in mean for second peak + //p15 = relative scaling in amplitude for third peak + //p16 = relative scaling in mean for third peak + //244 Cm + //p17 = amplitude of most intense peak + //p18 = mean of most intense peak + //p2 = sigma of most intense peak + //p19 = relative scaling in amplitude + //p20 = relative scaling in mean for main peak + //p21 = relative scaling in amplitude for second peak + //p22 = relative scaling in mean for second peak + double arg = 0; + double fitval = 0; + int ngaus = 8; + int k = 0; + int rest = 0; + + if (p[2]==0) {cout<<"sigma=0 in AlphaTripletGaus"<<endl; return fitval;} + + for(int i=0; i<ngaus; i++){ + rest = i%3; + if (i!=0 && rest==0) k++; + arg = (x[0] - p[2+k*ngaus]*p[4+k*ngaus+2*rest])/p[0]; + fitval += p[1+k*ngaus]*p[3+k*ngaus+2*rest]*TMath::Exp(-0.5*arg*arg); + } + + return fitval; +} +//////////////////////////////////////////////////////////////////////////////// +double AlphaTripletGaus(double *x,double *p) +{ + // eight gaussians, same sigma + //p0 = amplitude of most intense peak + //p1 = mean of most intense peak + //p2 = sigma most intense peak + //p3 = relative scaling in amplitude + //p4 = relative scaling in mean for main peak + //p5 = relative scaling in amplitude for second peak + //p6 = relative scaling in mean for second peak + //p7 = relative scaling in amplitude for third peak + //p8 = relative scaling in mean for third peak + double arg = 0; + if (p[2]!=0) arg = (x[0] - p[1]*p[4])/p[2]; + double fitval = p[0]*p[3]*TMath::Exp(-0.5*arg*arg); + if (p[2]!=0) arg = (x[0] - p[1]*p[6])/p[2]; + fitval += p[0]*p[5]*TMath::Exp(-0.5*arg*arg); + if (p[2]!=0) arg = (x[0] - p[1]*p[8])/p[2]; + fitval += p[0]*p[7]*TMath::Exp(-0.5*arg*arg); + return fitval; +} +//////////////////////////////////////////////////////////////////////////////// +double AlphaTripletWithTail(double *x,double *p) +{ + //p0 = area + //p1 = mean + //p2 = sigma + //p3 = tail + //p4 = amplitude scaling first peak + //p5 = amplitude scaling second peak + //p6 = amplitude scaling third peak + //p7 = energy scaling first peak + //p8 = energy scaling second peak + //p9 = energy scaling third peak + double arg1 = 0, arg2 = 0, arg3=0, arg4=0, arg5=0, arg6=0; + if (p[2]!=0 && p[3]!=0) { + arg1 = (x[0] - p[1]*p[7])/p[3] + p[2]*p[2]/(2*p[3]*p[3]); + arg2 = ( (x[0] - p[1]*p[7])/p[2] + p[2]/p[3] )/TMath::Sqrt(2); + + arg3 = (x[0] - p[1]*p[8])/p[3] + p[2]*p[2]/(2*p[3]*p[3]); + arg4 = ( (x[0] - p[1]*p[8])/p[2] + p[2]/p[3] )/TMath::Sqrt(2); + + arg5 = (x[0] - p[1]*p[9])/p[3] + p[2]*p[2]/(2*p[3]*p[3]); + arg6 = ( (x[0] - p[1]*p[9])/p[2] + p[2]/p[3] )/TMath::Sqrt(2); + } + double fitval = p[0]/(2*p[3])*p[4]*TMath::Exp(arg1)*TMath::Erfc(arg2) + + p[0]/(2*p[3])*p[5]*TMath::Exp(arg3)*TMath::Erfc(arg4) + + p[0]/(2*p[3])*p[6]*TMath::Exp(arg5)*TMath::Erfc(arg6); + return fitval; +} +//////////////////////////////////////////////////////////////////////////////// +double AlphaTripletWithTwoTail(double *x,double *p) +{ + //p0 = area + //p1 = mean + //p2 = sigma + //p3 = tail + //p4 = amplitude scaling first peak + //p5 = amplitude scaling second peak + //p6 = amplitude scaling third peak + //p7 = energy scaling first peak + //p8 = energy scaling second peak + //p9 = energy scaling third peak + //p10 = tail2 + //p11 = eta + double arg1 = 0, arg2 = 0, arg3=0, arg4=0, arg5=0, arg6=0; + double arg1b = 0, arg2b = 0, arg3b=0, arg4b=0, arg5b=0, arg6b=0; + if (p[2]!=0 && p[3]!=0) { + arg1 = (x[0] - p[1]*p[7])/p[3] + p[2]*p[2]/(2*p[3]*p[3]); + arg2 = ( (x[0] - p[1]*p[7])/p[2] + p[2]/p[3] )/TMath::Sqrt(2); + arg1b = (x[0] - p[1]*p[7])/p[10] + p[2]*p[2]/(2*p[10]*p[10]); + arg2b = ( (x[0] - p[1]*p[7])/p[2] + p[2]/p[10] )/TMath::Sqrt(2); + + arg3 = (x[0] - p[1]*p[8])/p[3] + p[2]*p[2]/(2*p[3]*p[3]); + arg4 = ( (x[0] - p[1]*p[8])/p[2] + p[2]/p[3] )/TMath::Sqrt(2); + arg3b = (x[0] - p[1]*p[8])/p[10] + p[2]*p[2]/(2*p[10]*p[10]); + arg4b = ( (x[0] - p[1]*p[8])/p[2] + p[2]/p[10] )/TMath::Sqrt(2); + + arg5 = (x[0] - p[1]*p[9])/p[3] + p[2]*p[2]/(2*p[3]*p[3]); + arg6 = ( (x[0] - p[1]*p[9])/p[2] + p[2]/p[3] )/TMath::Sqrt(2); + arg5b = (x[0] - p[1]*p[9])/p[10] + p[2]*p[2]/(2*p[10]*p[10]); + arg6b = ( (x[0] - p[1]*p[9])/p[2] + p[2]/p[10] )/TMath::Sqrt(2); + } + double fitval = + p[0]/2*p[4]*((1-p[11])/p[3]*TMath::Exp(arg1)*TMath::Erfc(arg2) + + p[11]/p[10]*TMath::Exp(arg1b)*TMath::Erfc(arg2b)) + + p[0]/2*p[5]*((1-p[11])/p[3]*TMath::Exp(arg3)*TMath::Erfc(arg4) + + p[11]/p[10]*TMath::Exp(arg3b)*TMath::Erfc(arg4b)) + + p[0]/2*p[6]*((1-p[11])/p[3]*TMath::Exp(arg5)*TMath::Erfc(arg6) + + p[11]/p[10]*TMath::Exp(arg5b)*TMath::Erfc(arg6b)); + return fitval; +} //////////////////////////////////////////////////////////////////////////////// TF1* NPL::CalibrationSource::GetSourceSignal(){ if(!m_SourceSignal) diff --git a/NPLib/Calibration/NPCalibrationSource.h b/NPLib/Calibration/NPCalibrationSource.h index b7919854e..9bca6fa24 100644 --- a/NPLib/Calibration/NPCalibrationSource.h +++ b/NPLib/Calibration/NPCalibrationSource.h @@ -14,6 +14,11 @@ using namespace std; // NPL #include "NPEnergyLoss.h" +double AlphaSourceGaus(double *,double *); +double AlphaTripletGaus(double *,double *); +double AlphaTripletWithTail(double *,double *); +double AlphaTripletWithTwoTail(double *,double *); + namespace NPL{ class CalibrationSource{ @@ -26,6 +31,7 @@ namespace NPL{ vector< vector<double> > m_Energies; vector< vector<double> > m_BranchingRatio; vector< vector<double> > m_ErrEnergies; + int m_FitFunctionType; private: // Computed source signal (a TF1 ready for fit use, set up with physical value) TF1* m_SourceSignal; @@ -33,6 +39,8 @@ namespace NPL{ public: // Getter and Setter TF1* GetSourceSignal(); + void SetFitFunctionType(int type){m_FitFunctionType=type;}; + int GetFitFunctionType(){return m_FitFunctionType;}; public: // Get and Set the energies // for particle like source (one gaussian per energies) @@ -50,5 +58,6 @@ namespace NPL{ void Set_244Cm(); }; + } #endif diff --git a/NPLib/Calibration/NPSiliconCalibrator.cxx b/NPLib/Calibration/NPSiliconCalibrator.cxx index 2cfb5961a..3658708db 100644 --- a/NPLib/Calibration/NPSiliconCalibrator.cxx +++ b/NPLib/Calibration/NPSiliconCalibrator.cxx @@ -24,7 +24,7 @@ NPL::SiliconCalibrator::~SiliconCalibrator(){ } ////////////////////////////////////////////// -double NPL::SiliconCalibrator::ZeroExtrapolation(TH1* histo, NPL::CalibrationSource* CS, NPL::EnergyLoss* EL, vector<double>& coeff, unsigned int pedestal, unsigned int max_iteration, double rmin,double rmax){ +double NPL::SiliconCalibrator::ZeroExtrapolation(TH1* histo, NPL::CalibrationSource* CS, NPL::EnergyLoss* EL, vector<double>& coeff, double pedestal, unsigned int max_iteration, double rmin,double rmax){ if(histo->GetEntries()==0){ coeff.clear(); coeff.push_back(0); @@ -63,7 +63,8 @@ double NPL::SiliconCalibrator::ZeroExtrapolation(TH1* histo, NPL::CalibrationSou bool LastStepDecrease = false; // 0.1% precision on the total scale (typically 6 MeV ) - double my_precision = (rmax-pedestal)*0.001; + //double my_precision = (rmax-pedestal)*0.001; + double my_precision = 1; // Energy of the Source and sigma on the value (MeV) double Assume_Thickness = 0 ; // micrometer vector<double> Assume_E; // Energie calculated assuming Assume_Thickness deadlayer of Al @@ -96,15 +97,17 @@ double NPL::SiliconCalibrator::ZeroExtrapolation(TH1* histo, NPL::CalibrationSou g->SetPoint(i,x[i] ,Assume_E[i]); } - DistanceToPedestal = FitPoints(g,&Assume_E[0], Source_Sig, coeff, 0 ); - + DistanceToPedestal = FitPoints(g,&Assume_E[0], Source_Sig, coeff, pedestal ); +/* + cout << "test " << histo->GetName() << ", Assume_Thick =" << Assume_Thickness / micrometer << "um with step "<< Step/micrometer << ", Dst to Pedestal = " << DistanceToPedestal <<", pedestal= "<<pedestal << endl; +*/ if(abs(DistanceToPedestal) < my_precision || Step < 0.01*micrometer){ break; } else if(DistanceToPedestal < 0 ){ if(LastStepIncrease) - Step *= 5; //multiply step by 5 + //Step *= 5; //multiply step by 5 Assume_Thickness += Step; LastStepIncrease = true; @@ -112,7 +115,7 @@ double NPL::SiliconCalibrator::ZeroExtrapolation(TH1* histo, NPL::CalibrationSou else if(DistanceToPedestal > 0 ){ if(LastStepDecrease) - Step *= 0.5; //decrease step by half + //Step *= 0.5; //decrease step by half Assume_Thickness -= Step; LastStepDecrease = true; @@ -249,7 +252,179 @@ TGraphErrors* NPL::SiliconCalibrator::FitSpectrum(TH1* histo, double rmin, doubl // sigma: must be >=1, higher sgma higher resolution // option: nobackground => Don't subtract back ground // threshold: look for peaks within range [HighespeakAmp*threshold ; HighespeakAmp] - Int_t nfound = sp.Search(histo,2,"",0.15); + Int_t nfound = sp.Search(histo,2,"",0.6); + //std::cout << "Number of peaks found = " << nfound << std::endl; // used for debugging + TSpectrumPosition_t xpeaks = sp.GetPositionX(); + + // order list of peaks + sort(xpeaks, xpeaks+nfound); + + m_FitFunction = m_CalibrationSource->GetSourceSignal(); + int FitFunctionType = m_CalibrationSource->GetFitFunctionType(); + if (nfound == 3) { + + if(FitFunctionType==0){ + // 3 * (triple gaussian (no tail)) + vector< vector<double> > Energies = m_CalibrationSource->GetEnergies(); + vector< vector<double> > ErrEnergies = m_CalibrationSource->GetEnergiesErrors(); + vector< vector<double> > BranchingRatio = m_CalibrationSource->GetBranchingRatio(); + + // ballpark the sigma + double sigma = (xpeaks[1]-xpeaks[0])/10; + m_FitFunction->FixParameter(0,sigma); + m_FitFunction->SetParLimits(0,0.1,sigma*3); + + int arg_number=1; + double H=0, Bratio=0, Eratio=0; + for(unsigned int i = 0 ; i < Energies.size() ; i++){ + H = histo->GetBinContent(histo->FindBin(xpeaks[i])); + m_FitFunction->SetParameter(arg_number,H ); //main peak amp + m_FitFunction->SetParLimits(arg_number, H*0.8, H*1.2 ); + arg_number++; + m_FitFunction->FixParameter(arg_number, xpeaks[i]); //main peak mean + //m_FitFunction->SetParLimits(arg_number, xpeaks[i]*0.99, xpeaks[i]*1.01); + arg_number++; + for(unsigned int j = 0 ; j < Energies[i].size() ; j++){ + Bratio = BranchingRatio[i][j]/BranchingRatio[i][0]; + Eratio = Energies[i][j]/Energies[i][0]; + m_FitFunction->FixParameter(arg_number,Bratio); + //m_FitFunction->SetParLimits(arg_number,Bratio*0.95,Bratio*1.05); + arg_number++; + m_FitFunction->SetParameter(arg_number,Eratio); + m_FitFunction->SetParLimits(arg_number,Eratio*0.998,Eratio*1.01); + arg_number++; + } + } + + // Set range and fit spectrum + histo->GetXaxis()->SetRangeUser(xpeaks[0]-xpeaks[0]/20.,xpeaks[2]+xpeaks[2]/20.); + histo->Fit(m_FitFunction,"MQR"); + TF1* fit = histo->GetFunction(m_FitFunction->GetName()); + std::cout << "sigma: " << fit->GetParameter(0)<< std::endl; + + // Graph energies(MeV) VS fitted peak channel and associated uncertainties + TGraphErrors* gre = new TGraphErrors(); + int point = 0 ; + for (unsigned int i = 0; i < Energies.size(); i++) { + gre->SetPoint(point, fit->GetParameter(2+8*i), Energies[i][0]); + gre->SetPointError(point++, fit->GetParError(2+8*i), ErrEnergies[i][0]); + } + //std::cout << "gre->GetN() = " << gre->GetN() << std::endl; // used for debugging + return gre; + + + } else if(FitFunctionType==1){// 3 * (triple gaussian with tail) + + //WORK IN PROGRESS (only one triplet fit) + double H2 = histo->GetBinContent(histo->FindBin(xpeaks[1])); + + m_FitFunction->SetParameter(0,H2*30); + m_FitFunction->SetParameter(1,xpeaks[1]); + double sigma = (xpeaks[1]-xpeaks[0])/50; + m_FitFunction->SetParameter(2,sigma); + m_FitFunction->SetParameter(3,sigma); //tail=sigma as a start + m_FitFunction->SetParameter(10,5*sigma); //tail2=5*sigma as a start + m_FitFunction->SetParLimits(10,2*sigma,10*sigma); //tail2=5*sigma as a start + // Set range and fit spectrum + //histo->GetXaxis()->SetRangeUser(xpeaks[0]-xpeaks[0]/20.,xpeaks[2]+xpeaks[2]/20.); + histo->GetXaxis()->SetRangeUser(xpeaks[1]-2000.,xpeaks[1]+1000); + histo->Fit(m_FitFunction,"MQR"); + TF1* fit = histo->GetFunction(m_FitFunction->GetName()); + + vector< vector<double> > Energies = m_CalibrationSource->GetEnergies(); + vector< vector<double> > ErrEnergies = m_CalibrationSource->GetEnergiesErrors(); + + TGraphErrors* gre = new TGraphErrors(); + int point = 0 ; + for (unsigned int i = 0; i < Energies.size(); i++) { + gre->SetPoint(point, fit->GetParameter(3*i+1), Energies[i][0]); + gre->SetPointError(point++, fit->GetParError(3*i+1), ErrEnergies[i][0]); + } + return gre; + + }else if(FitFunctionType==2){//old way + + // Set initial mean + m_FitFunction->SetParameter(1,xpeaks[0]); + m_FitFunction->SetParameter(4,xpeaks[1]); + m_FitFunction->SetParameter(7,xpeaks[2]); + + // Set Limit + m_FitFunction->SetParLimits(1,xpeaks[0]*0.8,xpeaks[0]*1.2); + m_FitFunction->SetParLimits(4,xpeaks[1]*0.8,xpeaks[1]*1.2); + m_FitFunction->SetParLimits(7,xpeaks[2]*0.8,xpeaks[2]*1.2); + + + // Set initial height + double H1 = histo->GetBinContent(histo->FindBin(xpeaks[0])); + double H2 = histo->GetBinContent(histo->FindBin(xpeaks[1])); + double H3 = histo->GetBinContent(histo->FindBin(xpeaks[2])); + + m_FitFunction->SetParameter(0,H1); + m_FitFunction->SetParameter(3,H2); + m_FitFunction->SetParameter(6,H3); + + // Set Limit + m_FitFunction->SetParLimits(0,H1*0.4,H1*2); + m_FitFunction->SetParLimits(3,H2*0.4,H2*2); + m_FitFunction->SetParLimits(6,H3*0.4,H3*2); + + // ballpark the sigma + double sigma = (xpeaks[1]-xpeaks[0])/10; + m_FitFunction->SetParameter(2,sigma); + m_FitFunction->SetParameter(5,sigma); + m_FitFunction->SetParameter(8,sigma); + + // Set Limit + m_FitFunction->SetParLimits(2,0,sigma*3); + m_FitFunction->SetParLimits(5,0,sigma*3); + m_FitFunction->SetParLimits(8,0,sigma*3); + + // Set range and fit spectrum + histo->GetXaxis()->SetRangeUser(xpeaks[0]-xpeaks[0]/20.,xpeaks[2]+xpeaks[2]/20.); + histo->Fit(m_FitFunction,"MQR"); + TF1* fit = histo->GetFunction(m_FitFunction->GetName()); + // energies and associated uncertainties + vector< vector<double> > Energies = m_CalibrationSource->GetEnergies(); + vector< vector<double> > ErrEnergies = m_CalibrationSource->GetEnergiesErrors(); + + // unsigned int mysize = Energies.size(); + TGraphErrors* gre = new TGraphErrors(); + int point = 0 ; + for (unsigned int i = 0; i < Energies.size(); i++) { + gre->SetPoint(point, fit->GetParameter(3*i+1), Energies[i][0]); + gre->SetPointError(point++, fit->GetParError(3*i+1), ErrEnergies[i][0]); + } + //std::cout << "gre->GetN() = " << gre->GetN() << std::endl; // used for debugging + return gre; + + } else{ //Fit functiuon type not 0,1 or 2 (undefined) + return (new TGraphErrors()); + } + + } + + else{ //nfound!=3 + return (new TGraphErrors()); + } +} +/* +TGraphErrors* NPL::SiliconCalibrator::FitSpectrum(TH1* histo, double rmin, double rmax) +{ +// for(unsigned int i = 0 ; i < histo->GetNbinsX() ; i++) +// if(histo->GetBinCenter(i)<rmin || histo->GetBinCenter(i)>rmax ) +// histo->SetBinContent(i,0); + + // apply range for peak search + histo->GetXaxis()->SetRangeUser(rmin, rmax); + // Perform a peak search to get a hint of where are the peaks + TSpectrum sp(4,1); // number of peaks is 4 to avoid warning of peak buffer + //arguments: + // hist : input histogram + // sigma: must be >=1, higher sgma higher resolution + // option: nobackground => Don't subtract back ground + // threshold: look for peaks within range [HighespeakAmp*threshold ; HighespeakAmp] + Int_t nfound = sp.Search(histo,2,"",0.6); //std::cout << "Number of peaks found = " << nfound << std::endl; // used for debugging TSpectrumPosition_t xpeaks = sp.GetPositionX(); @@ -317,5 +492,6 @@ TGraphErrors* NPL::SiliconCalibrator::FitSpectrum(TH1* histo, double rmin, doubl return (new TGraphErrors()); } } +*/ diff --git a/NPLib/Calibration/NPSiliconCalibrator.h b/NPLib/Calibration/NPSiliconCalibrator.h index eab6a935d..1b359a573 100644 --- a/NPLib/Calibration/NPSiliconCalibrator.h +++ b/NPLib/Calibration/NPSiliconCalibrator.h @@ -24,7 +24,7 @@ namespace NPL{ public: // Use the Zero Extrapolation method to perform fit and return the dead layer thickness - double ZeroExtrapolation(TH1* histo, NPL::CalibrationSource* CS, NPL::EnergyLoss* EL, vector<double>& coeff, unsigned int pedestal, unsigned int max_iteration = 10000 , double rmin=-1,double rmax=-1); + double ZeroExtrapolation(TH1* histo, NPL::CalibrationSource* CS, NPL::EnergyLoss* EL, vector<double>& coeff, double pedestal, unsigned int max_iteration = 10000 , double rmin=-1,double rmax=-1); double SimpleCalibration(TH1* histo, NPL::CalibrationSource* CS, NPL::EnergyLoss* EL, vector<double>& coeff, double Assume_Thickness=0,double rmin=-1,double rmax=-1); -- GitLab