Analysis Software
Documentation for sPHENIX simulation software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
BEmcRecCEMC.cc
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file BEmcRecCEMC.cc
1 #include "BEmcRecCEMC.h"
2 
3 #include "BEmcCluster.h"
4 #include "BEmcProfile.h"
5 
6 #include <cmath>
7 #include <iostream>
8 
10 // : _emcprof(nullptr)
11 {
12  Name("BEmcRecCEMC");
14 }
15 
17 {
18  // you can delete null pointers
19  // delete _emcprof;
20 }
21 
23 {
24  // std::cout << "Infor from BEmcRecCEMC::LoadProfile(): no external file used for shower profile evaluation in CEMC" << std::endl;
25  _emcprof = new BEmcProfile(fname);
26 }
27 
28 void BEmcRecCEMC::GetImpactThetaPhi(float xg, float yg, float zg, float& theta, float& phi)
29 {
30  theta = 0;
31  phi = 0;
32 
33  // float theta = atan(sqrt(xg*xg + yg*yg)/fabs(zg-fVz));
34  float rg = std::sqrt(xg * xg + yg * yg);
35  float theta_twr;
36  if (std::fabs(zg) <= 15)
37  {
38  theta_twr = 0;
39  }
40  else if (zg > 15)
41  {
42  theta_twr = std::atan2(zg - 15, rg);
43  }
44  else
45  {
46  theta_twr = std::atan2(zg + 15, rg);
47  }
48  float theta_tr = std::atan2(zg - fVz, rg);
49  theta = std::fabs(theta_tr - theta_twr);
50  // phi = atan2(yg,xg);
51 }
52 
53 /*
54 float BEmcRecCEMC::GetProb(vector<EmcModule> HitList, float ecl, float xg, float yg, float zg, float& chi2, int& ndf)
55 {
56  chi2 = 0;
57  ndf = 0;
58  float prob = -1;
59 
60  // float theta = atan(sqrt(xg*xg + yg*yg)/fabs(zg-fVz));
61  float rg = sqrt(xg * xg + yg * yg);
62  float theta_twr;
63  if (fabs(zg) <= 15)
64  theta_twr = 0;
65  else if (zg > 15)
66  theta_twr = atan2(zg - 15, rg);
67  else
68  theta_twr = atan2(zg + 15, rg);
69  float theta_tr = atan2(zg - fVz, rg);
70  float theta = fabs(theta_tr - theta_twr);
71 
72  float phi = atan2(yg, xg);
73  if (_emcprof != nullptr) prob = _emcprof->GetProb(&HitList, fNx, ecl, theta, phi);
74 
75  return prob;
76 }
77 */
78 /*
79 float BEmcRecCEMC::GetProb(vector<EmcModule> HitList, float et, float xg, float yg, float zg, float& chi2, int& ndf)
80 // et, xg, yg, zg not used here
81 {
82  const float thresh = 0.01;
83  const int DXY = 3; // 2 is for 5x5 matrix; 3 for 7x7 matrix
84  const int Nmax = 1000;
85  float ee[Nmax];
86  int iyy[Nmax];
87  int izz[Nmax];
88 
89  int ich;
90  vector<EmcModule>::iterator ph = HitList.begin();
91 
92  chi2 = 0;
93  ndf = 0;
94 
95  int nn = 0;
96 
97  while (ph != HitList.end())
98  {
99  ee[nn] = ph->amp;
100  if (ee[nn] > thresh)
101  {
102  ich = ph->ich;
103  izz[nn] = ich % fNx;
104  iyy[nn] = ich / fNx;
105  nn++;
106  if (nn >= Nmax)
107  {
108  std::cout << "BEmcRec::GetProb: Cluster size is too big. Skipping the rest of the towers" << std::endl;
109  break;
110  }
111  } // if( ee[nn]
112  ++ph;
113  } // while( ph
114 
115  if (nn <= 0) return -1;
116 
117  int iy0 = -1, iz0 = -1;
118  float emax = 0;
119 
120  for (int i = 0; i < nn; i++)
121  {
122  if (ee[i] > emax)
123  {
124  emax = ee[i];
125  iy0 = iyy[i];
126  iz0 = izz[i];
127  }
128  }
129 
130  if (emax <= 0) return -1;
131 
132  int id;
133  float etot = 0;
134  float sz = 0;
135  float sy = 0;
136 
137  for (int idz = -DXY; idz <= DXY; idz++)
138  {
139  for (int idy = -DXY; idy <= DXY; idy++)
140  {
141  id = GetTowerID(iy0 + idy, iz0 + idz, nn, iyy, izz, ee);
142  if (id >= 0)
143  {
144  etot += ee[id];
145  sz += ee[id] * (iz0 + idz);
146  sy += ee[id] * (iy0 + idy);
147  }
148  }
149  }
150  float zcg = sz / etot; // Here cg allowed to be out of range
151  float ycg = sy / etot;
152  int iz0cg = int(zcg + 0.5);
153  int iy0cg = int(ycg + 0.5);
154  float ddz = fabs(zcg - iz0cg);
155  float ddy = fabs(ycg - iy0cg);
156 
157  int isz = 1;
158  if (zcg - iz0cg < 0) isz = -1;
159  int isy = 1;
160  if (ycg - iy0cg < 0) isy = -1;
161 
162  // 4 central towers: 43
163  // 12
164  // Tower 1 - central one
165  float e1, e2, e3, e4;
166  e1 = e2 = e3 = e4 = 0;
167  id = GetTowerID(iy0cg, iz0cg, nn, iyy, izz, ee);
168  if (id >= 0) e1 = ee[id];
169  id = GetTowerID(iy0cg, iz0cg + isz, nn, iyy, izz, ee);
170  if (id >= 0) e2 = ee[id];
171  id = GetTowerID(iy0cg + isy, iz0cg + isz, nn, iyy, izz, ee);
172  if (id >= 0) e3 = ee[id];
173  id = GetTowerID(iy0cg + isy, iz0cg, nn, iyy, izz, ee);
174  if (id >= 0) e4 = ee[id];
175 
176  float e1t = (e1 + e2 + e3 + e4) / etot;
177  float e2t = (e1 + e2 - e3 - e4) / etot;
178  float e3t = (e1 - e2 - e3 + e4) / etot;
179  float e4t = (e3) / etot;
180  // float e5t = (e2+e4)/etot;
181 
182  float rr = sqrt((0.5 - ddz) * (0.5 - ddz) + (0.5 - ddy) * (0.5 - ddy));
183 
184  float c1, c2, c11;
185 
186  float logE = log(etot);
187 
188  // e1 energy is the most effective for PID if properly tuned !
189  // Discrimination power is very sensitive to paramter c1: the bigger it is
190  // the better discrimination;
191  c1 = 0.95;
192  c2 = 0.0066364 * logE + 0.00466667;
193  if (c2 < 0) c2 = 0;
194  float e1p = c1 - c2 * rr * rr;
195  c1 = 0.034 - 0.01523 * logE + 0.0029 * logE * logE;
196  float err1 = c1;
197 
198  // For e2
199  c1 = 0.00844086 + 0.00645359 * logE - 0.00119381 * logE * logE;
200  if (etot > 15) c1 = 0.00844086 + 0.00645359 * log(15.) - 0.00119381 * log(15.) * log(15.); // Const at etot>15GeV
201  if (c1 < 0) c1 = 0;
202  c2 = 3.9; // Fixed
203  float e2p = sqrt(c1 + 0.25 * c2) - sqrt(c1 + c2 * ddy * ddy); // =0 at ddy=0.5
204 
205  c1 = 0.0212333 + 0.0420473 / etot;
206  c2 = 0.090; // Fixed
207  float err2 = c1 + c2 * ddy;
208  if (ddy > 0.3) err2 = c1 + c2 * 0.3; // Const at ddy>0.3
209 
210  // For e3
211  c1 = 0.0107857 + 0.0056801 * logE - 0.000892016 * logE * logE;
212  if (etot > 15) c1 = 0.0107857 + 0.0056801 * log(15.) - 0.000892016 * log(15.) * log(15.); // Const at etot>15GeV
213  if (c1 < 0) c1 = 0;
214  c2 = 3.9; // Fixed
215  float e3p = sqrt(c1 + 0.25 * c2) - sqrt(c1 + c2 * ddz * ddz); // =0 at ddz=0.5
216 
217  // c1 = 0.0200 + 0.042/etot;
218  c1 = 0.0167 + 0.058 / etot;
219  c2 = 0.090; // Fixed
220  float err3 = c1 + c2 * ddz;
221  if (ddz > 0.3) err3 = c1 + c2 * 0.3; // Const at ddz>0.3
222 
223  // For e4
224  float e4p = 0.25 - 0.668 * rr + 0.460 * rr * rr;
225  c11 = 0.171958 + 0.0142421 * logE - 0.00214827 * logE * logE;
226  // c11 = 0.171085 + 0.0156215*logE - -0.0025809*logE*logE;
227  float err4 = 0.102 - 1.43 * c11 * rr + c11 * rr * rr; // Min is set to x=1.43/2.
228  err4 *= 1.1;
229 
230  chi2 = 0.;
231  chi2 += (e1p - e1t) * (e1p - e1t) / err1 / err1;
232  chi2 += (e2p - e2t) * (e2p - e2t) / err2 / err2;
233  chi2 += (e3p - e3t) * (e3p - e3t) / err3 / err3;
234  chi2 += (e4p - e4t) * (e4p - e4t) / err4 / err4;
235  ndf = 4;
236 
237  // chi2 /= 1.1;
238  float prob = TMath::Prob(chi2, ndf);
239 
240  return prob;
241 }
242 */
243 
244 void BEmcRecCEMC::CorrectShowerDepth(float E, float xA, float yA, float zA, float& xC, float& yC, float& zC)
245 {
246  /*
247  xC = xA;
248  yC = yA;
249  zC = zA;
250  */
251 
252  float logE = log(0.1);
253  if (E > 0.1)
254  {
255  logE = std::log(E);
256  }
257 
258  // Rotate by phi (towers are tilted by a fixed angle in phi by ~9 deg?)
259  // Just tuned from sim data
260  float phi = 0.002 - 0.001 * logE;
261  xC = xA * std::cos(phi) - yA * std::sin(phi);
262  yC = xA * std::sin(phi) + yA * std::cos(phi);
263 
264  // Correction in z
265  // Just tuned for sim data ... don't fully understand why it works like that
266  float rA = std::sqrt(xA * xA + yA * yA);
267  // float theta_twr = GetTowerTheta(xA,yA,zA);
268  float theta_twr;
269  if (std::fabs(zA) <= 15)
270  {
271  theta_twr = 0;
272  }
273  else if (zA > 15)
274  {
275  theta_twr = std::atan2(zA - 15, rA);
276  }
277  else
278  {
279  theta_twr = std::atan2(zA + 15, rA);
280  }
281 
282  float theta_tr = std::atan2(zA - fVz, rA);
283  float L = -1.3 + 0.7 * logE; // Shower CG in long. direction
284  float dz = L * std::sin(theta_tr - theta_twr) / std::cos(theta_twr);
285 
286  dz -= fVz * 0.10;
287 
288  zC = zA - dz;
289 
290  return;
291 }
292 
293 void BEmcRecCEMC::CorrectEnergy(float Energy, float /*x*/, float /*y*/,
294  float& Ecorr)
295 {
296  // Corrects the EM Shower Energy for attenuation in fibers and
297  // long energy leakage
298  //
299  // (x,y) - impact position (cm) in Sector frame
300  /*
301  float sinT;
302  float att, leak, corr;
303  const float leakPar = 0.0033; // parameter from fit
304  const float attPar = 120; // Attenuation in module (cm)
305  const float X0 = 2; // radiation length (cm)
306 
307  *Ecorr = Energy;
308  if( Energy < 0.01 ) return;
309 
310  GetImpactAngle(x, y, &sinT); // sinT not used so far
311  leak = 2-sqrt(1+leakPar*log(1+Energy)*log(1+Energy));
312  att = exp(log(Energy)*X0/attPar);
313  corr = leak*att;
314  *Ecorr = Energy/corr;
315  */
316  Ecorr = Energy;
317 }
318 
319 void BEmcRecCEMC::CorrectECore(float Ecore, float /*x*/, float /*y*/, float& Ecorr)
320 {
321  // Corrects the EM Shower Core Energy for attenuation in fibers,
322  // long energy leakage and angle dependance
323  //
324  // (x,y) - impact position (cm) in Sector frame
325 
326  const float c0 = 0.950; // For no threshold
327  Ecorr = Ecore / c0;
328 }
329 
330 void BEmcRecCEMC::CorrectPosition(float Energy, float x, float y,
331  float& xc, float& yc)
332 {
333  // Corrects the Shower Center of Gravity for the systematic shift due to
334  // limited tower size
335  //
336  // Everything here is in tower units.
337  // (x,y) - CG position, (xc,yc) - corrected position
338 
339  float xZero, yZero, bx, by;
340  float t, x0, y0;
341  int ix0, iy0;
342 
343  xc = x;
344  yc = y;
345 
346  if (Energy < 0.01)
347  {
348  return;
349  }
350  /*
351  float xA, yA, zA;
352  Tower2Global(Energy, x, y, xA, yA, zA);
353  zA -= fVz;
354  float sinTx = xA / sqrt(xA * xA + zA * zA);
355  float sinTy = yA / sqrt(yA * yA + zA * zA);
356  */
357  float sinTx = 0;
358  float sinTy = 0;
359 
360  float sin2Tx = sinTx * sinTx;
361  float sin2Ty = sinTy * sinTy;
362 
363  if (sinTx > 0)
364  {
365  xZero = -0.417 * sinTx - 1.500 * sin2Tx;
366  }
367  else
368  {
369  xZero = -0.417 * sinTx + 1.500 * sin2Tx;
370  }
371 
372  if (sinTy > 0)
373  {
374  yZero = -0.417 * sinTy - 1.500 * sin2Ty;
375  }
376  else
377  {
378  yZero = -0.417 * sinTy + 1.500 * sin2Ty;
379  }
380 
381  t = 0.98 + 0.98 * std::sqrt(Energy);
382  bx = 0.15 + t * sin2Tx;
383  by = 0.15 + t * sin2Ty;
384 
385  x0 = x + xZero;
386  ix0 = EmcCluster::lowint(x0 + 0.5);
387 
388  if (EmcCluster::ABS(x0 - ix0) <= 0.5)
389  {
390  x0 = (ix0 - xZero) + bx * asinh(2. * (x0 - ix0) * sinh(0.5 / bx));
391  }
392  else
393  {
394  x0 = x;
395  std::cout << "????? Something wrong in BEmcRecCEMC::CorrectPosition: x = "
396  << x << " dx = " << x0 - ix0 << std::endl;
397  }
398 
399  // Correct for phi bias within module of 8 towers
400  int ix8 = int(x + 0.5) / 8;
401  float x8 = x + 0.5 - ix8 * 8 - 4; // from -4 to +4
402  float dx = 0.10 * x8 / 4.;
403  if (std::fabs(x8) > 3.3)
404  {
405  dx = 0; // Don't correct near the module edge
406  }
407  // dx = 0;
408 
409  xc = x0 - dx;
410  while (xc < -0.5)
411  {
412  xc += float(fNx);
413  }
414  while (xc >= fNx - 0.5)
415  {
416  xc -= float(fNx);
417  }
418 
419  y0 = y + yZero;
420  iy0 = EmcCluster::lowint(y0 + 0.5);
421 
422  if (EmcCluster::ABS(y0 - iy0) <= 0.5)
423  {
424  y0 = (iy0 - yZero) + by * asinh(2. * (y0 - iy0) * sinh(0.5 / by));
425  }
426  else
427  {
428  y0 = y;
429  std::cout << "????? Something wrong in BEmcRecCEMC::CorrectPosition: y = "
430  << y << "dy = " << y0 - iy0 << std::endl;
431  }
432  yc = y0;
433 }
434 
435 /*
436 void BEmcRecCEMC::CorrectPosition(float Energy, float x, float y,
437  float* pxc, float* pyc)
438 {
439  // Corrects the Shower Center of Gravity for the systematic error due to
440  // the limited tower size and angle shift
441  //
442  // Everything here is in cell units.
443  // (x,y) - CG position, (*pxc,*pyc) - corrected position
444 
445  float xShift, yShift, xZero, yZero, bx, by;
446  float t, x0, y0;
447  int ix0, iy0;
448  // int signx, signy;
449 
450  const float Xrad = 0.3; // !!!!! Need to put correct value
451  const float Remc = 90.; // EMCal inner radius. !!!!! Should be obtained from geometry container
452 
453  *pxc = x;
454  *pyc = y;
455  // return;
456 
457  SetProfileParameters(0, Energy, x, y);
458  // if( fSinTx >= 0 ) signx = 1;
459  // else signx = -1;
460  // if( fSinTy >= 0 ) signy = 1;
461  // else signy = -1;
462  t = 5.0 + 1.0 * log(Energy); // In Rad Length units
463  t *= (Xrad / Remc / GetModSizex()); // !!!!!
464  xShift = t * fSinTx;
465  yShift = t * fSinTy;
466  // xZero=xShift-(0.417*EmcCluster::ABS(fSinTx)+1.500*fSinTx*fSinTx)*signx;
467  // yZero=yShift-(0.417*EmcCluster::ABS(fSinTy)+1.500*fSinTy*fSinTy)*signy;
468  xZero = xShift; // ...Somehow this works better !!!!!
469  yZero = yShift; // ...Somehow this works better !!!!!
470  t = 0.98 + 0.98 * sqrt(Energy); // !!!!! Still from PHENIX
471  bx = 0.15 + t * fSinTx * fSinTx;
472  by = 0.15 + t * fSinTy * fSinTy;
473 
474  x0 = x;
475  x0 = x0 - xShift + xZero;
476  ix0 = EmcCluster::lowint(x0 + 0.5);
477  if (EmcCluster::ABS(x0 - ix0) <= 0.5)
478  {
479  x0 = (ix0 - xZero) + bx * asinh(2. * (x0 - ix0) * sinh(0.5 / bx));
480  *pxc = x0;
481  }
482  else
483  {
484  *pxc = x - xShift;
485  std::cout << "????? Something wrong in CorrectPosition: x = "
486  << x << " dx = " << x0 - ix0 << std::endl;
487  }
488 
489  y0 = y;
490  y0 = y0 - yShift + yZero;
491  iy0 = EmcCluster::lowint(y0 + 0.5);
492  if (EmcCluster::ABS(y0 - iy0) <= 0.5)
493  {
494  y0 = (iy0 - yZero) + by * asinh(2. * (y0 - iy0) * sinh(0.5 / by));
495  *pyc = y0;
496  }
497  else
498  {
499  *pyc = y - yShift;
500  std::cout << "????? Something wrong in CorrectPosition: y = "
501  << y << " dy = " << y0 - iy << std::endl;
502  }
503 }
504 */