FairRoot/PandaRoot
fitsb.C
Go to the documentation of this file.
1 #include "TStyle.h"
2 #include "TString.h"
3 #include "TH1F.h"
4 #include "TF1.h"
5 #include "TPaveStats.h"
6 #include "TLatex.h"
7 #include "TPad.h"
8 #include "TList.h"
9 
10 const int maxdeg = 5;
11 
12 int fitsb(TH1 *h=0, TString type="", TString parms="", double A=0., double min=-999., double max = -999.)
13 {
14  gStyle->SetOptFit(112);
15  int i;
16  if (h==0)
17  {
18  cout <<"\nFits a distribution consisting of signal peak and background; prints out the integral of the signal in the fit region\n\n";
19  cout <<"USAGE:\nfitsb(TH1* h, <TString type>, <TString parms>, <double N>, <double min>, <double max>)\n";
20  cout <<" h : histogram pointer\n";
21  cout <<" <type> : default = \"gaus2\"; definition of fit function (gaus,bw,vgt,dgaus,bigaus,novo) and degree of bkg polyn (max=5, no number->no bkg, 8=argus fcn). E.g.: \"bw3\" = breit wigner + pol3\n";
22  cout <<" gaus = Gaussian; bw = Breit-Wigner; vgt = Voigt-Fcn; dgaus = Double Gaussian (common mean); bigaus = Bifurcated Gaussian; novo = Novosibirsk Fcn\n";
23  cout <<" <parms> : defauls extracted from histogram; string with initial fit parameters w/o amplitude param. E.g.: \"3.5,0.2,1,1,1\" -> mean=3.5, sigma=0.2, a0=1, a1=1, a2=1\n";
24  cout <<" a leading 'f' fixes the parameter. E.g.: \"f3.5,0.2\" -> mean=3.5 (fixed), sigma=0.2\n";
25  cout <<" <A> : amplitude parameter; default = h.Entries()/3. Negative value fixes the parameter at -A.\n";
26  cout <<" <min> : minimum of fit range; default = h min x\n";
27  cout <<" <max> : maximum of fit range; default = h max x\n";
28  return 0;
29  }
30 
31  h->Draw();
32 
33  if (type=="") type="gaus2";
34 
35  // bin width for amplitude param
36  double w = h->GetBinWidth(1);
37 
38  // fit range; if min=max, fit range over the whole histogram
39  if (min==-999.) min = h->GetXaxis()->GetXmin();
40  if (max==-999.) max = h->GetXaxis()->GetXmax();
41 
42  if (min>max) {double tmp=min; min=max;max=tmp;}
43 
44  TString tmpl;
45  int sigmode = 0;
46  int paroff = 3; // first parameter offset for the bkg polynomial
47 
48  // set signal type
49  if (type.BeginsWith("gaus")) sigmode = 0; // gaussian
50  else if (type.BeginsWith("bw")) sigmode = 1; // breit wigner
51  else if (type.BeginsWith("vgt")) sigmode = 2; // voigtian
52  else if (type.BeginsWith("dgaus")) sigmode = 3; // double gaussian
53  else if (type.BeginsWith("bigaus")) sigmode = 4; // bifurcated gaussian
54  else if (type.BeginsWith("novo")) sigmode = 5; // novosibirsk function
55 
56  // set fit function template
57  if (sigmode==0) tmpl = "%f*[0]/[2]/sqrt(2.0*pi)*exp(-0.5*((x-[1])/[2])^2)"; // Gaussian
58 // else if (sigmode==1) tmpl = "%f*[0]*TMath::Voigt(x-[1],0,[2],4.)"; // Breit-Wigner via Voigt
59  else if (sigmode==1) tmpl = "%f*[0]*[2]/(2.0*pi*((x-[1])^2+([2]/2)^2))"; // Breit-Wigner
60  else if (sigmode==2) tmpl = "%f*[0]*TMath::Voigt(x-[1],[2],[3],4.)"; // Voigt
61  else if (sigmode==3) tmpl = "%f*[0]*([4]/([4]+1.0)/[2]*exp(-0.5*((x-[1])/[2])^2)+1.0/([4]+1.0)/[3]*exp(-0.5*((x-[1])/[3])^2))/sqrt(2.0*pi)"; // 2 Gaussians with common mean (double gauss)
62  else if (sigmode==4) tmpl = "%f*[0]*2./([2]+[3])/sqrt(2.0*pi)*exp(-0.5*(x-[1])^2/([2]*(x<[1])+[3]*(x>=[1]))^2)"; // bifurcated Gaussian
63  else if (sigmode==5) tmpl = "[0]*(([3]>0)*((x-[1])*[3]/[2]<1)*exp( -0.5*(log(1-((x-[1])*[3]/[2]<1)*(x-[1])*[3]/[2]))^2/(2./2.3548*sinh(0.5*[3]*2.3548))^2 - 0.5*[2]^2)+([3]<=0)*(1./[2]/sqrt(2.0*pi)*exp(-0.5*((x-[1])/[2])^2)))"; // Novisibirsk function
64 
65  if (sigmode==2 || sigmode==4 || sigmode==5) paroff = 4;
66  if (sigmode==3) paroff = 5;
67 
68  // degree of bkg polynomial; 8+9 are argus fcn and truncated polynom
69  int deg = -1; // no background fcn
70  TString degs = type(type.Length()-1,1); // last character of fcn string could be the digit for bkg polynomial
71  TString nums="0123458";
72  if (nums.Contains(degs)) deg = degs.Atoi();
73  if (deg>maxdeg && deg<8) deg=maxdeg;
74 
75  // total number of params
76  int partot = paroff+deg+1;
77  if (deg==8) partot-=5; // correction for number of parameters for abusing deg==8 (->9 parms) for argus fcn with only 4 parameters
78 
79  // set fit function TFormula
80  TString fnc = TString::Format(tmpl.Data(), w);
81  if (deg>=0&&deg<8) fnc+=TString::Format("+pol%d(%d)",deg, paroff);
82  else if (deg==8) // ARGUS fcn bkg
83  {
84  fnc+=TString::Format("+(x<[%d])*[%d]*x*(abs(1-(x/[%d])^2))^[%d]*exp([%d]*(1-(x/[%d])^2))", paroff+1, paroff, paroff+1, paroff+2, paroff+3, paroff+1);
85  }
86 
87  cout<<"\nFit fcn: " <<fnc<<endl<<endl;
88 
89  // set the parameter list from par string
90  double prm[20]={0}; // the parameters
91  double prmr[20]={0}; // possible second par values defining a range
92  bool fixparm[20]={0}; // flags for fixed parameter
93  int pcnt = 0;
94  if (parms!="") parms=parms+",";
95 
96  // set some defaults
97  prm[0] = h->GetEntries()/3.; // N
98  prm[1] = h->GetBinCenter(h->GetMaximumBin()); // mean estimate
99  prm[2] = h->GetRMS()/2; // sigma/Gamma estimate
100  if (sigmode>1) prm[3] = prm[2]*2.; // 2nd sigma/Gamma estimate
101  if (sigmode==3) prm[4] = 1.0; // ratio sigma1/sigma2
102 
103  if (deg<maxdeg+1)
104  {
105  for (i=paroff;i<partot;++i) prm[i] = 1.0; // bkg parms
106  }
107  else if (deg==8)
108  {
109  prm[paroff] = h->GetMaximum()/5.;
110  prm[paroff+1] = max;
111  prm[paroff+2] = prm[paroff+3] = 0.5;
112  }
113 
114  // set initial amplitude parameter
115  if (A>0) prm[0] = A;
116  // if A<0 the parameter value will be fixed to -A
117  if (A<0) {prm[0] = -A; fixparm[0]=true;}
118 
119  // analyse parameter string
120  while (parms!="")
121  {
122  TString sparm = parms(0,parms.Index(","));
123  if (sparm!="")
124  {
125  // fix this parameter?
126  if (sparm.BeginsWith("f"))
127  {
128  sparm=sparm(1,1000); // cut away the 'f'
129  fixparm[1+pcnt] = true;
130  }
131  // ranged parameter in form 'r10.2|10.5'?
132  if (sparm.BeginsWith("r"))
133  {
134 // cout<<"ranged"<<endl;
135  TString sparm2 = sparm(sparm.Index("|")+1,1000);
136  sparm = sparm(1,sparm.Index("|"));
137  prmr[1+pcnt]=sparm2.Atof();
138 // cout <<"parm2="<<prmr[1+pcnt];
139  }
140  prm[1+pcnt++] = sparm.Atof();
141  parms = parms(parms.Index(",")+1,1000);
142  }
143  }
144 
145  // setup the total fit fcn (signal + background)
146  TF1 ff1("ff1", fnc);
147  ff1.SetLineColor(4); ff1.SetNpx(500); // some style setting
148 
149  // set the parameter names
150  if (sigmode==0) ff1.SetParNames("N","#mu","#sigma", "a_{0}","a_{1}","a_{2}","a_{3}","a_{4}","a_{5}");
151  else if (sigmode==1) ff1.SetParNames("N","#mu","#Gamma", "a_{0}","a_{1}","a_{2}","a_{3}","a_{4}","a_{5}");
152  else if (sigmode==2) ff1.SetParNames("N","#mu","#sigma","#Gamma", "a_{0}","a_{1}","a_{2}","a_{3}","a_{4}","a_{5}");
153  else if (sigmode==3) ff1.SetParNames("N","#mu","#sigma_{1}","#sigma_{2}","R", "a_{0}","a_{1}","a_{2}","a_{3}","a_{4}","a_{5}");
154  else if (sigmode==4) ff1.SetParNames("N","#mu","#sigma_{1}","#sigma_{2}", "a_{0}","a_{1}","a_{2}","a_{3}","a_{4}","a_{5}");
155  else if (sigmode==5) ff1.SetParNames("A","#mu","#sigma","#tau", "a_{0}","a_{1}","a_{2}","a_{3}","a_{4}","a_{5}");
156 
157  if (deg==8)
158  {
159  ff1.SetParName(paroff , "a");
160  ff1.SetParName(paroff+1, "m_{0}");
161  ff1.SetParName(paroff+2, "p");
162  ff1.SetParName(paroff+3, "c");
163  }
164 
165  // fix the parameters which were requested to be fixed
166  for (i=0;i<partot;++i)
167  {
168  if (fixparm[i])
169  ff1.FixParameter(i,prm[i]);
170  else if (prmr[i]!=0)
171  ff1.SetParLimits(i,prm[i],prmr[i]);
172  else
173  ff1.SetParameter(i,prm[i]);
174  }
175 
176  // ***** do the fit
177  h->Fit("ff1","q","",min, max);
178  h->Fit("ff1","m","",min, max);
179 
180  // compute integral of total fit fcn in interval min ... max
181  int integral = ff1.Integral(min,max)/w;
182  int bkg = 0;
183 
184  // do we have a bkg polynomial?
185  if (deg>=0 && deg<=maxdeg)
186  {
187  // create pure bkg function
188  TF1 *ff2=new TF1("ff2",TString::Format("pol%d",deg));
189  ff2->SetLineColor(kRed+1); ff2->SetLineStyle(2); ff2->SetNpx(500); // some style setting
190  ff2->SetRange(min,max);
191 
192  // copy parameters from full fcn
193  for (i=0;i<deg+1;++i) ff2->SetParameter(i,ff1.GetParameter(paroff+i));
194 
195  // add it to the histogram (so that it is shown when drawing the histogram)
196  h->GetListOfFunctions()->Add(ff2);
197 
198  // compute bkg intergral
199  bkg = ff2->Integral(min,max)/w;
200 
201  // #signals = #total - #bkg
202  if (bkg>0) integral -= bkg;
203  }
204 
205  // argus bkg
206  if (deg==8)
207  {
208  // create pure bkg function
209  TF1 *ff2=new TF1("ff2","(x<[1])*[0]*x*(abs(1-(x/[1])^2))^[2]*exp([3]*(1-(x/[1])^2))");
210  ff2->SetLineColor(kRed+1); ff2->SetLineStyle(2); ff2->SetNpx(500); // some style setting
211  ff2->SetRange(min,max);
212 
213  // copy parameters from full fcn
214  for (i=0;i<4;++i) ff2->SetParameter(i,ff1.GetParameter(paroff+i));
215 
216  // add it to the histogram (so that it is shown when drawing the histogram)
217  h->GetListOfFunctions()->Add(ff2);
218 
219  // compute bkg intergral
220  bkg = ff2->Integral(min,max)/w;
221 
222  // #signals = #total - #bkg
223  if (bkg>0) integral -= bkg;
224  }
225 
226  // restyle the stats box to adapt different number of parameters
227  TPaveStats *s = (TPaveStats*) gPad->GetPrimitive("stats");
228  if (s)
229  {
230  s->SetX1NDC(0.65);
231  s->SetY1NDC(gStyle->GetStatX()-0.032*(partot+4));
232  s->SetTextSize(0.025);
233  }
234 
235  // write numbers of S and B to the histogram
236  TLatex ls,lb;
237  double xmin = h->GetXaxis()->GetXmin(), xmax = h->GetXaxis()->GetXmax();
238  ls.SetTextSize(0.045); ls.SetTextColor(4);
239  ls.DrawLatex(xmin+(xmax-xmin)*0.03,h->GetMaximum()*0.95,TString::Format("S_{int} = %d",integral));
240  if (deg>=0)
241  {
242  lb.SetTextSize(0.045); lb.SetTextColor(kRed+1);
243  lb.DrawLatex(xmin+(xmax-xmin)*0.03,h->GetMaximum()*0.87,TString::Format("B_{int} = %d",bkg));
244  }
245 
246  // compute S/N and significance
247  double StoN = (double)integral/(double)bkg;
248  double Sign = (double)integral/sqrt((double)bkg+(double)integral);
249 
250  // print out the var list string for easier copy paste
251  cout <<endl<<"Var-list: \"";
252  for (int i=1;i<partot;++i)
253  {
254  if (fixparm[i]) cout<<"f";
255  cout << ff1.GetParameter(i);
256  if (i<partot-1) cout<<",";
257  }
258  cout <<"\"";
259 
260  // print some info about S and B
261  printf("\n\n[%.3f ... %.3f] : S = %d B = %d S/B = %.3f S/sqrt(S+B) = %.4f\n", min, max, integral, bkg, StoN, Sign);
262  return integral;
263 }
printf("RealTime=%f seconds, CpuTime=%f seconds\n", rtime, ctime)
static int prm
Definition: ranlxd.cxx:374
Int_t i
Definition: run_full.C:25
friend F32vec4 sqrt(const F32vec4 &a)
Definition: P4_F32vec4.h:29
const int maxdeg
Definition: fitsb.C:10
TLorentzVector s
Definition: Pnd2DStar.C:50
Double_t xmax
friend F32vec4 max(const F32vec4 &a, const F32vec4 &b)
Definition: P4_F32vec4.h:26
int fitsb(TH1 *h=0, TString type="", TString parms="", double A=0., double min=-999., double max=-999.)
Definition: fitsb.C:12
friend F32vec4 min(const F32vec4 &a, const F32vec4 &b)
Definition: P4_F32vec4.h:25
Double_t xmin
f ls()