Analysis Software
Documentation for sPHENIX simulation software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
BEmcCluster.cc
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file BEmcCluster.cc
1 // Name: EmcCluster.cxx
2 // Author: A. Bazilevsky (RIKEN-BNL)
3 // Major modifications by M. Volkov (RRC KI) Jan 27 2000
4 
5 #include "BEmcCluster.h"
6 #include "BEmcRec.h"
7 
8 #include <iostream>
9 
10 // Define and initialize static members
11 
12 // Max number of peaks in cluster; used in EmcCluster::GetSubClusters(...)
13 int const EmcCluster::fgMaxNofPeaks = 1000;
14 
15 // Used in EmcCluster::GetSubClusters(...), it is the number of iterations
16 // when fitting photons to peak areas
17 int const EmcCluster::fgPeakIter = 6;
18 
19 // Emin cuts cluster energy: Ecl >= Epk1+Epk2 +...+Epkn !!!!!!!!!!!!!
20 float const EmcCluster::fgEmin = 0.002;
21 
23  : ich(0)
24  , amp(0)
25  , tof(0)
26 {
27 }
28 
29 //_____________________________________________________________________________
30 EmcModule::EmcModule(int ich_, float amp_, float tof_)
31  : ich(ich_)
32  , amp(amp_)
33  , tof(tof_)
34 {
35 }
36 
37 // ///////////////////////////////////////////////////////////////////////////
38 // EmcCluster member functions
39 
40 void EmcCluster::GetCorrPos(float& xc, float& yc)
41 // Returns the cluster corrected position in tower units
42 // Corrected for S-oscilations, not for shower depth
43 // Shower depth (z-coord) is defined in fOwner->Tower2Global()
44 {
45  float e, x, y, xx, yy, xy;
46 
47  fOwner->Momenta(&fHitList, e, x, y, xx, yy, xy);
48  fOwner->CorrectPosition(e, x, y, xc, yc);
49 }
50 
51 // ///////////////////////////////////////////////////////////////////////////
52 
53 void EmcCluster::GetGlobalPos(float& xA, float& yA, float& zA)
54 // Returns the cluster position in PHENIX global coord system
55 {
56  float xc, yc;
57  float e = GetTotalEnergy();
58  GetCorrPos(xc, yc);
59  fOwner->Tower2Global(e, xc, yc, xA, yA, zA);
60 }
61 
62 // ///////////////////////////////////////////////////////////////////////////
63 
65 // Returns the energy of the ich-tower (0 if ich not found in the fHitList)
66 {
67  std::vector<EmcModule>::iterator ph;
68  if (fHitList.empty())
69  {
70  return 0;
71  }
72  ph = fHitList.begin();
73  while (ph != fHitList.end())
74  {
75  if ((*ph).ich == ich)
76  {
77  return (*ph).amp;
78  }
79  ++ph;
80  }
81  return 0;
82 }
83 
84 // ///////////////////////////////////////////////////////////////////////////
85 
86 float EmcCluster::GetTowerEnergy(int ix, int iy)
87 // Returns the energy of the tower ix,iy (0 if tower not found in the fHitList)
88 {
89  std::vector<EmcModule>::iterator ph;
90 
91  if (fHitList.empty())
92  {
93  return 0;
94  }
95  ph = fHitList.begin();
96  int ich = iy * fOwner->GetNx() + ix;
97  return GetTowerEnergy(ich);
98 }
99 
100 // ///////////////////////////////////////////////////////////////////////////
101 
103 // Returns the ToF of the ich-tower (0 if ich not found in the fHitList)
104 {
105  std::vector<EmcModule>::iterator ph;
106  if (fHitList.empty())
107  {
108  return 0;
109  }
110  ph = fHitList.begin();
111  while (ph != fHitList.end())
112  {
113  if ((*ph).ich == ich)
114  {
115  return (*ph).tof;
116  }
117  ++ph;
118  }
119  return 0;
120 }
121 
122 // ///////////////////////////////////////////////////////////////////////////
123 
125 // Returns the cluster total energy
126 {
127  std::vector<EmcModule>::iterator ph;
128  float et = 0;
129  if (fHitList.empty())
130  {
131  return 0;
132  }
133  ph = fHitList.begin();
134  while (ph != fHitList.end())
135  {
136  et += (*ph).amp;
137  ++ph;
138  }
139  return et;
140 }
141 
142 // ///////////////////////////////////////////////////////////////////////////
143 
145 // Returns the energy in core towers around the cluster Center of Gravity
146 // Corrected for energy leak sidewise from core towers
147 {
148  float e, x, y, xx, yy, xy;
149  float ecore, ecorecorr;
150  ecore = GetECore();
151  fOwner->Momenta(&fHitList, e, x, y, xx, yy, xy);
152  fOwner->CorrectECore(ecore, x, y, ecorecorr);
153  return ecorecorr;
154 }
155 
157 // Returns the energy in core towers around the cluster Center of Gravity
158 {
159  const float thresh = 0.01;
160 
161  std::vector<EmcModule>::iterator ph;
162  float xcg, ycg, xx, xy, yy;
163  float energy, es;
164 
165  fOwner->Momenta(&fHitList, energy, xcg, ycg, xx, yy, xy);
166  // fOwner->SetProfileParameters(0, energy, xcg, ycg);
167 
168  es = 0;
169  if (fHitList.empty())
170  {
171  return 0;
172  }
173  ph = fHitList.begin();
174  while (ph != fHitList.end())
175  {
176  int ixy = (*ph).ich;
177  int iy = ixy / fOwner->GetNx();
178  int ix = ixy - iy * fOwner->GetNx();
179  // dx = xcg - ix;
180  // float dx = fOwner->fTowerDist(float(ix), xcg);
181  // float dy = ycg - iy;
182  // float et = fOwner->PredictEnergy(dx, dy, energy);
183  float et = fOwner->PredictEnergy(energy, xcg, ycg, ix, iy);
184  if (et > thresh)
185  {
186  es += (*ph).amp;
187  }
188  ++ph;
189  }
190  return es;
191 }
192 
193 // ///////////////////////////////////////////////////////////////////////////
194 
196 // Returns the energy in 2x2 towers around the cluster Center of Gravity
197 {
198  float et, xcg, ycg, xx, xy, yy;
199  float e1, e2, e3, e4;
200  int ix0, iy0, isx, isy;
201 
202  fOwner->Momenta(&fHitList, et, xcg, ycg, xx, yy, xy);
203  ix0 = int(xcg + 0.5);
204  iy0 = int(ycg + 0.5);
205 
206  isx = 1;
207  if (xcg - ix0 < 0)
208  {
209  isx = -1;
210  }
211  isy = 1;
212  if (ycg - iy0 < 0)
213  {
214  isy = -1;
215  }
216 
217  e1 = GetTowerEnergy(ix0, iy0);
218  e2 = GetTowerEnergy(ix0 + isx, iy0);
219  e3 = GetTowerEnergy(ix0 + isx, iy0 + isy);
220  e4 = GetTowerEnergy(ix0, iy0 + isy);
221 
222  return (e1 + e2 + e3 + e4);
223 }
224 // ///////////////////////////////////////////////////////////////////////////
225 
227 // Returns the energy in 3x3 towers around the cluster Center of Gravity
228 {
229  float et, xcg, ycg, xx, xy, yy;
230  int ich, ix0, iy0, nhit;
231 
232  nhit = fHitList.size();
233 
234  if (nhit <= 0)
235  {
236  return 0;
237  }
238 
239  fOwner->Momenta(&fHitList, et, xcg, ycg, xx, yy, xy);
240  ix0 = int(xcg + 0.5);
241  iy0 = int(ycg + 0.5);
242  ich = iy0 * fOwner->GetNx() + ix0;
243 
244  return GetE9(ich);
245 }
246 
247 // ///////////////////////////////////////////////////////////////////////////
248 
249 float EmcCluster::GetE9(int ich)
250 // Returns the energy in 3x3 towers around the tower ich
251 {
252  std::vector<EmcModule>::iterator ph;
253 
254  int iy0 = ich / fOwner->GetNx();
255  int ix0 = ich - iy0 * fOwner->GetNx();
256 
257  float es = 0;
258  if (fHitList.empty())
259  {
260  return 0;
261  }
262  ph = fHitList.begin();
263  while (ph != fHitList.end())
264  {
265  int ixy = (*ph).ich;
266  int iy = ixy / fOwner->GetNx();
267  int ix = ixy - iy * fOwner->GetNx();
268  int idx = fOwner->iTowerDist(ix0, ix);
269  int idy = iy - iy0;
270  if (abs(idx) <= 1 && abs(idy) <= 1)
271  {
272  es += (*ph).amp;
273  }
274  ++ph;
275  }
276  return es;
277 }
278 
279 // ///////////////////////////////////////////////////////////////////////////
280 
282 // Returns the EmcModule with the maximum energy
283 {
284  std::vector<EmcModule>::iterator ph;
285  float emax = 0;
286  EmcModule ht;
287 
288  ht.ich = -1;
289  ht.amp = 0;
290  ht.tof = 0;
291  if (fHitList.empty())
292  {
293  return ht;
294  }
295 
296  ph = fHitList.begin();
297  while (ph != fHitList.end())
298  {
299  if ((*ph).amp > emax)
300  {
301  emax = (*ph).amp;
302  ht = *ph;
303  }
304  ++ph;
305  }
306  return ht;
307 }
308 
309 // ///////////////////////////////////////////////////////////////////////////
310 
311 void EmcCluster::GetMoments(float& x, float& y, float& xx, float& xy, float& yy)
312 // Returns cluster 1-st (px,py) and 2-d momenta (pxx,pxy,pyy) in cell unit
313 {
314  float e;
315  fOwner->Momenta(&fHitList, e, x, y, xx, yy, xy);
316 }
317 
318 // ///////////////////////////////////////////////////////////////////////////
319 
320 float EmcCluster::GetProb(float& chi2, int& ndf)
321 {
322  float e, xg, yg, zg;
323  e = GetTotalEnergy();
324  xg = 0;
325  GetGlobalPos(xg, yg, zg);
326  return fOwner->GetProb(fHitList, e, xg, yg, zg, chi2, ndf);
327 }
328 
329 // ///////////////////////////////////////////////////////////////////////////
330 
331 int EmcCluster::GetSubClusters(std::vector<EmcCluster>& PkList, std::vector<EmcModule>& ppeaks)
332 {
333  // Splits the cluster onto subclusters
334  // The number of subclusters is equal to the number of Local Maxima in a cluster.
335  // Local Maxima can have the energy not less then
336  // defined in fgMinPeakEnergy
337  //
338  // Output: PkList - vector of subclusters
339  // ppeaks - vector of peak EmcModules (one for each subcluster)
340  //
341  // Returns: >= 0 Number of Peaks;
342  // -1 The number of Peaks is greater then fgMaxNofPeaks;
343  // (just increase parameter fgMaxNofPeaks)
344 
345  int npk, ipk, nhit;
346  int ixypk, ixpk, iypk, in, nh, ic;
347  int ixy, ix, iy, nn;
348  int idx, idy;
349  int ig, ng, igmpk1[fgMaxNofPeaks], igmpk2[fgMaxNofPeaks];
350  int PeakCh[fgMaxNofPeaks];
351  float epk[fgMaxNofPeaks * 2], xpk[fgMaxNofPeaks * 2], ypk[fgMaxNofPeaks * 2];
352  float ratio, eg, dx, dy, a;
353  float *Energy[fgMaxNofPeaks], *totEnergy, *tmpEnergy;
354  EmcModule *phit, *hlist, *vv;
355  EmcCluster peak(fOwner);
356  std::vector<EmcModule>::iterator ph;
357  std::vector<EmcModule> hl;
358 
359  PkList.clear();
360  ppeaks.clear();
361 
362  nhit = fHitList.size();
363 
364  if (nhit <= 0)
365  {
366  return 0;
367  }
368 
369  hlist = new EmcModule[nhit];
370 
371  ph = fHitList.begin();
372  vv = hlist;
373  while (ph != fHitList.end())
374  {
375  *vv++ = *ph++;
376  }
377 
378  // sort by linear channel number
379  qsort(hlist, nhit, sizeof(EmcModule), fOwner->HitNCompare);
380 
381  //
382  // Find peak (maximum) position (towers with local maximum amp)
383  //
384  npk = 0;
385  for (ic = 0; ic < nhit; ic++)
386  {
387  float amp = hlist[ic].amp;
388  if (amp > fOwner->GetPeakThreshold())
389  {
390  int ich = hlist[ic].ich;
391  // old int ichmax = ich + fOwner->GetNx() + 1;
392  // old int ichmin = ich - fOwner->GetNx() - 1;
393  // Look into three raws only
394  int ichmax = (ich / fOwner->GetNx() + 2) * fOwner->GetNx() - 1;
395  int ichmin = (ich / fOwner->GetNx() - 1) * fOwner->GetNx();
396  int ixc = ich - ich / fOwner->GetNx() * fOwner->GetNx();
397  int inA = ic + 1;
398  // check right, and 3 towers above if there is another max
399  while ((inA < nhit) && (hlist[inA].ich <= ichmax))
400  {
401  int ixA = hlist[inA].ich - hlist[inA].ich / fOwner->GetNx() * fOwner->GetNx();
402  // old if( (abs(ixc-ixA) <= 1) && (hlist[inA].amp >= amp) ) goto new_ic;
403  if ((abs(fOwner->iTowerDist(ixA, ixc)) <= 1) && (hlist[inA].amp >= amp))
404  {
405  goto new_ic;
406  }
407  inA++;
408  }
409  inA = ic - 1;
410  // check left, and 3 towers below if there is another max
411  while ((inA >= 0) && (hlist[inA].ich >= ichmin))
412  {
413  int ixA = hlist[inA].ich - hlist[inA].ich / fOwner->GetNx() * fOwner->GetNx();
414  // old if( (abs(ixc-ixA) <= 1) && (hlist[inA].amp > amp) ) goto new_ic;
415  if ((abs(fOwner->iTowerDist(ixA, ixc)) <= 1) && (hlist[inA].amp > amp))
416  {
417  goto new_ic;
418  }
419  inA--;
420  }
421  if (npk >= fgMaxNofPeaks)
422  {
423  delete[] hlist;
424  std::cout << "!!! Error in EmcCluster::GetSubClusters(): too many peaks in a cluster (>"
425  << fgMaxNofPeaks
426  << "). May need tower energy threshold increase for clustering." << std::endl;
427  return -1;
428  }
429 
430  // ic is a maximum in a 3x3 tower group
431  PeakCh[npk] = ic;
432  npk++;
433  }
434  new_ic:
435  continue;
436  }
437  /*
438  for( ipk=0; ipk<npk; ipk++ ) {
439  ic = PeakCh[ipk];
440  std::cout << " " << ipk << ": E = " << hlist[ic].amp << std::endl;
441  }
442  */
443 
444  // there was only one peak
445  if (npk <= 1)
446  {
447  hl.clear();
448  for (int ich = 0; ich < nhit; ich++)
449  {
450  hl.push_back(hlist[ich]);
451  }
452  peak.ReInitialize(hl);
453  PkList.push_back(peak);
454 
455  if (npk == 1)
456  {
457  ppeaks.push_back(hlist[PeakCh[0]]);
458  }
459  else
460  {
461  ppeaks.push_back(GetMaxTower());
462  }
463 
464  delete[] hlist;
465  return 1;
466  }
467 
468  // there were more than one peak
469 
470  for (ipk = 0; ipk < npk; ipk++)
471  {
472  Energy[ipk] = new float[nhit];
473  }
474  totEnergy = new float[nhit];
475  tmpEnergy = new float[nhit];
476  for (int i = 0; i < nhit; ++i)
477  {
478  totEnergy[i] = 0.0;
479  tmpEnergy[i] = 0.0;
480  }
481  //
482  // Divide energy in towers among photons positioned in every peak
483  //
484  ratio = 1.;
485  for (int iter = 0; iter < fgPeakIter; iter++)
486  {
487  fOwner->ZeroVector(tmpEnergy, nhit);
488  for (ipk = 0; ipk < npk; ipk++)
489  {
490  ic = PeakCh[ipk];
491  if (iter > 0)
492  {
493  ratio = Energy[ipk][ic] / totEnergy[ic];
494  }
495  eg = hlist[ic].amp * ratio;
496  ixypk = hlist[ic].ich;
497  iypk = ixypk / fOwner->GetNx();
498  ixpk = ixypk - iypk * fOwner->GetNx();
499  epk[ipk] = eg;
500  xpk[ipk] = 0.; // CoG from the peak tower
501  ypk[ipk] = 0.; // CoG from the peak tower
502 
503  int ichmax = (iypk + 2) * fOwner->GetNx() - 1;
504  int ichmin = (iypk - 1) * fOwner->GetNx();
505 
506  // add up energies of tower to the right and up
507  if (ic < nhit - 1)
508  {
509  for (in = ic + 1; in < nhit; in++)
510  {
511  ixy = hlist[in].ich;
512  iy = ixy / fOwner->GetNx();
513  ix = ixy - iy * fOwner->GetNx();
514 
515  // old if( (ixy-ixypk) > fOwner->GetNx()+1 ) break;
516  if (ixy > ichmax)
517  {
518  break;
519  }
520  // old if( abs(ix-ixpk) <= 1 ) {
521  idx = fOwner->iTowerDist(ixpk, ix);
522  idy = iy - iypk;
523  if (abs(idx) <= 1)
524  {
525  if (iter > 0)
526  {
527  ratio = Energy[ipk][in] / totEnergy[in];
528  }
529  eg = hlist[in].amp * ratio;
530  epk[ipk] += eg;
531  xpk[ipk] += eg * idx;
532  ypk[ipk] += eg * idy;
533  }
534  }
535  } // if ic
536 
537  // add up energies of tower to the left and down
538  if (ic >= 1)
539  {
540  for (in = ic - 1; in >= 0; in--)
541  {
542  ixy = hlist[in].ich;
543  iy = ixy / fOwner->GetNx();
544  ix = ixy - iy * fOwner->GetNx();
545 
546  // old if( (ixypk-ixy) > fOwner->GetNx()+1 ) break;
547  if (ixy < ichmin)
548  {
549  break;
550  }
551  // old if( abs(ix-ixpk) <= 1 ) {
552  idx = fOwner->iTowerDist(ixpk, ix);
553  idy = iy - iypk;
554  if (abs(idx) <= 1)
555  {
556  if (iter > 0)
557  {
558  ratio = Energy[ipk][in] / totEnergy[in];
559  }
560  eg = hlist[in].amp * ratio;
561  epk[ipk] += eg;
562  xpk[ipk] += eg * idx;
563  ypk[ipk] += eg * idy;
564  }
565  }
566  } // if ic
567 
568  xpk[ipk] = xpk[ipk] / epk[ipk] + ixpk;
569  ypk[ipk] = ypk[ipk] / epk[ipk] + iypk;
570  // fOwner->SetProfileParameters(0, epk[ipk], xpk[ipk], ypk[ipk]);
571 
572  for (in = 0; in < nhit; in++)
573  {
574  ixy = hlist[in].ich;
575  iy = ixy / fOwner->GetNx();
576  ix = ixy - iy * fOwner->GetNx();
577  dx = fOwner->fTowerDist(float(ix), xpk[ipk]);
578  dy = ypk[ipk] - iy;
579  a = 0;
580 
581  // predict energy within 2.5 cell square around local peak
582  if (ABS(dx) < 2.5 && ABS(dy) < 2.5)
583  {
584  // a = epk[ipk] * fOwner->PredictEnergy(dx, dy, epk[ipk]);
585  a = epk[ipk] * fOwner->PredictEnergy(epk[ipk], xpk[ipk], ypk[ipk], ix, iy);
586  }
587 
588  Energy[ipk][in] = a;
589  tmpEnergy[in] += a;
590  }
591 
592  } // for ipk
593  float flim = 0.000001;
594  for (in = 0; in < nhit; in++)
595  {
596  if (tmpEnergy[in] > flim)
597  {
598  totEnergy[in] = tmpEnergy[in];
599  }
600  else
601  {
602  totEnergy[in] = flim;
603  }
604  }
605  } // for iter
606 
607  phit = new EmcModule[nhit];
608 
609  ng = 0;
610  for (ipk = 0; ipk < npk; ipk++)
611  {
612  nh = 0;
613 
614  // fill phit, the tower distribution for a peak
615  for (in = 0; in < nhit; in++)
616  {
617  if (tmpEnergy[in] > 0)
618  {
619  ixy = hlist[in].ich;
620  a = hlist[in].amp * Energy[ipk][in] / tmpEnergy[in];
621  if (a > fgEmin)
622  {
623  phit[nh].ich = ixy;
624  phit[nh].amp = a;
625  phit[nh].tof = hlist[in].tof; // Not necessary here
626 
627  nh++;
628  }
629  }
630  }
631 
632  // if number hits > 0
633  if (nh > 0)
634  {
635  // !!!!! Exclude Gamma() for now until it is proved working and useful
636  /*
637  chi=fOwner->Chi2Limit(nh)*10;
638  int ndf; // just a plug for changed Gamma parameter list MV 28.01.00
639 
640  fOwner->Gamma(nh, phit,&chi, &chi0, &epk[ng], &xpk[ng], &ypk[ng],
641  &epk[ng+1], &xpk[ng+1], &ypk[ng+1], ndf);
642 
643  igmpk1[ipk]=ng;
644  igmpk2[ipk]=ng;
645  if( epk[ng+1]>0 ) { ng++; igmpk2[ipk]=ng;}
646  */
647  igmpk1[ipk] = ng;
648  igmpk2[ipk] = ng;
649 
650  ng++;
651  }
652  else
653  {
654  igmpk1[ipk] = -1;
655  igmpk2[ipk] = -1;
656  }
657  } // for( ipk=
658 
659  fOwner->ZeroVector(tmpEnergy, nhit);
660  for (ipk = 0; ipk < npk; ipk++)
661  {
662  ig = igmpk1[ipk];
663  if (ig >= 0)
664  {
665  // std::cout << " " << ipk << ": X = " << xpk[ig]
666  // << " Y = " << ypk[ig] << std::endl;
667  // fOwner->SetProfileParameters(0, epk[ig], xpk[ig], ypk[ig]);
668  for (in = 0; in < nhit; in++)
669  {
670  Energy[ipk][in] = 0;
671  for (ig = igmpk1[ipk]; ig <= igmpk2[ipk]; ig++)
672  {
673  ixy = hlist[in].ich;
674  iy = ixy / fOwner->GetNx();
675  ix = ixy - iy * fOwner->GetNx();
676  dx = fOwner->fTowerDist(float(ix), xpk[ig]);
677  dy = ypk[ig] - iy;
678  // a = epk[ig] * fOwner->PredictEnergy(dx, dy, epk[ig]);
679  a = epk[ig] * fOwner->PredictEnergy(epk[ig], xpk[ig], ypk[ig], ix, iy);
680  Energy[ipk][in] += a;
681  tmpEnergy[in] += a;
682  }
683  } // for( in
684  } // if( ig >= 0
685  } // for( ipk
686 
687  nn = 0;
688  for (ipk = 0; ipk < npk; ipk++)
689  {
690  nh = 0;
691  for (in = 0; in < nhit; in++)
692  {
693  if (tmpEnergy[in] > 0)
694  {
695  ixy = hlist[in].ich;
696  a = hlist[in].amp * Energy[ipk][in] / tmpEnergy[in];
697  if (a > fgEmin)
698  {
699  phit[nh].ich = ixy;
700  phit[nh].amp = a;
701  phit[nh].tof = hlist[in].tof;
702 
703  nh++;
704  }
705  }
706  } // for( in
707  if (nh > 0)
708  {
709  // *ip++ = hlist[PeakCh[ipk]];
710  ppeaks.push_back(hlist[PeakCh[ipk]]);
711  hl.clear();
712  for (in = 0; in < nh; in++)
713  {
714  hl.push_back(phit[in]);
715  }
716  peak.ReInitialize(hl);
717  PkList.push_back(peak);
718  nn++;
719  }
720  } // for( ipk
721 
722  delete[] phit;
723  delete[] hlist;
724  for (ipk = 0; ipk < npk; ipk++)
725  {
726  delete[] Energy[ipk];
727  }
728  delete[] totEnergy;
729  delete[] tmpEnergy;
730 
731  return nn;
732 }