19 #include <TVirtualFitter.h> 20 #include <TDatabasePDG.h> 23 #include <TPaveText.h> 54 fTypeOfFit4Bkg(
kExpo),
58 fTypeOfFit4Sgn(
kGaus),
68 fOnlySideBands(kFALSE),
69 fNSigma4SideBands(4.),
80 fFixRflOverSig(kFALSE),
195 AliError(
"Error in computing fNParsBkg: check fTypeOfFit4Bkg");
207 AliError(
"Error in computing fNParsSig: check fTypeOfFit4Sgn");
225 TVirtualFitter::SetDefaultFitter(
"Minuit");
232 printf(
"\n--- First fit with only background on the side bands - Exclusion region = %.2f sigma ---\n",
fNSigma4SideBands);
243 printf(
" ---> Failed first fit with only background, minuit status = %d\n",status);
254 printf(
"\n--- Estimate signal counts in the peak region ---\n");
271 printf(
" ---> Final fit includes a second inv. mass peak\n");
276 printf(
" ---> Final fit includes reflections\n");
283 printf(
"\n--- Final fit with signal+background on the full range ---\n");
286 printf(
" ---> Failed fit with signal+background, minuit status = %d\n",status);
301 fSecFunc->SetParameter(ipar,
fTotFunc->GetParameter(ipar+fNParsBkg+fNParsSig));
302 fSecFunc->SetParError(ipar,
fTotFunc->GetParError(ipar+fNParsBkg+fNParsSig));
331 if(doFinalFit)
return 1;
339 TCanvas* c0=
new TCanvas(
"c0");
347 gStyle->SetOptStat(0);
348 gStyle->SetCanvasColor(0);
349 gStyle->SetFrameFillColor(0);
362 if(writeFitInfo > 0){
363 TPaveText *pinfos=
new TPaveText(0.12,0.65,0.47,0.89,
"NDC");
364 TPaveText *pinfom=
new TPaveText(0.6,0.7,1.,.87,
"NDC");
365 pinfos->SetBorderSize(0);
366 pinfos->SetFillStyle(0);
367 pinfom->SetBorderSize(0);
368 pinfom->SetFillStyle(0);
370 pinfom->SetTextColor(kBlue);
382 pinfos->AddText(Form(
"B (%.0f#sigma) = %.0f #pm %.0f",nsigma,bkg,errbkg));
383 pinfos->AddText(Form(
"S/B = (%.0f#sigma) %.4f ",nsigma,
fRawYield/bkg));
385 pinfos->AddText(Form(
"Signif (%.0f#sigma) = %.1f #pm %.1f ",nsigma,signif,errsignif));
404 for(
Int_t ibin=binForMinSig; ibin<=binForMaxSig; ibin++){
408 Double_t diffUnderPeak=(sum-sumback);
409 printf(
" ---> IntegralUnderFitFunc=%f IntegralUnderHisto=%f EstimatedSignal=%f\n",sum,sumback,diffUnderPeak);
410 if(diffUnderPeak/TMath::Sqrt(sum)<1.){
411 printf(
" ---> (Tot-Bkg)/sqrt(Tot)=%f ---> Likely no signal/\n",diffUnderPeak/TMath::Sqrt(sum));
426 funcbkg->SetParNames(
"BkgInt",
"Slope");
427 funcbkg->SetParameters(integral,-2.);
430 funcbkg->SetParNames(
"BkgInt",
"Slope");
431 funcbkg->SetParameters(integral,-100.);
434 funcbkg->SetParNames(
"BkgInt",
"Coef1",
"Coef2");
435 funcbkg->SetParameters(integral,-10.,5);
438 funcbkg->SetParNames(
"Const");
439 funcbkg->SetParameter(0,0.);
440 funcbkg->FixParameter(0,0.);
443 funcbkg->SetParNames(
"BkgInt",
"Coef1");
444 funcbkg->SetParameters(integral,0.5);
447 funcbkg->SetParNames(
"Coef1",
"Coef2");
448 funcbkg->SetParameters(-10.,5.);
452 funcbkg->SetParName(j,Form(
"Coef%d",j));
453 funcbkg->SetParameter(j,0);
455 funcbkg->SetParameter(0,integral);
458 AliError(Form(
"Wrong choice of fTypeOfFit4Bkg (%d)",
fTypeOfFit4Bkg));
464 funcbkg->SetLineColor(kBlue+3);
473 funcsec->SetParameter(0,integsig);
478 funcsec->SetParNames(
"SecPeakInt",
"SecMean",
"SecSigma");
487 funcrfl->SetParLimits(0,0.,1.);
489 funcrfl->SetParNames(
"ReflOverS");
500 fbr->SetParameter(ipar,
fBkgFunc->GetParameter(ipar));
501 fbr->SetParName(ipar,
fBkgFunc->GetParName(ipar));
504 fbr->SetParameter(ipar+fNParsBkg,
fRflFunc->GetParameter(ipar));
505 fbr->SetParName(ipar+fNParsBkg,
fRflFunc->GetParName(ipar));
518 funcsig->SetParameter(0,integsig);
520 funcsig->SetParameter(1,
fMass);
524 funcsig->SetParNames(
"SgnInt",
"Mean",
"Sigma");
527 funcsig->SetParameter(0,integsig);
529 funcsig->SetParameter(1,
fMass);
532 funcsig->SetParLimits(2,0.004,0.05);
534 funcsig->SetParameter(3,0.2);
535 funcsig->SetParLimits(3,0.,1.);
537 funcsig->SetParLimits(4,0.004,0.05);
538 funcsig->SetParNames(
"SgnInt",
"Mean",
"Sigma1",
"Frac",
"Sigma2");
552 ftot->SetParameter(ipar,
fBkgFunc->GetParameter(ipar));
553 ftot->SetParName(ipar,
fBkgFunc->GetParName(ipar));
559 ftot->SetParameter(ipar+fNParsBkg,
fSigFunc->GetParameter(ipar));
560 ftot->SetParName(ipar+fNParsBkg,
fSigFunc->GetParName(ipar));
562 fSigFunc->GetParLimits(ipar,parmin,parmax);
563 ftot->SetParLimits(ipar+fNParsBkg,parmin,parmax);
567 ftot->SetParameter(ipar+fNParsBkg+fNParsSig,
fSecFunc->GetParameter(ipar));
568 ftot->SetParName(ipar+fNParsBkg+fNParsSig,
fSecFunc->GetParName(ipar));
570 fSecFunc->GetParLimits(ipar,parmin,parmax);
571 ftot->SetParLimits(ipar+fNParsBkg+fNParsSig,parmin,parmax);
576 ftot->SetParameter(ipar+fNParsBkg+fNParsSig+
fNParsSec,
fRflFunc->GetParameter(ipar));
579 fRflFunc->GetParLimits(ipar,parmin,parmax);
580 ftot->SetParLimits(ipar+fNParsBkg+fNParsSig+
fNParsSec,parmin,parmax);
611 total = par[0]*par[1]/(TMath::Exp(par[1]*
fMaxMass)-TMath::Exp(par[1]*
fMinMass))*TMath::Exp(par[1]*x[0]);
619 total= par[0]/(fMaxMass-
fMinMass)+par[1]*(x[0]-0.5*(fMaxMass+fMinMass));
630 total = par[0]/(fMaxMass-
fMinMass)+par[1]*(x[0]-0.5*(fMaxMass+fMinMass))+par[2]*(x[0]*x[0]-1/3.*(fMaxMass*fMaxMass*fMaxMass-fMinMass*fMinMass*fMinMass)/(fMaxMass-
fMinMass));
645 Double_t mpi = TDatabasePDG::Instance()->GetParticle(211)->Mass();
647 total = par[0]*(par[1]+1.)/(TMath::Power(fMaxMass-mpi,par[1]+1.)-TMath::Power(fMinMass-mpi,par[1]+1.))*TMath::Power(x[0]-mpi,par[1]);
655 Double_t mpi = TDatabasePDG::Instance()->GetParticle(211)->Mass();
657 total = par[0]*TMath::Sqrt(x[0] - mpi)*TMath::Exp(-1.*par[1]*(x[0]-mpi));
674 total+=par[it]*TMath::Power(x[0]-
fMassParticle,it)/TMath::Factorial(it);
696 sigval=par[0]/TMath::Sqrt(2.*TMath::Pi())/par[2]*TMath::Exp(-(x[0]-par[1])*(x[0]-par[1])/2./par[2]/par[2]);
707 Double_t g1=(1.-par[3])/TMath::Sqrt(2.*TMath::Pi())/par[2]*TMath::Exp(-(x[0]-par[1])*(x[0]-par[1])/2./par[2]/par[2]);
708 Double_t g2=par[3]/TMath::Sqrt(2.*TMath::Pi())/par[4]*TMath::Exp(-(x[0]-par[1])*(x[0]-par[1])/2./par[4]/par[4]);
709 sigval=par[0]*(g1+g2);
751 Double_t secgaval=par[0]/TMath::Sqrt(2.*TMath::Pi())/par[2]*TMath::Exp(-(x[0]-par[1])*(x[0]-par[1])/2./par[2]/par[2]);
765 return bkg+sig+sec+refl;
775 Signal(minMass,maxMass,signal,errsignal);
796 Background(minMass,maxMass,background,errbackground);
809 AliError(
"Bkg function not found!");
813 Double_t intB=funcbkg->GetParameter(0);
814 Double_t intBerr=funcbkg->GetParError(0);
822 for(
Int_t i=1;i<=leftBand;i++){
829 intBerr=TMath::Sqrt(sum2);
832 errbackground=intBerr/intB*background;
845 Significance(minMass, maxMass, significance, errsignificance);
879 TF1 *funcbkg,*funcPrev=0x0;
884 funcbkg->SetParameter(j,funcPrev->GetParameter(j));
889 funcbkg->SetParameter(0,estimatecent);
890 funcbkg->SetParameter(1,estimateslope);
892 printf(
" ---> Pre-fit of background with pol degree %d ---\n",
fCurPolDegreeBkg);
893 hCp->Fit(funcbkg,
"REMN",
"");
894 funcPrev=(TF1*)funcbkg->Clone(
"ftemp");
900 fback->SetParameter(j,funcPrev->GetParameter(j));
901 fback->SetParError(j,funcPrev->GetParError(j));
903 printf(
" ---> Final background fit with pol degree %d ---\n",
fPolDegreeBkg);
904 hCp->Fit(fback,
"REMN",
"");
932 back+=par[it]*TMath::Power(x[0]-
fMassParticle,it)/TMath::Factorial(it);
953 printf(
"\n--- Reflection templates from simulation ---\n");
954 if(opt.Contains(
"templ")){
955 printf(
" ---> Reflection contribution using directly the histogram from simulation\n");
961 Double_t xMinForFit=h->GetBinLowEdge(1);
962 Double_t xMaxForFit=h->GetXaxis()->GetBinUpEdge(h->GetNbinsX());
963 if(minRange>=0 && maxRange>=0){
964 xMinForFit=TMath::Max(minRange,h->GetBinLowEdge(1));
965 xMaxForFit=TMath::Min(maxRange,h->GetXaxis()->GetBinUpEdge(h->GetNbinsX()));
967 if(opt.EqualTo(
"1gaus") || opt.EqualTo(
"singlegaus")){
968 printf(
" ---> Reflection contribution from single-Gaussian fit to histogram from simulation\n");
969 f=
new TF1(
"mygaus",
"gaus",xMinForFit,xMaxForFit);
970 f->SetParameter(0,h->GetMaximum());
972 f->SetParameter(1,1.865);
973 f->SetParameter(2,0.050);
976 else if(opt.EqualTo(
"2gaus") || opt.EqualTo(
"doublegaus")){
977 printf(
" ---> Reflection contribution from double-Gaussian fit to histogram from simulation\n");
978 f=
new TF1(
"my2gaus",
"[0]*([3]/( TMath::Sqrt(2.*TMath::Pi())*[2])*TMath::Exp(-(x-[1])*(x-[1])/(2.*[2]*[2]))+(1.-[3])/( TMath::Sqrt(2.*TMath::Pi())*[5])*TMath::Exp(-(x-[4])*(x-[4])/(2.*[5]*[5])))",xMinForFit,xMaxForFit);
979 f->SetParameter(0,h->GetMaximum());
981 f->SetParLimits(3,0.,1.);
982 f->SetParameter(3,0.5);
983 f->SetParameter(1,1.84);
984 f->SetParameter(2,0.050);
985 f->SetParameter(4,1.88);
986 f->SetParameter(5,0.050);
989 else if(opt.EqualTo(
"pol3")){
990 printf(
" ---> Reflection contribution from pol3 fit to histogram from simulation\n");
991 f=
new TF1(
"mypol3",
"pol3",xMinForFit,xMaxForFit);
992 f->SetParameter(0,h->GetMaximum());
998 else if(opt.EqualTo(
"pol6")){
999 printf(
" ---> Reflection contribution from pol6 fit to histogram from simulation\n");
1000 f=
new TF1(
"mypol6",
"pol6",xMinForFit,xMaxForFit);
1001 f->SetParameter(0,h->GetMaximum());
1008 printf(
" ---> Bad option for reflection configuration -> reflections will not be included in the fit\n");
1019 if(
fHistoTemplRfl->GetBinContent(j)>=0.&&TMath::Abs(h->GetBinError(j)*h->GetBinError(j)-h->GetBinContent(j))>0.1*h->GetBinContent(j))isPoissErr=kFALSE;
1030 printf(
" ---> Fit to MC template for reflection failed -> reflections will not be included in the fit\n");
1051 massVal=TDatabasePDG::Instance()->GetParticle(pdgCode)->Mass();
1054 massVal=TDatabasePDG::Instance()->GetParticle(pdgCode)->Mass();
1055 massVal-=TDatabasePDG::Instance()->GetParticle(421)->Mass();
1076 printf(
"Left range for bin counting smaller than allowed by histogram axis, setting it to the lower edge of the first histo bin\n");
1080 printf(
"Right range for bin counting larger than allowed by histogram axis, setting it to the upper edge of the last histo bin\n");
1088 if(!fbackground)
return 0.;
1090 for(
Int_t jb=minBinSum; jb<=maxBinSum; jb++){
1096 cntSig+=(cntTot-cntBkg-cntRefl);
1099 errRyBC=TMath::Sqrt(cntErr);
1111 if(maxrange>minrange){
1118 hResidualTrend->SetName(Form(
"%s_residualTrend",
fHistoInvMass->GetName()));
1119 hResidualTrend->SetTitle(Form(
"%s (Residuals)",
fHistoInvMass->GetTitle()));
1120 hResidualTrend->SetMarkerStyle(20);
1121 hResidualTrend->SetMarkerSize(1.0);
1122 hResidualTrend->Reset();
1126 hPullsTrend->Reset();
1127 hPullsTrend->SetName(Form(
"%s_pullTrend",
fHistoInvMass->GetName()));
1128 hPullsTrend->SetTitle(Form(
"%s (Pulls)",
fHistoInvMass->GetTitle()));
1129 hPullsTrend->SetMarkerStyle(20);
1130 hPullsTrend->SetMarkerSize(1.0);
1134 hPulls->SetTitle(Form(
"%s ; Pulls",
fHistoInvMass->GetTitle()));
1135 hPulls->SetBins(40,-10,10);
1139 Double_t res=-1.e-6,min=1.e+12,max=-1.e+12;
1144 if(jst>=binmi&&jst<=binma){
1145 arval->AddAt(res,jst-binmi);
1151 hResidualTrend->SetBinContent(jst,res);
1152 hResidualTrend->SetBinError(jst,
fHistoInvMass->GetBinError(jst));
1155 if(jst>=binmi&&jst<=binma)hPulls->Fill(res/
fHistoInvMass->GetBinError(jst));
1158 hPullsTrend->SetBinContent(jst,res/
fHistoInvMass->GetBinError(jst));
1159 hPullsTrend->SetBinError(jst,0.0001);
1162 if(hResidualTrend)hResidualTrend->GetXaxis()->SetRange(binmi,binma);
1164 hPullsTrend->GetXaxis()->SetRange(binmi,binma);
1165 hPullsTrend->SetMinimum(-7);
1166 hPullsTrend->SetMaximum(+7);
1168 if(TMath::Abs(min)>TMath::Abs(max))max=min;
1170 TH1F *hout=
new TH1F(Form(
"%s_residuals",
fHistoInvMass->GetName()),Form(
"%s ; residuals",
fHistoInvMass->GetTitle()),25,-TMath::Abs(max)*1.5,TMath::Abs(max)*1.5);
1171 for(
Int_t j=0;j<binma-binmi+1;j++){
1172 hout->Fill(arval->At(j));
1175 hout->Fit(
"gaus",
"LEM",
"",-TMath::Abs(max)*1.2,TMath::Abs(max)*1.2);
1179 hPulls->Fit(
"gaus",
"LEM",
"",-3,3);
1189 printf(
"--- Background function in 1st step fit to side bands ---\n");
1193 printf(
"--- Total fit function from 2nd step fit ---\n");
1197 printf(
"--- Background function in 2nd step fit ---\n");
1201 printf(
"--- Reflections ---\n");
1205 printf(
"--- Background + reflections ---\n");
1209 printf(
"--- Additional Gaussian peak ---\n");
Int_t fTypeOfFit4Sgn
pdg value of particle mass
Double_t fSigmaSgnErr
signal gaussian sigma
Bool_t fFixSecWidth
flag to fix the position of the 2nd peak
Double_t fRawYieldHelp
switch for smoothing of reflection template
Double_t fRawYield
L, LW or Chi2.
void DrawHere(TVirtualPad *c, Double_t nsigma=3, Int_t writeFitInfo=1)
TF1 * CreateReflectionFunction(TString fname)
Int_t fCurPolDegreeBkg
degree of polynomial expansion for back fit (option 6 for back)
Bool_t PrepareHighPolFit(TF1 *fback)
Bool_t fOnlySideBands
fit parameters in background fit function
virtual void Signal(Double_t nOfSigma, Double_t &signal, Double_t &errsignal) const
Double_t FitFunction4SecPeak(Double_t *x, Double_t *par)
Double_t fMass
signal fit func
TF1 * CreateTotalFitFunction(TString fname)
Double_t fRawYieldErr
signal gaussian integral
Int_t MassFitter(Bool_t draw=kTRUE)
Int_t fNParsBkg
fit parameters in signal fit function
AliHFInvMassFitter class for the fit of invariant mass distribution of charm hadrons.
Int_t fNParsRfl
flag use/not use reflections
TF1 * CreateSecondPeakFunction(TString fname, Double_t integral)
TF1 * fTotFunc
fit function for second peak
Double_t fFixedRawYield
switch for fix Sigma of gaussian
Double_t FitFunction4Bkg(Double_t *x, Double_t *par)
Double_t fSigmaSgn
unc on signal gaussian mean value
Double_t fSecMass
fit parameters in 2nd peak fit function
Bool_t fFixSecMass
width of the 2nd peak
TF1 * fSecFunc
flag to fix the width of the 2nd peak
TH1F * GetResidualsAndPulls(TH1 *hPulls=0x0, TH1 *hResidualTrend=0x0, TH1 *hPullsTrend=0x0, Double_t minrange=0, Double_t maxrange=-1)
Double_t fSecWidth
position of the 2nd peak
TString fFitOption
number of sigmas to veto the signal peak
TF1 * fBkRFunc
fit function for reflections
Int_t fNParsSec
switch off/on second peak (for D+->KKpi in Ds)
TF1 * CreateSignalFitFunction(TString fname, Double_t integral)
Bool_t fFixedMean
unc on signal gaussian sigma
Double_t fMassParticle
help variable
Double_t FitFunction4Refl(Double_t *x, Double_t *par)
Double_t GetRawYieldBinCounting(Double_t &errRyBC, Double_t nSigma=3., Int_t option=0, Int_t pdgCode=0) const
TH1F * SetTemplateReflections(const TH1 *h, TString opt, Double_t minRange, Double_t maxRange)
Int_t fTypeOfFit4Bkg
upper mass limit
TH1F * fHistoTemplRfl
switch for fix refl/signal
TF1 * fBkgFunc
background fit function (1st step, side bands only)
Double_t fMassErr
signal gaussian mean value
Double_t fRflOverSig
fit parameters in reflection fit function
Double_t fMinMass
histogram to fit
Bool_t fFixRflOverSig
reflection/signal
static void ComputeSignificance(Double_t signal, Double_t errsignal, Double_t background, Double_t errbackground, Double_t &significance, Double_t &errsignificance)
Significance calculator.
Double_t FitFunction4Mass(Double_t *x, Double_t *par)
void Significance(Double_t nOfSigma, Double_t &significance, Double_t &errsignificance) const
Double_t BackFitFuncPolHelper(Double_t *x, Double_t *par)
Double_t fMaxMass
lower mass limit
TF1 * CreateBackgroundFitFunction(TString fname, Double_t integral)
TF1 * fRflFunc
internal variable for fit with reflections
Double_t fNSigma4SideBands
kTRUE = only side bands considered
void Background(Double_t nOfSigma, Double_t &background, Double_t &errbackground) const
Double_t FitFunction4Sgn(Double_t *x, Double_t *par)
Int_t fPolDegreeBkg
background fit func
TF1 * fBkgFuncRefit
background fit function (1st step, extended in peak region)
Double_t CheckForSignal(Double_t mean, Double_t sigma)
TF1 * fSigFunc
err on signal gaussian integral
TF1 * fBkgFuncSb
Signal fit function.
Bool_t fSecondPeak
fit function for reflections
Bool_t fSmoothRfl
histogram with reflection template
TF1 * CreateBackgroundPlusReflectionFunction(TString fname)
Double_t FitFunction4BkgAndRefl(Double_t *x, Double_t *par)
Int_t fNParsSig
initialization for wa yield
Bool_t fReflections
background fit function (2nd step)
Bool_t fFixedSigma
switch for fix mean of gaussian