Back to home page

sPhenix code displayed by LXR

 
 

    


File indexing completed on 2025-08-06 08:17:31

0001 // Name: EmcCluster.cxx
0002 // Author: A. Bazilevsky (RIKEN-BNL)
0003 // Major modifications by M. Volkov (RRC KI) Jan 27 2000
0004 
0005 #include "BEmcCluster.h"
0006 #include "BEmcRec.h"
0007 
0008 #include <iostream>
0009 
0010 // Define and initialize static members
0011 
0012 // Max number of peaks in cluster; used in EmcCluster::GetSubClusters(...)
0013 int const EmcCluster::fgMaxNofPeaks = 1000;
0014 
0015 // Used in EmcCluster::GetSubClusters(...), it is the number of iterations
0016 // when fitting photons to peak areas
0017 int const EmcCluster::fgPeakIter = 6;
0018 
0019 // Emin cuts cluster energy: Ecl >= Epk1+Epk2 +...+Epkn !!!!!!!!!!!!!
0020 float const EmcCluster::fgEmin = 0.002;
0021 
0022 // ///////////////////////////////////////////////////////////////////////////
0023 // EmcCluster member functions
0024 
0025 void EmcCluster::GetCorrPos(float& xc, float& yc)
0026 // Returns the cluster corrected position in tower units
0027 // Corrected for S-oscilations, not for shower depth
0028 // Shower depth (z-coord) is defined in fOwner->Tower2Global()
0029 {
0030   float e;
0031   float x;
0032   float y;
0033   float xx;
0034   float yy;
0035   float xy;
0036 
0037   fOwner->Momenta(&fHitList, e, x, y, xx, yy, xy);
0038   fOwner->CorrectPosition(e, x, y, xc, yc);
0039 }
0040 
0041 // ///////////////////////////////////////////////////////////////////////////
0042 
0043 void EmcCluster::GetGlobalPos(float& xA, float& yA, float& zA)
0044 // Returns the cluster position in PHENIX global coord system
0045 {
0046   float xc;
0047   float yc;
0048   float e = GetTotalEnergy();
0049   GetCorrPos(xc, yc);
0050   fOwner->Tower2Global(e, xc, yc, xA, yA, zA);
0051 }
0052 
0053 // ///////////////////////////////////////////////////////////////////////////
0054 
0055 float EmcCluster::GetTowerEnergy(int ich)
0056 // Returns the energy of the ich-tower (0 if ich not found in the fHitList)
0057 {
0058   std::vector<EmcModule>::iterator ph;
0059   if (fHitList.empty())
0060   {
0061     return 0;
0062   }
0063   ph = fHitList.begin();
0064   while (ph != fHitList.end())
0065   {
0066     if ((*ph).ich == ich)
0067     {
0068       return (*ph).amp;
0069     }
0070     ++ph;
0071   }
0072   return 0;
0073 }
0074 
0075 // ///////////////////////////////////////////////////////////////////////////
0076 
0077 float EmcCluster::GetTowerEnergy(int ix, int iy)
0078 // Returns the energy of the tower ix,iy (0 if tower not found in the fHitList)
0079 {
0080   std::vector<EmcModule>::iterator ph;
0081 
0082   if (fHitList.empty())
0083   {
0084     return 0;
0085   }
0086   ph = fHitList.begin();
0087   int ich = (iy * fOwner->GetNx()) + ix;
0088   return GetTowerEnergy(ich);
0089 }
0090 
0091 // ///////////////////////////////////////////////////////////////////////////
0092 
0093 float EmcCluster::GetTowerToF(int ich)
0094 // Returns the ToF of the ich-tower (0 if ich not found in the fHitList)
0095 {
0096   std::vector<EmcModule>::iterator ph;
0097   if (fHitList.empty())
0098   {
0099     return 0;
0100   }
0101   ph = fHitList.begin();
0102   while (ph != fHitList.end())
0103   {
0104     if ((*ph).ich == ich)
0105     {
0106       return (*ph).tof;
0107     }
0108     ++ph;
0109   }
0110   return 0;
0111 }
0112 
0113 // ///////////////////////////////////////////////////////////////////////////
0114 
0115 float EmcCluster::GetTotalEnergy()
0116 // Returns the cluster total energy
0117 {
0118   std::vector<EmcModule>::iterator ph;
0119   float et = 0;
0120   if (fHitList.empty())
0121   {
0122     return 0;
0123   }
0124   ph = fHitList.begin();
0125   while (ph != fHitList.end())
0126   {
0127     et += (*ph).amp;
0128     ++ph;
0129   }
0130   return et;
0131 }
0132 
0133 // ///////////////////////////////////////////////////////////////////////////
0134 
0135 float EmcCluster::GetECoreCorrected()
0136 // Returns the energy in core towers around the cluster Center of Gravity
0137 // Corrected for energy leak sidewise from core towers
0138 {
0139   float e;
0140   float x;
0141   float y;
0142   float xx;
0143   float yy;
0144   float xy;
0145   float ecore;
0146   float ecorecorr;
0147   ecore = GetECore();
0148   fOwner->Momenta(&fHitList, e, x, y, xx, yy, xy);
0149   fOwner->CorrectECore(ecore, x, y, ecorecorr);
0150   return ecorecorr;
0151 }
0152 
0153 float EmcCluster::GetECore()
0154 // Returns the energy in core towers around the cluster Center of Gravity
0155 {
0156   const float thresh = 0.01;
0157 
0158   std::vector<EmcModule>::iterator ph;
0159   float xcg;
0160   float ycg;
0161   float xx;
0162   float xy;
0163   float yy;
0164   float energy;
0165   float es;
0166 
0167   fOwner->Momenta(&fHitList, energy, xcg, ycg, xx, yy, xy);
0168   //  fOwner->SetProfileParameters(0, energy, xcg, ycg);
0169 
0170   es = 0;
0171   if (fHitList.empty())
0172   {
0173     return 0;
0174   }
0175   ph = fHitList.begin();
0176   while (ph != fHitList.end())
0177   {
0178     int ixy = (*ph).ich;
0179     int iy = ixy / fOwner->GetNx();
0180     int ix = ixy - (iy * fOwner->GetNx());
0181     //      dx = xcg - ix;
0182     //    float dx = fOwner->fTowerDist(float(ix), xcg);
0183     //    float dy = ycg - iy;
0184     //    float et = fOwner->PredictEnergy(dx, dy, energy);
0185     float et = fOwner->PredictEnergy(energy, xcg, ycg, ix, iy);
0186     if (et > thresh)
0187     {
0188       es += (*ph).amp;
0189     }
0190     ++ph;
0191   }
0192   return es;
0193 }
0194 
0195 // ///////////////////////////////////////////////////////////////////////////
0196 
0197 float EmcCluster::GetE4()
0198 // Returns the energy in 2x2 towers around the cluster Center of Gravity
0199 {
0200   float et;
0201   float xcg;
0202   float ycg;
0203   float xx;
0204   float xy;
0205   float yy;
0206   float e1;
0207   float e2;
0208   float e3;
0209   float e4;
0210   int ix0;
0211   int iy0;
0212   int isx;
0213   int isy;
0214 
0215   fOwner->Momenta(&fHitList, et, xcg, ycg, xx, yy, xy);
0216 // NOLINTNEXTLINE(bugprone-incorrect-roundings)
0217   ix0 = int(xcg + 0.5);
0218 // NOLINTNEXTLINE(bugprone-incorrect-roundings)
0219   iy0 = int(ycg + 0.5);
0220 
0221   isx = 1;
0222   if (xcg - ix0 < 0)
0223   {
0224     isx = -1;
0225   }
0226   isy = 1;
0227   if (ycg - iy0 < 0)
0228   {
0229     isy = -1;
0230   }
0231 
0232   e1 = GetTowerEnergy(ix0, iy0);
0233   e2 = GetTowerEnergy(ix0 + isx, iy0);
0234   e3 = GetTowerEnergy(ix0 + isx, iy0 + isy);
0235   e4 = GetTowerEnergy(ix0, iy0 + isy);
0236 
0237   return (e1 + e2 + e3 + e4);
0238 }
0239 // ///////////////////////////////////////////////////////////////////////////
0240 
0241 float EmcCluster::GetE9()
0242 // Returns the energy in 3x3 towers around the cluster Center of Gravity
0243 {
0244   float et;
0245   float xcg;
0246   float ycg;
0247   float xx;
0248   float xy;
0249   float yy;
0250   int ich;
0251   int ix0;
0252   int iy0;
0253   int nhit;
0254 
0255   nhit = fHitList.size();
0256 
0257   if (nhit <= 0)
0258   {
0259     return 0;
0260   }
0261 
0262   fOwner->Momenta(&fHitList, et, xcg, ycg, xx, yy, xy);
0263 // NOLINTNEXTLINE(bugprone-incorrect-roundings)
0264   ix0 = int(xcg + 0.5);
0265 // NOLINTNEXTLINE(bugprone-incorrect-roundings)
0266   iy0 = int(ycg + 0.5);
0267   ich = iy0 * fOwner->GetNx() + ix0;
0268 
0269   return GetE9(ich);
0270 }
0271 
0272 // ///////////////////////////////////////////////////////////////////////////
0273 
0274 float EmcCluster::GetE9(int ich)
0275 // Returns the energy in 3x3 towers around the tower ich
0276 {
0277   std::vector<EmcModule>::iterator ph;
0278 
0279   int iy0 = ich / fOwner->GetNx();
0280   int ix0 = ich - (iy0 * fOwner->GetNx());
0281 
0282   float es = 0;
0283   if (fHitList.empty())
0284   {
0285     return 0;
0286   }
0287   ph = fHitList.begin();
0288   while (ph != fHitList.end())
0289   {
0290     int ixy = (*ph).ich;
0291     int iy = ixy / fOwner->GetNx();
0292     int ix = ixy - (iy * fOwner->GetNx());
0293     int idx = fOwner->iTowerDist(ix0, ix);
0294     int idy = iy - iy0;
0295     if (abs(idx) <= 1 && abs(idy) <= 1)
0296     {
0297       es += (*ph).amp;
0298     }
0299     ++ph;
0300   }
0301   return es;
0302 }
0303 
0304 // ///////////////////////////////////////////////////////////////////////////
0305 
0306 EmcModule EmcCluster::GetMaxTower()
0307 // Returns the EmcModule with the maximum energy
0308 {
0309   std::vector<EmcModule>::iterator ph;
0310   float emax = 0;
0311   EmcModule ht;
0312 
0313   ht.ich = -1;
0314   ht.amp = 0;
0315   ht.tof = 0;
0316   if (fHitList.empty())
0317   {
0318     return ht;
0319   }
0320 
0321   ph = fHitList.begin();
0322   while (ph != fHitList.end())
0323   {
0324     if ((*ph).amp > emax)
0325     {
0326       emax = (*ph).amp;
0327       ht = *ph;
0328     }
0329     ++ph;
0330   }
0331   return ht;
0332 }
0333 
0334 // ///////////////////////////////////////////////////////////////////////////
0335 
0336 void EmcCluster::GetMoments(float& x, float& y, float& xx, float& xy, float& yy)
0337 //  Returns cluster 1-st (px,py) and 2-d momenta (pxx,pxy,pyy) in cell unit
0338 {
0339   float e;
0340   fOwner->Momenta(&fHitList, e, x, y, xx, yy, xy);
0341 }
0342 
0343 // ///////////////////////////////////////////////////////////////////////////
0344 
0345 float EmcCluster::GetProb(float& chi2, int& ndf)
0346 {
0347   float e;
0348   float xg;
0349   float yg;
0350   float zg;
0351   e = GetTotalEnergy();
0352   xg = 0; 
0353   GetGlobalPos(xg, yg, zg);
0354   return fOwner->GetProb(fHitList, e, xg, yg, zg, chi2, ndf);
0355 }
0356 
0357 // ///////////////////////////////////////////////////////////////////////////
0358 
0359 int EmcCluster::GetSubClusters(std::vector<EmcCluster>& PkList, std::vector<EmcModule>& ppeaks, bool dosubclustersplitting)
0360 {
0361   // Splits the cluster onto subclusters
0362   // The number of subclusters is equal to the number of Local Maxima in a cluster.
0363   // Local Maxima can have the energy not less then
0364   // defined in fgMinPeakEnergy
0365   //
0366   // Output: PkList - vector of subclusters
0367   //         ppeaks - vector of peak EmcModules (one for each subcluster)
0368   //
0369   // Returns: >= 0 Number of Peaks;
0370   //          -1 The number of Peaks is greater then fgMaxNofPeaks;
0371   //         (just increase parameter fgMaxNofPeaks)
0372 
0373   int npk;
0374   int ipk;
0375   int nhit;
0376   int ixypk;
0377   int ixpk;
0378   int iypk;
0379   int in;
0380   int nh;
0381   int ic;
0382   int ixy;
0383   int ix;
0384   int iy;
0385   int nn;
0386   int idx;
0387   int idy;
0388   int ig;
0389   int ng;
0390   int igmpk1[fgMaxNofPeaks];
0391   int igmpk2[fgMaxNofPeaks];
0392   int PeakCh[fgMaxNofPeaks];
0393   float epk[fgMaxNofPeaks * 2];
0394   float xpk[fgMaxNofPeaks * 2];
0395   float ypk[fgMaxNofPeaks * 2];
0396   float ratio;
0397   float eg;
0398   float dx;
0399   float dy;
0400   float a;
0401   float *Energy[fgMaxNofPeaks];
0402   float *totEnergy;
0403   float *tmpEnergy;
0404   EmcModule *phit;
0405   EmcModule *hlist;
0406   EmcModule *vv;
0407   EmcCluster peak(fOwner);
0408   std::vector<EmcModule>::iterator ph;
0409   std::vector<EmcModule> hl;
0410 
0411   PkList.clear();
0412   ppeaks.clear();
0413 
0414   nhit = fHitList.size();
0415 
0416   if (nhit <= 0)
0417   {
0418     return 0;
0419   }
0420 
0421   hlist = new EmcModule[nhit];
0422 
0423   ph = fHitList.begin();
0424   vv = hlist;
0425   while (ph != fHitList.end())
0426   {
0427     *vv++ = *ph++;// NOLINT(bugprone-pointer-arithmetic-on-polymorphic-object)
0428   }
0429 
0430   // sort by linear channel number
0431   qsort(hlist, nhit, sizeof(EmcModule), BEmcRec::HitNCompare);
0432 
0433   //
0434   //  Find peak (maximum) position (towers with local maximum amp)
0435   //
0436 
0437   int maxc=0;
0438   float maxamp = 0;
0439 
0440   npk = 0;
0441   for (ic = 0; ic < nhit; ic++)
0442   {
0443     float amp = hlist[ic].amp;// NOLINT(bugprone-pointer-arithmetic-on-polymorphic-object)
0444     if (amp > fOwner->GetPeakThreshold())
0445     {
0446       int ich = hlist[ic].ich;// NOLINT(bugprone-pointer-arithmetic-on-polymorphic-object)
0447       // old      int ichmax = ich + fOwner->GetNx() + 1;
0448       // old      int ichmin = ich - fOwner->GetNx() - 1;
0449       //  Look into three raws only
0450       int ichmax = ((ich / fOwner->GetNx() + 2) * fOwner->GetNx()) - 1;
0451       int ichmin = (ich / fOwner->GetNx() - 1) * fOwner->GetNx();
0452       int ixc = ich - (ich / fOwner->GetNx() * fOwner->GetNx());
0453       int inA = ic + 1;
0454       // check right, and 3 towers above if there is another max
0455       while ((inA < nhit) && (hlist[inA].ich <= ichmax))// NOLINT(bugprone-pointer-arithmetic-on-polymorphic-object)
0456       {
0457         int ixA = hlist[inA].ich - (hlist[inA].ich / fOwner->GetNx() * fOwner->GetNx());// NOLINT(bugprone-pointer-arithmetic-on-polymorphic-object)
0458         // old  if( (abs(ixc-ixA) <= 1) && (hlist[inA].amp >= amp) ) goto new_ic;
0459         if ((std::abs(fOwner->iTowerDist(ixA, ixc)) <= 1) && (hlist[inA].amp >= amp))// NOLINT(bugprone-pointer-arithmetic-on-polymorphic-object)
0460         {
0461           goto new_ic;
0462         }
0463         inA++;
0464       }
0465       inA = ic - 1;
0466       // check left, and 3 towers below if there is another max
0467       while ((inA >= 0) && (hlist[inA].ich >= ichmin))// NOLINT(bugprone-pointer-arithmetic-on-polymorphic-object)
0468       {
0469         int ixA = hlist[inA].ich - (hlist[inA].ich / fOwner->GetNx() * fOwner->GetNx());// NOLINT(bugprone-pointer-arithmetic-on-polymorphic-object)
0470         // old  if( (abs(ixc-ixA) <= 1) && (hlist[inA].amp > amp) ) goto new_ic;
0471         if ((std::abs(fOwner->iTowerDist(ixA, ixc)) <= 1) && (hlist[inA].amp > amp))// NOLINT(bugprone-pointer-arithmetic-on-polymorphic-object)
0472         {
0473           goto new_ic;
0474         }
0475         inA--;
0476       }
0477       if (npk >= fgMaxNofPeaks)
0478       {
0479         delete[] hlist;
0480         std::cout << "!!! Error in EmcCluster::GetSubClusters(): too many peaks in a cluster (>"
0481                   << fgMaxNofPeaks
0482                   << "). May need tower energy threshold increase for clustering." << std::endl;
0483         return -1;
0484       }
0485 
0486       // ic is a maximum in a 3x3 tower group
0487       if (amp > maxamp) {
0488         maxamp = amp;
0489         maxc = npk;
0490       }   
0491       PeakCh[npk] = ic;
0492       npk++;
0493     }
0494   new_ic:
0495     continue;
0496   }
0497   /*
0498   for( ipk=0; ipk<npk; ipk++ ) {
0499     ic = PeakCh[ipk];
0500     std::cout << "  " << ipk << ": E = " << hlist[ic].amp << std::endl;
0501   }
0502   */
0503 
0504   if(!dosubclustersplitting){
0505     hl.clear();
0506     for (int ich = 0; ich < nhit; ich++)
0507     {
0508       hl.push_back(hlist[ich]);// NOLINT(bugprone-pointer-arithmetic-on-polymorphic-object)
0509     }
0510     peak.ReInitialize(hl);
0511     PkList.push_back(peak);
0512 
0513     if (npk > 0)
0514     {
0515       ppeaks.push_back(hlist[PeakCh[maxc]]);// NOLINT(bugprone-pointer-arithmetic-on-polymorphic-object)
0516     }
0517     else
0518     {
0519       ppeaks.push_back(GetMaxTower());
0520     }
0521     delete[] hlist;
0522     return 1;
0523   }
0524 
0525 
0526   // there was only one peak
0527   if(npk <= 1)
0528   {
0529     hl.clear();
0530     for (int ich = 0; ich < nhit; ich++)
0531     {
0532       hl.push_back(hlist[ich]);// NOLINT(bugprone-pointer-arithmetic-on-polymorphic-object)
0533     }
0534     peak.ReInitialize(hl);
0535     PkList.push_back(peak);
0536 
0537     if (npk == 1)
0538     {
0539       ppeaks.push_back(hlist[PeakCh[0]]);// NOLINT(bugprone-pointer-arithmetic-on-polymorphic-object)
0540     }
0541     else
0542     {
0543       ppeaks.push_back(GetMaxTower());
0544     }
0545 
0546     delete[] hlist;
0547     return 1;
0548   }
0549 
0550   // there were more than one peak
0551 
0552   for (ipk = 0; ipk < npk; ipk++)
0553   {
0554     Energy[ipk] = new float[nhit];
0555   }
0556   totEnergy = new float[nhit];
0557   tmpEnergy = new float[nhit];
0558   for (int i = 0; i < nhit; ++i)
0559   {
0560     totEnergy[i] = 0.0;
0561     tmpEnergy[i] = 0.0;
0562   }
0563   //
0564   // Divide energy in towers among photons positioned in every peak
0565   //
0566   ratio = 1.;
0567   for (int iter = 0; iter < fgPeakIter; iter++)
0568   {
0569     BEmcRec::ZeroVector(tmpEnergy, nhit);
0570     for (ipk = 0; ipk < npk; ipk++)
0571     {
0572       ic = PeakCh[ipk];
0573       if (iter > 0)
0574       {
0575         ratio = Energy[ipk][ic] / totEnergy[ic];
0576       }
0577       eg = hlist[ic].amp * ratio;// NOLINT(bugprone-pointer-arithmetic-on-polymorphic-object)
0578       ixypk = hlist[ic].ich;// NOLINT(bugprone-pointer-arithmetic-on-polymorphic-object)
0579       iypk = ixypk / fOwner->GetNx();
0580       ixpk = ixypk - iypk * fOwner->GetNx();
0581       epk[ipk] = eg;
0582       xpk[ipk] = 0.;  // CoG from the peak tower
0583       ypk[ipk] = 0.;  // CoG from the peak tower
0584 
0585       int ichmax = ((iypk + 2) * fOwner->GetNx()) - 1;
0586       int ichmin = (iypk - 1) * fOwner->GetNx();
0587 
0588       // add up energies of tower to the right and up
0589       if (ic < nhit - 1)
0590       {
0591         for (in = ic + 1; in < nhit; in++)
0592         {
0593           ixy = hlist[in].ich;// NOLINT(bugprone-pointer-arithmetic-on-polymorphic-object)
0594           iy = ixy / fOwner->GetNx();
0595           ix = ixy - iy * fOwner->GetNx();
0596 
0597           // old      if( (ixy-ixypk) > fOwner->GetNx()+1 ) break;
0598           if (ixy > ichmax)
0599           {
0600             break;
0601           }
0602           // old      if( abs(ix-ixpk) <= 1 ) {
0603           idx = fOwner->iTowerDist(ixpk, ix);
0604           idy = iy - iypk;
0605           if (abs(idx) <= 1)
0606           {
0607             if (iter > 0)
0608             {
0609               ratio = Energy[ipk][in] / totEnergy[in];
0610             }
0611             eg = hlist[in].amp * ratio;// NOLINT(bugprone-pointer-arithmetic-on-polymorphic-object)
0612             epk[ipk] += eg;
0613             xpk[ipk] += eg * idx;
0614             ypk[ipk] += eg * idy;
0615           }
0616         }
0617       }  // if ic
0618 
0619       // add up energies of tower to the left and down
0620       if (ic >= 1)
0621       {
0622         for (in = ic - 1; in >= 0; in--)
0623         {
0624           ixy = hlist[in].ich;// NOLINT(bugprone-pointer-arithmetic-on-polymorphic-object)
0625           iy = ixy / fOwner->GetNx();
0626           ix = ixy - iy * fOwner->GetNx();
0627 
0628           // old      if( (ixypk-ixy) > fOwner->GetNx()+1 ) break;
0629           if (ixy < ichmin)
0630           {
0631             break;
0632           }
0633           // old      if( abs(ix-ixpk) <= 1 ) {
0634           idx = fOwner->iTowerDist(ixpk, ix);
0635           idy = iy - iypk;
0636           if (abs(idx) <= 1)
0637           {
0638             if (iter > 0)
0639             {
0640               ratio = Energy[ipk][in] / totEnergy[in];
0641             }
0642             eg = hlist[in].amp * ratio;// NOLINT(bugprone-pointer-arithmetic-on-polymorphic-object)
0643             epk[ipk] += eg;
0644             xpk[ipk] += eg * idx;
0645             ypk[ipk] += eg * idy;
0646           }
0647         }
0648       }  // if ic
0649 
0650       xpk[ipk] = xpk[ipk] / epk[ipk] + ixpk;
0651       ypk[ipk] = ypk[ipk] / epk[ipk] + iypk;
0652       //      fOwner->SetProfileParameters(0, epk[ipk], xpk[ipk], ypk[ipk]);
0653 
0654       for (in = 0; in < nhit; in++)
0655       {
0656         ixy = hlist[in].ich;// NOLINT(bugprone-pointer-arithmetic-on-polymorphic-object)
0657         iy = ixy / fOwner->GetNx();
0658         ix = ixy - iy * fOwner->GetNx();
0659         dx = fOwner->fTowerDist(float(ix), xpk[ipk]);
0660         dy = ypk[ipk] - iy;
0661         a = 0;
0662 
0663         // predict energy within 2.5 cell square around local peak
0664         if (ABS(dx) < 2.5 && ABS(dy) < 2.5)
0665         {
0666           //          a = epk[ipk] * fOwner->PredictEnergy(dx, dy, epk[ipk]);
0667           a = epk[ipk] * fOwner->PredictEnergy(epk[ipk], xpk[ipk], ypk[ipk], ix, iy);
0668         }
0669 
0670         Energy[ipk][in] = a;
0671         tmpEnergy[in] += a;
0672       }
0673 
0674     }  // for ipk
0675     float flim = 0.000001;
0676     for (in = 0; in < nhit; in++)
0677     {
0678       if (tmpEnergy[in] > flim)
0679       {
0680         totEnergy[in] = tmpEnergy[in];
0681       }
0682       else
0683       {
0684         totEnergy[in] = flim;
0685       }
0686     }
0687   }  // for iter
0688 
0689   phit = new EmcModule[nhit];
0690 
0691   ng = 0;
0692   for (ipk = 0; ipk < npk; ipk++)
0693   {
0694     nh = 0;
0695 
0696     // fill phit, the tower distribution for a peak
0697     for (in = 0; in < nhit; in++)
0698     {
0699       if (tmpEnergy[in] > 0)
0700       {
0701         ixy = hlist[in].ich;// NOLINT(bugprone-pointer-arithmetic-on-polymorphic-object)
0702         a = hlist[in].amp * Energy[ipk][in] / tmpEnergy[in];// NOLINT(bugprone-pointer-arithmetic-on-polymorphic-object)
0703         if (a > fgEmin)
0704         {
0705           phit[nh].ich = ixy;// NOLINT(bugprone-pointer-arithmetic-on-polymorphic-object)
0706           phit[nh].amp = a;// NOLINT(bugprone-pointer-arithmetic-on-polymorphic-object)
0707           phit[nh].tof = hlist[in].tof; // NOLINT(bugprone-pointer-arithmetic-on-polymorphic-object) // Not necessary here
0708 
0709           nh++;
0710         }
0711       }
0712     }
0713 
0714     // if number hits > 0
0715     if (nh > 0)
0716     {
0717       // !!!!! Exclude Gamma() for now until it is proved working and useful
0718       /*
0719       chi=fOwner->Chi2Limit(nh)*10;
0720       int ndf; // just a plug for changed Gamma parameter list MV 28.01.00
0721 
0722       fOwner->Gamma(nh, phit,&chi, &chi0, &epk[ng], &xpk[ng], &ypk[ng],
0723                     &epk[ng+1], &xpk[ng+1], &ypk[ng+1], ndf);
0724 
0725       igmpk1[ipk]=ng;
0726       igmpk2[ipk]=ng;
0727       if( epk[ng+1]>0 ) { ng++; igmpk2[ipk]=ng;}
0728       */
0729       igmpk1[ipk] = ng;
0730       igmpk2[ipk] = ng;
0731 
0732       ng++;
0733     }
0734     else
0735     {
0736       igmpk1[ipk] = -1;
0737       igmpk2[ipk] = -1;
0738     }
0739   }  // for( ipk=
0740 
0741   BEmcRec::ZeroVector(tmpEnergy, nhit);
0742   for (ipk = 0; ipk < npk; ipk++)
0743   {
0744     ig = igmpk1[ipk];
0745     if (ig >= 0)
0746     {
0747       //      std::cout << "  " << ipk << ": X = " << xpk[ig]
0748       //           << " Y = " << ypk[ig] << std::endl;
0749       //      fOwner->SetProfileParameters(0, epk[ig], xpk[ig], ypk[ig]);
0750       for (in = 0; in < nhit; in++)
0751       {
0752         Energy[ipk][in] = 0;
0753         for (ig = igmpk1[ipk]; ig <= igmpk2[ipk]; ig++)
0754         {
0755           ixy = hlist[in].ich;// NOLINT(bugprone-pointer-arithmetic-on-polymorphic-object)
0756           iy = ixy / fOwner->GetNx();
0757           ix = ixy - iy * fOwner->GetNx();
0758           dx = fOwner->fTowerDist(float(ix), xpk[ig]);
0759           dy = ypk[ig] - iy;
0760           //          a = epk[ig] * fOwner->PredictEnergy(dx, dy, epk[ig]);
0761           a = epk[ig] * fOwner->PredictEnergy(epk[ig], xpk[ig], ypk[ig], ix, iy);
0762           Energy[ipk][in] += a;
0763           tmpEnergy[in] += a;
0764         }
0765       }  // for( in
0766     }    // if( ig >= 0
0767   }      // for( ipk
0768 
0769   nn = 0;
0770   for (ipk = 0; ipk < npk; ipk++)
0771   {
0772     nh = 0;
0773     for (in = 0; in < nhit; in++)
0774     {
0775       if (tmpEnergy[in] > 0)
0776       {
0777         ixy = hlist[in].ich;// NOLINT(bugprone-pointer-arithmetic-on-polymorphic-object)
0778         a = hlist[in].amp * Energy[ipk][in] / tmpEnergy[in];// NOLINT(bugprone-pointer-arithmetic-on-polymorphic-object)
0779         if (a > fgEmin)
0780         {
0781           phit[nh].ich = ixy;// NOLINT(bugprone-pointer-arithmetic-on-polymorphic-object)
0782           phit[nh].amp = a;// NOLINT(bugprone-pointer-arithmetic-on-polymorphic-object)
0783           phit[nh].tof = hlist[in].tof;// NOLINT(bugprone-pointer-arithmetic-on-polymorphic-object)
0784 
0785           nh++;
0786         }
0787       }
0788     }  // for( in
0789     if (nh > 0)
0790     {
0791       //      *ip++ = hlist[PeakCh[ipk]];
0792       ppeaks.push_back(hlist[PeakCh[ipk]]);// NOLINT(bugprone-pointer-arithmetic-on-polymorphic-object)
0793       hl.clear();
0794       for (in = 0; in < nh; in++)
0795       {
0796         hl.push_back(phit[in]);// NOLINT(bugprone-pointer-arithmetic-on-polymorphic-object)
0797       }
0798       peak.ReInitialize(hl);
0799       PkList.push_back(peak);
0800       nn++;
0801     }
0802   }  // for( ipk
0803 
0804   delete[] phit;
0805   delete[] hlist;
0806   for (ipk = 0; ipk < npk; ipk++)
0807   {
0808     delete[] Energy[ipk];
0809   }
0810   delete[] totEnergy;
0811   delete[] tmpEnergy;
0812 
0813   return nn;
0814 }