StRoot  1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
StGammaFitter.cxx
1 //
2 // Pibero Djawotho <pibero@indiana.edu>
3 // Indiana University
4 // 28 July 2007
5 //
6 
7 // ROOT
8 #include "TFile.h"
9 #include "TH1.h"
10 #include "TF1.h"
11 #include "TCanvas.h"
12 
13 // STAR
14 #include "StEEmcUtil/EEmcGeom/EEmcGeomSimple.h"
15 #include "StEEmcUtil/EEmcSmdMap/EEmcSmdMap.h"
16 #include "StEEmcUtil/StEEmcSmd/EEmcSmdGeom.h"
17 #include "StEmcUtil/geometry/StEmcGeom.h"
18 
19 // Local
20 #include "StGammaEvent.h"
21 #include "StGammaCandidate.h"
22 #include "StGammaFitterResult.h"
23 #include "StGammaFitter.h"
24 
25 ClassImp(StGammaFitter);
26 
27 StGammaFitter* StGammaFitter::mInstance = 0;
28 TH1* StGammaFitter::hU = 0;
29 TH1* StGammaFitter::hV = 0;
30 TF1* StGammaFitter::fFit[2];
31 TF1* StGammaFitter::fResidualCut = 0;
32 int StGammaFitter::mNdf = 0;
33 TCanvas* StGammaFitter::mCanvas = 0;
34 TF1* StGammaFitter::mShowerShapes[3];
35 
37 {
38  hU = new TH1F("hU", "hU", 288, 0, 288);
39  hV = new TH1F("hV", "hV", 288, 0, 288);
40 
41  fResidualCut = new TF1("fResidualCut", "pol2", 0, 200);
42  fResidualCut->SetParameters(100, 0, 0.05);
43 
44  // Initialize shower shapes with fits from Ilya based on his gamma-jet analysis for
45  // different preshower conditions.
46  // See http://www.star.bnl.gov/protected/spin/seluzhen/gammaJet/2008.05.27/showerShapes_comparison.html
47  static const char* formula[] = {
48  "[0]*(0.669864*exp(-0.5*sq((x-[1])/0.574864))+0.272997*exp(-0.5*sq((x-[1])/-1.84608))+0.0585682*exp(-0.5*sq((x-[1])/5.49802)))", // pre1=0, pre2=0
49  "[0]*(0.0694729*exp(-0.5*sq((x-[1])/5.65413))+0.615724*exp(-0.5*sq((x-[1])/0.590723))+0.314777*exp(-0.5*sq((x-[1])/2.00192)))", // pre1=0, pre2>0
50  "[0]*(0.0955638*exp(-0.5*sq((x-[1])/5.59675))+0.558661*exp(-0.5*sq((x-[1])/0.567596))+0.345896*exp(-0.5*sq((x-[1])/1.9914)))" // pre1>0, pre2>0
51  };
52 
53  for (int i = 0; i < 3; ++i) {
54  const char* name = Form("mShowerShapes%d", i);
55  mShowerShapes[i] = new TF1(name, formula[i], 0, 288);
56  }
57 }
58 
60 {
61  // Never called???
62  delete hU;
63  delete hV;
64  delete fResidualCut;
65 }
66 
68 {
69  if (!mInstance) mInstance = new StGammaFitter;
70  return mInstance;
71 }
72 
73 int StGammaFitter::fit(StGammaCandidate* candidate, StGammaFitterResult* fits, Int_t plane)
74 {
75  // Require at least 5 strips in each SMD plane
76  if (candidate->numberOfSmdu() < 5) return 9;
77  if (candidate->numberOfSmdv() < 5) return 9;
78 
79  // Clear fit results
80  //memset(fits, 0, 1 * sizeof(StGammaFitterResult));
81 
82  TF1* fit = 0;
83 
84  if (candidate->pre1Energy() == 0 && candidate->pre2Energy() == 0)
85  fit = mShowerShapes[0];
86  else if (candidate->pre1Energy() == 0 && candidate->pre2Energy() > 0)
87  fit = mShowerShapes[1];
88  else if (candidate->pre1Energy() > 0 && candidate->pre2Energy() > 0)
89  fit = mShowerShapes[2];
90  else
91  return 9;
92 
93  // Loop over planes
94  // for (int plane = 0; plane < 2; ++plane) {
95  {
96  static TH1* hStrips = new TH1F("hStrips", "hStrips", 288, 0, 288);
97  hStrips->Reset();
98 
99  switch (plane) {
100  case 0:
101  for (int i = 0; i < candidate->numberOfSmdu(); ++i) {
102  StGammaStrip* strip = candidate->smdu(i);
103  hStrips->Fill(strip->index, strip->energy);
104  }
105  break;
106  case 1:
107  for (int i = 0; i < candidate->numberOfSmdv(); ++i) {
108  StGammaStrip* strip = candidate->smdv(i);
109  hStrips->Fill(strip->index, strip->energy);
110  }
111  break;
112  }
113 
114  // Find maximum strip
115  int mean = hStrips->GetMaximumBin();
116 
117  // Integrate yield from +/- 2 strips of max strip
118  int bin1 = max(1, mean - 2);
119  int bin2 = min(288, mean + 2);
120 
121  // Fit to Ilya's shower shape
122  float yield = hStrips->Integral(bin1, bin2);
123  fit->SetParameters(yield, hStrips->GetBinLowEdge(mean));
124  hStrips->Fit(fit, "WWQ", "", hStrips->GetBinLowEdge(bin1), hStrips->GetBinLowEdge(bin2));
125 
126  // Save fit results
127  fits[plane].yield = yield;
128  fits[plane].yieldError = 0;
129  fits[plane].centroid = fit->GetParameter(1);
130  fits[plane].centroidError = fit->GetParError(1);
131  fits[plane].residual = residual(hStrips, fit);
132  fits[plane].mean = hStrips->GetMean();
133  fits[plane].rms = hStrips->GetRMS();
134  fits[plane].chiSquare = fit->GetChisquare();
135  fits[plane].ndf = fit->GetNDF();
136  fits[plane].prob = fit->GetProb();
137  }
138 
139  return 0;
140 }
141 
142 void StGammaFitter::estimateYieldMean(TH1* h1, float& yield, float& mean)
143 {
144  int bin = h1->GetMaximumBin();
145  int xmin = max(bin - 2, 1);
146  int xmax = min(bin + 2, 288);
147  yield = h1->Integral(xmin, xmax);
148  mean = h1->GetBinCenter(bin);
149 }
150 
151 float StGammaFitter::residual(TH1* h1, TF1* f1)
152 {
153  int mean = h1->FindBin(f1->GetParameter(1));
154 
155  int leftMin = 1;
156  int leftMax = max(mean - 3, 1);
157  float leftResidual = 0;
158 
159  for (int bin = leftMin; bin <= leftMax; ++bin) {
160  float data = h1->GetBinContent(bin);
161  float x = h1->GetBinCenter(bin);
162  float fit = f1->Eval(x);
163  leftResidual += data - fit;
164  }
165 
166  int rightMin = min(mean + 3, 288);
167  int rightMax = 288;
168  float rightResidual = 0;
169 
170  for (int bin = rightMin; bin <= rightMax; ++bin) {
171  float data = h1->GetBinContent(bin);
172  float x = h1->GetBinCenter(bin);
173  float fit = f1->Eval(x);
174  rightResidual += data - fit;
175  }
176 
177  return max(leftResidual, rightResidual);
178 }
179 
180 double StGammaFitter::distanceToQuadraticCut(double x, double y)
181 {
182  double a = fResidualCut->GetParameter(0);
183  double b = fResidualCut->GetParameter(2);
184  double coef[] = { -x, 2*b*(a-y)+1, 0, 2*b*b };
185  double r1, r2, r3;
186  double x1 = 0;
187 
188  if (TMath::RootsCubic(coef, r1, r2, r3)) {
189  // 1 real root r1 and 2 complex conjugates r2+i*r3 and r2-i*r3
190  // Pick real root
191  x1 = r1;
192  }
193  else {
194  // 3 real roots r1, r2, r3
195  // Pick positive root
196  if (r1 >= 0)
197  x1 = r1;
198  else if (r2 >= 0)
199  x1 = r2;
200  else if (r3 >= 0)
201  x1 = r3;
202  else {
203  LOG_ERROR << "Can't find positive root" << endm;
204  }
205  }
206 
207  double y1 = fResidualCut->Eval(x1);
208  double d = hypot(x - x1, y - y1);
209 
210  return (y > fResidualCut->Eval(x)) ? d : -d;
211 }
212 
213 float StGammaFitter::GetMaximum(TH1* h1, float xmin, float xmax)
214 {
215  int bin1 = h1->FindBin(xmin);
216  int bin2 = h1->FindBin(xmax);
217 
218  float ymax = 0;
219 
220  for (int bin = bin1; bin <= bin2; ++bin) {
221  float y = h1->GetBinContent(bin);
222  if (y > ymax) ymax = y;
223  }
224 
225  return ymax;
226 }
~StGammaFitter()
Destructor.
static StGammaFitter * instance()
Access to single instance of this singleton class.
StGammaFitter()
Constructor in protected section to prevent user from creating instances of this singleton class...
static double distanceToQuadraticCut(double x, double y)
distance in yield vs. maximal-sided residual plane between the quadratic residual cut and the point (...
int fit(StGammaCandidate *candidate, StGammaFitterResult *fits, Int_t plane=0)
Fit transverse SMD profile to predetermined peak in u- and v-plane.