EmcCluster.cxx

Go to the documentation of this file.
00001 // Name: EmcCluster.cxx
00002 // Author: A. Bazilevsky (RIKEN-BNL)
00003 // Major modifications by M. Volkov (RRC KI) Jan 27 2000
00004 
00005 #include "EmcCluster.h"
00006 #include "EmcSectorRec.h"
00007 
00008 using namespace std;
00009 
00010 // Define and initialize static members
00011 
00012 // Max number of peaks in cluster; used in EmcCluster::GetPeaks(...)
00013 int const EmcCluster::fgMaxNofPeaks=10;
00014 
00015 // Used in EmcCluster::GetPeaks(...), it is the number of iterations
00016 // when fitting photons to peak areas
00017 int const EmcCluster::fgPeakIter=6;
00018 
00019 // Emin cuts cluster energy: Ecl >= Epk1+Epk2 +...+Epkn !!!!!!!!!!!!!
00020 float const EmcCluster::fgEmin=0.002;
00021 
00022 // chisq=3 devides about 1% of single showers (now it isn't used)
00023 float const EmcCluster::fgChisq=3.;
00024 
00025 // define meaningless values for (x,y)
00026 float const EmcCluster::fgXABSURD=-999999.;
00027 float const EmcCluster::fgYABSURD=-999999.;
00028 
00029 EmcModule::EmcModule() 
00030   : ich(0),
00031     softKey(0),
00032     amp(0),
00033     tof(0),
00034     deadmap(0),
00035     warnmap(0),
00036     adc(0),
00037     tac(0)
00038 {
00039 }
00040 
00041 //_____________________________________________________________________________
00042 EmcModule::EmcModule(int ich_, int softkey_, float amp_, float tof_,
00043                      int deadmap_, int warnmap_, float adc_, float tac_) 
00044   : ich(ich_),
00045     softKey(softkey_),
00046     amp(amp_),
00047     tof(tof_),
00048     deadmap(deadmap_),
00049     warnmap(warnmap_),
00050     adc(adc_),
00051     tac(tac_)                               
00052 {  
00053 }
00054 
00055 // ///////////////////////////////////////////////////////////////////////////
00056 // EmcCluster member functions
00057 
00058 void EmcCluster::GetCorrPos(float* px, float* py)
00059 {
00060   // Returns the cluster corrected position in Sector (SM) frame
00061   
00062   float e, x, y, xx, yy, xy;
00063   
00064   e = GetTotalEnergy();
00065   GetMoments(&x, &y, &xx, &xy, &yy);
00066   fOwner->CorrectPosition(e, x, y, px, py);
00067 }
00068 
00069 // ///////////////////////////////////////////////////////////////////////////
00070 
00071 void EmcCluster::GetGlobalPos( float* px, float* py, float* pz )
00072 // Returns the cluster position in PHENIX global coord system
00073 {
00074 
00075    float xc, yc;
00076 
00077    GetCorrPos( &xc, &yc );
00078 // X in Sector coord is Z in Global coord !!
00079    fOwner->SectorToGlobal( xc, yc, 0., px, py, pz );
00080 
00081 }
00082 
00083 // ///////////////////////////////////////////////////////////////////////////
00084 
00085 float EmcCluster::GetTowerEnergy( int ich )
00086 // Returns the energy of the ich-tower (0 if ich not found in the fHitList)
00087 {
00088      vector<EmcModule>::iterator ph;
00089      if( fHitList.empty() ) return 0;
00090      ph = fHitList.begin();
00091      while( ph != fHitList.end() ) {
00092        if( (*ph).ich == ich ) return (*ph).amp;
00093         ph++;
00094      }
00095      return 0;
00096 }
00097 
00098 // ///////////////////////////////////////////////////////////////////////////
00099 
00100 float EmcCluster::GetTowerEnergy( int ix, int iy )
00101 // Returns the energy of the tower ix,iy (0 if tower not found in the fHitList)
00102 {
00103      int ich, ixl, iyl;
00104      vector<EmcModule>::iterator ph;
00105 
00106      if( fHitList.empty() ) return 0;
00107      ph = fHitList.begin();
00108      while( ph != fHitList.end() ) {
00109        ich = (*ph).ich;
00110        iyl = ich/fOwner->GetNx();
00111        ixl = ich % fOwner->GetNx();
00112        if( ixl == ix && iyl == iy ) return (*ph).amp;
00113         ph++;
00114      }
00115      return 0;
00116 }
00117 
00118 // ///////////////////////////////////////////////////////////////////////////
00119 float EmcCluster::GetTowerToF( int ich )
00120 // Returns the ToF of the ich-tower (0 if ich not found in the fHitList)
00121 {
00122      vector<EmcModule>::iterator ph;
00123      if( fHitList.empty() ) return 0;
00124      ph = fHitList.begin();
00125      while( ph != fHitList.end() ) {
00126        if( (*ph).ich == ich ) return (*ph).tof;
00127         ph++;
00128      }
00129      return 0;
00130 }
00131 
00132 // ///////////////////////////////////////////////////////////////////////////
00133 
00134 int EmcCluster::GetTowerDeadMap( int ich )
00135 // Returns the Dead Map of the ich-tower (0 if ich not found in the fHitList)
00136 {
00137      vector<EmcModule>::iterator ph;
00138      if( fHitList.empty() ) return 0;
00139      ph = fHitList.begin();
00140      while( ph != fHitList.end() ) {
00141        if( (*ph).ich == ich ) return (*ph).deadmap;
00142        ph++;
00143      }
00144      return 0;
00145 }
00146 
00147 // ///////////////////////////////////////////////////////////////////////////
00148 
00149 int EmcCluster::GetTowerWarnMap( int ich )
00150   // Returns the Warning Map of the ich-tower (0 if ich not found in the fHitList)
00151 {
00152      vector<EmcModule>::iterator ph;
00153      if( fHitList.empty() ) return 0;
00154      ph = fHitList.begin();
00155      while( ph != fHitList.end() ) {
00156        if( (*ph).ich == ich ) return (*ph).warnmap;
00157        ph++;
00158      }
00159      return 0;
00160 }
00161 
00162 // ///////////////////////////////////////////////////////////////////////////
00163 
00164 float EmcCluster::GetTowerADC( int ich )
00165   // Returns ADC of the ich-tower (0 if ich not found in the fHitList)
00166 {
00167      vector<EmcModule>::iterator ph;
00168      if( fHitList.empty() ) return 0;
00169      ph = fHitList.begin();
00170      while( ph != fHitList.end() ) {
00171        if( (*ph).ich == ich ) return (*ph).adc;
00172        ph++;
00173      }
00174      return 0.;
00175 }
00176 
00177 // ///////////////////////////////////////////////////////////////////////////
00178 
00179 float EmcCluster::GetTowerTAC( int ich )
00180   // Returns ADC of the ich-tower (0 if ich not found in the fHitList)
00181 {
00182      vector<EmcModule>::iterator ph;
00183      if( fHitList.empty() ) return 0;
00184      ph = fHitList.begin();
00185      while( ph != fHitList.end() ) {
00186        if( (*ph).ich == ich ) return (*ph).tac;
00187        ph++;
00188      }
00189      return 0.;
00190 }
00191 
00192 // ///////////////////////////////////////////////////////////////////////////
00193 
00194 // Returns Number of Dead Channels in 3x3 Modules around MaxTower
00195 // see emc-calib/Calib/emcQAs.C for deadmap defn.
00196 int EmcCluster::GetNDead()
00197 {
00198   EmcModule hmax = GetMaxTower();
00199   int dead = hmax.deadmap;
00200   int ndead = 0;
00201 
00202   dead = dead>>4;               // start at bit 4
00203   for ( int iy=0; iy<3; iy++ )
00204     {
00205       for ( int iz=0; iz<3; iz++ )
00206         {
00207           ndead += dead&1;
00208           dead = dead>>1;       // shift to next tower
00209         }
00210       dead = dead>>2;           // shift up to next row
00211     }
00212   return ndead;
00213 }
00214 
00215 // ///////////////////////////////////////////////////////////////////////////
00216 
00217 int EmcCluster::GetDeadMap()
00218 {
00219   // MV 2001/12/06 Returns the deadmap of the dominant tower
00220   
00221   EmcModule hmax = GetMaxTower();
00222   return hmax.deadmap;
00223 
00224 }
00225 
00226 // ///////////////////////////////////////////////////////////////////////////
00227 
00228 int EmcCluster::GetWarnMap()
00229 {
00230   // MV 2001/12/06 Returns the warnmap of the dominant tower
00231   
00232   EmcModule hmax = GetMaxTower();
00233   return hmax.warnmap;
00234 
00235 }
00236 
00237 // ///////////////////////////////////////////////////////////////////////////
00238 
00239 float EmcCluster::GetTotalEnergy()
00240 // Returns the cluster total energy
00241 {
00242      vector<EmcModule>::iterator ph;
00243      float et=0;
00244      if( fHitList.empty() ) return 0;
00245      ph = fHitList.begin();
00246      while( ph != fHitList.end() ) { 
00247         et += (*ph).amp;
00248         ph++;
00249      }
00250      return et;
00251 }
00252 
00253 // ///////////////////////////////////////////////////////////////////////////
00254 
00255 float EmcCluster::GetECore()
00256 // Returns the energy in 2x2 towers around the cluster Center of Gravity
00257 {
00258     vector<EmcModule>::iterator ph;
00259     float xcg, ycg, xx, xy, yy, dx, dy;
00260     float energy, es, et;
00261     int ix, iy, ixy;
00262 
00263     GetMoments( &xcg, &ycg, &xx, &xy, &yy );
00264     xcg /= fOwner->GetModSizex();
00265     ycg /= fOwner->GetModSizey();
00266     energy = GetTotalEnergy();
00267     fOwner->SetProfileParameters(0,energy,xcg,ycg);
00268 
00269     es=0;
00270     if( fHitList.empty() ) return 0;
00271     ph = fHitList.begin();
00272     while( ph != fHitList.end() ) { 
00273       ixy = (*ph).ich;
00274       iy = ixy/fOwner->GetNx();
00275       ix = ixy - iy*fOwner->GetNx();
00276       dx = xcg - ix;
00277       dy = ycg - iy;
00278       et = fOwner->PredictEnergy(dx, dy, -1);
00279       if( et > 0.02 ) es += (*ph).amp;
00280       ph++;
00281     }
00282     return es;
00283 }
00284 
00285 // ///////////////////////////////////////////////////////////////////////////
00286 
00287 float EmcCluster::GetE4()
00288 // Returns the energy in 2x2 towers around the cluster Center of Gravity
00289 {
00290     float xcg, ycg, xx, xy, yy;
00291     float e1, e2, e3, e4;
00292     int ix0, iy0, isx, isy;
00293 
00294     GetMoments( &xcg, &ycg, &xx, &xy, &yy );
00295     xcg /= fOwner->GetModSizex();
00296     ycg /= fOwner->GetModSizey();
00297     ix0 = int(xcg+0.5);
00298     iy0 = int(ycg+0.5);
00299 
00300     isx = 1;
00301     if( xcg-ix0 < 0 ) isx = -1;
00302     isy = 1;
00303     if( ycg-iy0 < 0 ) isy = -1;
00304 
00305     e1 = GetTowerEnergy(ix0,     iy0    );
00306     e2 = GetTowerEnergy(ix0+isx, iy0    );
00307     e3 = GetTowerEnergy(ix0+isx, iy0+isy);
00308     e4 = GetTowerEnergy(ix0    , iy0+isy);
00309 
00310     return (e1 + e2 + e3 + e4);
00311 }
00312 // ///////////////////////////////////////////////////////////////////////////
00313 
00314 float EmcCluster::GetE9()
00315 // Returns the energy in 3x3 towers around the cluster Center of Gravity
00316 {
00317      float xcg, ycg, xx, xy, yy;
00318      int i, ic, ich, ixc, ix0, iy0, ichmax, ichmin, nhit;
00319      float e;
00320      EmcModule *hlist, *vv;
00321      vector<EmcModule>::iterator ph;
00322 
00323      e=0;
00324 
00325      nhit = fHitList.size();
00326 
00327      if( nhit <= 0 ) return e;
00328 
00329      hlist = new EmcModule[nhit];
00330 
00331      ph = fHitList.begin();
00332      vv = hlist;
00333      while( ph != fHitList.end() ) *vv++ = *ph++;
00334 
00335      qsort( hlist, nhit, sizeof(EmcModule), fOwner->HitNCompare );
00336 
00337      GetMoments( &xcg, &ycg, &xx, &xy, &yy );
00338      xcg /= fOwner->GetModSizex();
00339      ycg /= fOwner->GetModSizey();
00340      ix0 = int(xcg+0.5);
00341      iy0 = int(ycg+0.5);
00342      ich = iy0*fOwner->GetNx() + ix0;
00343 
00344      ichmax = ich + fOwner->GetNx() + 1;
00345      ichmin = ich - fOwner->GetNx() - 1;
00346 
00347      for( i=0; i<nhit; i++ ) 
00348         if( hlist[i].ich >= ichmin ) break;
00349      while( (i < nhit) && ( (ic=hlist[i].ich) <= ichmax) ) {
00350         ixc = ic - ic/fOwner->GetNx()*fOwner->GetNx();
00351         if( abs(ixc-ix0) <= 1 ) e += hlist[i].amp;
00352         i++;
00353      }
00354         
00355      delete [] hlist;
00356      return e;
00357 }
00358 
00359 // ///////////////////////////////////////////////////////////////////////////
00360 
00361 float EmcCluster::GetE9( int ich )
00362 // Returns the energy in 3x3 towers around the tower ich
00363 {
00364      int i, ic, ixc, ix0, ichmax, ichmin, nhit;
00365      float e;
00366      EmcModule *hlist, *vv;
00367      vector<EmcModule>::iterator ph;
00368 
00369      e=0;
00370 
00371      nhit = fHitList.size();
00372 
00373      if( nhit <= 0 ) return e;
00374 
00375      hlist = new EmcModule[nhit];
00376 
00377      ph = fHitList.begin();
00378      vv = hlist;
00379      while( ph != fHitList.end() ) *vv++ = *ph++;
00380 
00381      qsort( hlist, nhit, sizeof(EmcModule), fOwner->HitNCompare );
00382 
00383      ichmax = ich + fOwner->GetNx() + 1;
00384      ichmin = ich - fOwner->GetNx() - 1;
00385      ix0 = ich - ich/fOwner->GetNx()*fOwner->GetNx();
00386 
00387      for( i=0; i<nhit; i++ ) 
00388         if( hlist[i].ich >= ichmin ) break;
00389      while( (i < nhit) && ( (ic=hlist[i].ich) <= ichmax) ) {
00390         ixc = ic - ic/fOwner->GetNx()*fOwner->GetNx();
00391         if( abs(ixc-ix0) <= 1 ) e += hlist[i].amp;
00392         i++;
00393      }
00394         
00395      delete [] hlist;
00396      return e;
00397 }
00398 
00399 // ///////////////////////////////////////////////////////////////////////////
00400 
00401 EmcModule EmcCluster::GetImpactTower()
00402 // Returns the EmcModule corresponding to the reconstructed impact tower
00403 {
00404      float x, y;
00405      int ix, iy, ich;
00406      EmcModule ht;
00407 
00408      GetCorrPos( &x, &y );
00409      ix = lowint(x/fOwner->GetModSizex() + 0.5);
00410      iy = lowint(y/fOwner->GetModSizey() + 0.5);
00411      if( ix < 0 || ix > fOwner->GetNx()-1 || iy < 0 || iy > fOwner->GetNy()-1 ) {
00412         printf("????? EmcClusterChi2: Something wrong in GetImpactTower: (x,y)=(%f,%f)  (ix,iy)=(%d,%d) \n", x, y, ix, iy);
00413         memset(&ht, 0, sizeof(EmcModule)); // MV 2002/03/12 bugfix
00414         ht.ich = -1;
00415         return ht;
00416      }
00417      else {
00418         ich = iy*fOwner->GetNx() + ix;
00419         ht.ich = ich;
00420         ht.amp = GetTowerEnergy( ich );
00421         ht.tof = GetTowerToF( ich );
00422         ht.deadmap = GetTowerDeadMap( ich );
00423         ht.warnmap = GetTowerWarnMap( ich ); // MV 2002/02/18 bugfix
00424         ht.adc=GetTowerADC(ich); // MV 2002/03/12 bugfix
00425         ht.tac=GetTowerTAC(ich); // MV 2002/03/12 bugfix
00426         return ht;
00427      }
00428 }
00429 
00430 // ///////////////////////////////////////////////////////////////////////////
00431 
00432 EmcModule EmcCluster::GetMaxTower()
00433 // Returns the EmcModule with the maximum energy
00434 {
00435      vector<EmcModule>::iterator ph;
00436      float emax=0;
00437      EmcModule ht;
00438 
00439      memset(&ht, 0, sizeof(EmcModule)); // MV 2002/03/12 bugfix
00440      ht.ich = -1;
00441      if( fHitList.empty() ) return ht;
00442 
00443      ph = fHitList.begin();
00444      while( ph != fHitList.end() ) { 
00445         if( (*ph).amp > emax ) { emax = (*ph).amp; ht = *ph; }
00446         ph++;
00447      }
00448      return ht;
00449 }
00450 
00451 // ///////////////////////////////////////////////////////////////////////////
00452 
00453 void EmcCluster::GetHits(EmcModule* phit, int n)
00454 // Returns n EmcModules (sorted) with the maximum energy
00455 {
00456      int nhit;
00457      EmcModule *hlist, *vv;
00458      vector<EmcModule>::iterator ph;
00459      vector<EmcModule> hl;
00460 
00461      fOwner->ZeroVector(phit, n);
00462      nhit = fHitList.size();
00463 
00464      if( nhit <= 0 ) return;
00465 
00466      hlist = new EmcModule[nhit];
00467 
00468      ph = fHitList.begin();
00469      vv = hlist;
00470      while( ph != fHitList.end() ) *vv++ = *ph++;
00471 
00472      qsort( hlist, nhit, sizeof(EmcModule), fOwner->HitACompare );
00473      for( int i=0; i<min(nhit,n); i++ ) phit[i]=hlist[i];
00474      delete [] hlist;
00475 }
00476 
00477 // ///////////////////////////////////////////////////////////////////////////
00478 
00479 void EmcCluster::GetMoments( float* px, float* py, float* pxx, float* pxy, float* pyy )
00480 //  Returns cluster 1-st (px,py) and 2-d momenta (pxx,pxy,pyy)
00481 {
00482      vector<EmcModule>::iterator ph;
00483      float e, x, y, xx, yy, xy;
00484      int nhit;
00485      EmcModule *phit, *p;
00486 
00487      *px = fgXABSURD; *py = fgYABSURD;
00488      *pxx = 0; *pxy = 0; *pyy = 0;
00489      nhit=fHitList.size();
00490      if( nhit <= 0 ) return;
00491 
00492      phit = new EmcModule[nhit];
00493      ph = fHitList.begin();
00494      p=phit;
00495      while( ph != fHitList.end() ) { 
00496         p->ich = (*ph).ich;
00497         p->amp = (*ph).amp;
00498         ph++;
00499         p++;
00500      }
00501      fOwner->Momenta( nhit, phit, &e, &x, &y, &xx, &yy, &xy );
00502      *px = x*fOwner->GetModSizex();
00503      *py = y*fOwner->GetModSizey();
00504      *pxx = xx*fOwner->GetModSizex()*fOwner->GetModSizex();
00505      *pxy = xy*fOwner->GetModSizex()*fOwner->GetModSizey();
00506      *pyy = yy*fOwner->GetModSizey()*fOwner->GetModSizey();
00507      delete [] phit;
00508 }
00509 
00510 // ///////////////////////////////////////////////////////////////////////////
00511 
00512 void EmcCluster::GetErrors( float* pde, float* pdx, float* pdy, float* pdz)
00513 {
00514   //  Returns the errors for the reconstructed energy and position
00515 
00516     float e, x, y;
00517 
00518     e = GetTotalEnergy();
00519     GetCorrPos( &x, &y );
00520     fOwner->CalculateErrors( e, x, y, pde, pdx, pdy, pdz);
00521 
00522 }
00523 
00524 // ///////////////////////////////////////////////////////////////////////////
00525 
00526 void EmcCluster::GetChar( float* pe, 
00527                           float* pxcg, float* pycg, 
00528                           float* pxc, float* pyc, 
00529                           float* pxg, float* pyg, float* pzg,
00530                           float* pxx, float* pxy, float* pyy,
00531                           float* pde, float* pdx, float* pdy, float* pdz  )
00532 {
00533   // This method replaces methods GetTotalEnergy, GetMoments, 
00534   // GetCorrPos, GetGlobalPos, GetErrors
00535 
00536   *pe = GetTotalEnergy();
00537   GetMoments( pxcg, pycg, pxx, pxy, pyy );
00538   fOwner->CorrectPosition( *pe, *pxcg, *pycg, pxc, pyc );
00539   fOwner->SectorToGlobal( *pxc, *pyc, 0, pxg, pyg, pzg );
00540   fOwner->CalculateErrors( *pe, *pxc, *pyc, pde, pdx, pdy, pdz);
00541 
00542 }
00543 
00544 // ///////////////////////////////////////////////////////////////////////////
00545 
00546 int EmcCluster::GetPeaks( EmcPeakarea* PkList, EmcModule* ppeaks )
00547 {
00548   // Splits the cluster onto peakarea's
00549   // The number of peakarea's is equal to the number of Local Maxima 
00550   // in the cluster. Local Maxima can have the energy not less then 
00551   // defined in fgMinPeakEnergy
00552   //
00553   // Output: PkList - the array of peakarea's
00554   //         ppeaks - the array of peak EmcModules (one for each peakarea)
00555   //
00556   // Returns: >= 0 Number of Peaks;
00557   //          -1 The number of Peaks is greater then fgMaxNofPeaks;
00558   //             (just increase parameter fgMaxNofPeaks)
00559   
00560   int npk, ipk, nhit;
00561   int ixypk, ixpk, iypk, in, nh, ic;
00562   int ixy, ix, iy, nn;
00563   int ig, ng, igmpk1[fgMaxNofPeaks], igmpk2[fgMaxNofPeaks];
00564   int PeakCh[fgMaxNofPeaks];
00565   float epk[fgMaxNofPeaks*2], xpk[fgMaxNofPeaks*2], ypk[fgMaxNofPeaks*2];
00566   float ratio, eg, dx, dy, a, chi, chi0;
00567   float *Energy[fgMaxNofPeaks], *totEnergy, *tmpEnergy;
00568   EmcModule *ip;
00569   EmcModule *phit, *hlist, *vv;
00570   EmcPeakarea peak(fOwner);
00571   vector<EmcModule>::iterator ph;
00572   vector<EmcModule> hl;
00573   
00574   nhit = fHitList.size();
00575   
00576   if( nhit <= 0 ) return 0;
00577   
00578   hlist = new EmcModule[nhit];
00579   
00580   ph = fHitList.begin();
00581   vv = hlist;
00582   while( ph != fHitList.end() ) *vv++ = *ph++;
00583   
00584   // sort by linear channel number
00585   qsort( hlist, nhit, sizeof(EmcModule), fOwner->HitNCompare );
00586 
00587   //
00588   //  Find peak (maximum) position (towers with local maximum amp)
00589   //
00590   npk=0;
00591   for( ic=0; ic<nhit; ic++ ) {
00592     float amp = hlist[ic].amp;
00593     if( amp > fOwner->GetPeakThreshold() ) {
00594       int ich = hlist[ic].ich;
00595       int ichmax = ich + fOwner->GetNx() + 1;
00596       int ichmin = ich - fOwner->GetNx() - 1;
00597       int ixc = ich - ich/fOwner->GetNx()*fOwner->GetNx();
00598       int in = ic + 1;
00599       // check right, and 3 towers above if there is another max
00600       while( (in < nhit) && (hlist[in].ich <= ichmax) ) {
00601         int ix = hlist[in].ich - hlist[in].ich/fOwner->GetNx()*fOwner->GetNx();
00602         if( (abs(ixc-ix) <= 1) && (hlist[in].amp >= amp) ) goto new_ic;
00603         in++;
00604       }
00605       in = ic - 1;
00606       // check left, and 3 towers below if there is another max
00607       while( (in >= 0) && (hlist[in].ich >= ichmin) ) {
00608         int ix = hlist[in].ich - hlist[in].ich/fOwner->GetNx()*fOwner->GetNx();
00609         if( (abs(ixc-ix) <= 1) && (hlist[in].amp > amp) ) goto new_ic;
00610         in--;
00611       }
00612       if( npk >= fgMaxNofPeaks ) { delete [] hlist; return -1; }
00613 
00614       // ic is a maximum in a 3x3 tower group
00615       PeakCh[npk]=ic;
00616       npk++;
00617     }
00618   new_ic: continue;
00619   }
00620  
00621   // there was only one peak
00622   if( npk <= 1 ) {
00623     hl.erase( hl.begin(), hl.end() );
00624     for( int ich=0; ich<nhit; ich++ ) hl.push_back(hlist[ich]);
00625     peak.ReInitialize(hl);
00626     PkList[0]=peak;
00627 
00628     if( npk == 1 ) *ppeaks = hlist[PeakCh[0]];
00629     else  *ppeaks = GetMaxTower();
00630 
00631     delete [] hlist;
00632     return 1;
00633   }
00634  
00635   // there were more than one peak
00636 
00637   for( ipk=0; ipk<npk; ipk++ ) { Energy[ipk] = new float[nhit]; }
00638   totEnergy = new float[nhit];
00639   tmpEnergy = new float[nhit];
00640   for ( int i = 0; i < nhit; ++i ) 
00641     {
00642       totEnergy[i]=0.0;
00643       tmpEnergy[i]=0.0;
00644     }
00645   //
00646   // Divide energy in towers among photons positioned in every peak
00647   //
00648   ratio = 1.;
00649   for( int iter=0; iter<fgPeakIter; iter++ ) {
00650     fOwner->ZeroVector( tmpEnergy, nhit );
00651     for( ipk=0; ipk<npk; ipk++ ) {
00652       
00653       ic = PeakCh[ipk];
00654       if( iter > 0 ) ratio = Energy[ipk][ic]/totEnergy[ic];
00655       eg = hlist[ic].amp * ratio;
00656       ixypk = hlist[ic].ich;
00657       iypk = ixypk/fOwner->GetNx();
00658       ixpk = ixypk - iypk*fOwner->GetNx();
00659       epk[ipk] = eg;
00660       xpk[ipk] = eg * ixpk;     // center of energy in x
00661       ypk[ipk] = eg * iypk;     // center of energy in y
00662       
00663       // add up energies of tower to the right and 3 above
00664       if( ic < nhit-1 ){
00665         for( in=ic+1; in<nhit; in++ ) {
00666           ixy = hlist[in].ich;
00667           iy = ixy/fOwner->GetNx();
00668           ix = ixy - iy*fOwner->GetNx();
00669 
00670           if( (ixy-ixypk) > fOwner->GetNx()+1 ) break;
00671           if( abs(ix-ixpk) <= 1 ) {
00672             if( iter > 0 ) ratio = Energy[ipk][in]/totEnergy[in];
00673             eg = hlist[in].amp * ratio;
00674             epk[ipk] += eg;
00675             xpk[ipk] += eg*ix;
00676             ypk[ipk] += eg*iy;
00677           }
00678         }
00679       } // if ic
00680       
00681       // add up energies of tower to the left and 3 below
00682       if( ic >= 1 ){
00683         for( in=ic-1; in >= 0; in-- ) {
00684           ixy = hlist[in].ich;
00685           iy = ixy/fOwner->GetNx();
00686           ix = ixy - iy*fOwner->GetNx();
00687           if( (ixypk-ixy) > fOwner->GetNx()+1 ) break;
00688           if( abs(ix-ixpk) <= 1 ) {
00689             if( iter > 0 ) ratio = Energy[ipk][in]/totEnergy[in];
00690             eg = hlist[in].amp * ratio;
00691             epk[ipk] += eg;
00692             xpk[ipk] += eg*ix;
00693             ypk[ipk] += eg*iy;
00694           }
00695         }
00696       } // if ic
00697       
00698       xpk[ipk] = xpk[ipk]/epk[ipk];
00699       ypk[ipk] = ypk[ipk]/epk[ipk];
00700       fOwner->SetProfileParameters(0, epk[ipk], xpk[ipk], ypk[ipk]);
00701 
00702       for( in=0; in<nhit; in++ ) {
00703         ixy = hlist[in].ich;
00704         iy = ixy/fOwner->GetNx();
00705         ix = ixy - iy*fOwner->GetNx();
00706         dx = xpk[ipk]-ix;
00707         dy = ypk[ipk]-iy;
00708         a = 0;
00709         
00710         // predict energy within 2.5 cell square around local peak
00711         if( ABS(dx) < 2.5 && ABS(dy) < 2.5 )
00712           a = epk[ipk]*fOwner->PredictEnergy(dx, dy, -1);
00713         
00714         Energy[ipk][in] = a;
00715         tmpEnergy[in] += a;
00716       }
00717       
00718     } // for ipk
00719     float flim = 0.000001;
00720     for ( in = 0; in < nhit; in++ )
00721       {
00722         if (tmpEnergy[in] > flim)
00723           {
00724             totEnergy[in] = tmpEnergy[in];
00725           }
00726         else
00727           {
00728             totEnergy[in] = flim;
00729           }
00730       }
00731   } // for iter
00732   
00733   phit = new EmcModule[nhit];
00734   
00735   ng=0;
00736   for( ipk=0; ipk<npk; ipk++ ) {
00737     nh=0;
00738 
00739     // fill phit, the tower distribution for a peak
00740     for( in=0; in<nhit; in++ ) {
00741       if( tmpEnergy[in] > 0 ) {
00742         ixy = hlist[in].ich;
00743         a = hlist[in].amp * Energy[ipk][in]/tmpEnergy[in];
00744         if( a > fgEmin ) {
00745           phit[nh].ich=ixy;
00746           phit[nh].amp=a;
00747           phit[nh].tof= hlist[in].tof;  // Not necessary here
00748           phit[nh].deadmap= hlist[in].deadmap;  // Not necessary here
00749           phit[nh].warnmap= hlist[in].warnmap;  // MV 2002/02/18 bugfix
00750 
00751           // MV 2002/03/12 bugfix: let adc, tdc=0 for split clusters
00752           phit[nh].adc=0.; // MV 2002/03/12 bugfix
00753           phit[nh].tac=0.; // MV 2002/03/12 bugfix
00754 
00755           nh++;
00756         }
00757       }
00758     }
00759 
00760     // if number hits > 0
00761     if( nh>0 ) {
00762       chi=fOwner->Chi2Limit(nh)*10;
00763       int ndf; // just a plug for changed Gamma parameter list MV 28.01.00
00764 
00765       fOwner->Gamma(nh, phit,&chi, &chi0, &epk[ng], &xpk[ng], &ypk[ng],
00766                     &epk[ng+1], &xpk[ng+1], &ypk[ng+1], ndf);
00767 
00768       igmpk1[ipk]=ng;
00769       igmpk2[ipk]=ng;
00770       if( epk[ng+1]>0 ) { ng++; igmpk2[ipk]=ng;}
00771       ng++;
00772     }
00773     else {
00774       igmpk1[ipk]=-1;
00775       igmpk2[ipk]=-1;
00776     }
00777   }
00778   
00779   fOwner->ZeroVector( tmpEnergy, nhit );
00780   for( ipk=0; ipk<npk; ipk++ ) {
00781     ig=igmpk1[ipk];
00782     if( ig >= 0 ) {
00783       fOwner->SetProfileParameters(0, epk[ig], xpk[ig], ypk[ig]);
00784       for( in=0; in<nhit; in++ ) {
00785         Energy[ipk][in]=0;
00786         for(ig=igmpk1[ipk]; ig<=igmpk2[ipk]; ig++){
00787           ixy = hlist[in].ich;
00788           iy = ixy/fOwner->GetNx();
00789           ix = ixy - iy*fOwner->GetNx();
00790           dx = xpk[ig]-ix;
00791           dy = ypk[ig]-iy;
00792           a = epk[ig]*fOwner->PredictEnergy(dx, dy, epk[ig]);
00793           Energy[ipk][in] += a;
00794           tmpEnergy[in] += a;
00795         }
00796       } // for( in
00797     } // if( ig >= 0
00798   } // for( ipk
00799   
00800   ip = ppeaks;
00801   nn=0;
00802   for( ipk=0; ipk<npk; ipk++ ) {
00803     nh=0;
00804     for( in=0; in<nhit; in++ ) {
00805       if( tmpEnergy[in] > 0 ) {
00806         ixy = hlist[in].ich;
00807         a = hlist[in].amp * Energy[ipk][in]/tmpEnergy[in];
00808         if( a > fgEmin ) {
00809           phit[nh].ich=ixy;
00810           phit[nh].amp=a;
00811           phit[nh].tof=hlist[in].tof;
00812           phit[nh].deadmap=hlist[in].deadmap;
00813           phit[nh].warnmap=hlist[in].warnmap; // MV 2002/02/18 bugfix
00814 
00815           // MV 2002/03/12 bugfix: let adc, tdc=0 for split clusters
00816           phit[nh].adc=0.; // MV 2002/03/12 bugfix
00817           phit[nh].tac=0.; // MV 2002/03/12 bugfix
00818 
00819           nh++;
00820         }
00821       }
00822     }
00823     if( nh>0 ) {
00824       *ip++ = hlist[PeakCh[ipk]];
00825       hl.erase( hl.begin(), hl.end() );
00826       for( in=0; in<nh; in++ ) hl.push_back(phit[in]);
00827       peak.ReInitialize(hl);
00828       PkList[nn++]=peak;
00829     }
00830   }
00831   
00832   delete [] phit;
00833   delete [] hlist;
00834   for( ipk=0; ipk<npk; ipk++ ) delete [] Energy[ipk];
00835   delete [] totEnergy;
00836   delete [] tmpEnergy;
00837 
00838   return nn;
00839 }
00840 
00841 // ///////////////////////////////////////////////////////////////////////////
00842 // EmcPeakarea member functions
00843 
00844 void EmcPeakarea::GetChar( float* pe, float* pec, 
00845                            float* pecore, float* pecorec, 
00846                            float* pxcg, float* pycg,            // center of gravity
00847                            float* pxcgmin, float* pycgmin,      // 
00848                            float* pxc, float* pyc,              // Local (Sector) coords
00849                            float* pxg, float* pyg, float* pzg,  // Global coords
00850                            float* pxx, float* pxy, float* pyy,  // moments
00851                            float* pchi,
00852                            float* pde, float* pdx, float* pdy, float* pdz  )
00853 // This method replaces "cluster" methods GetTotalEnergy, GetMoments,
00854 // GetCorrPos, GetGlobalPos, GetErrors and "EmcPeakarea" methods GetCGmin, GetChi2
00855 {
00856     float chi, chi0;
00857     float e1, x1, y1, e2, x2, y2;
00858     int nh;
00859     EmcModule *phit, *vv;
00860     vector<EmcModule>::iterator ph;
00861     vector<EmcModule> hl;
00862     float tmplvalue; // temporary lvalue
00863 
00864     *pe = 0;
00865     hl = fHitList;
00866     nh = hl.size();
00867     if( nh <= 0 ) return;
00868 
00869     phit = new EmcModule[nh];
00870 
00871     ph = hl.begin();
00872     vv = phit;
00873     while( ph != hl.end() ) *vv++ = *ph++;
00874 
00875     chi = fgChisq*1000;
00876     int ndf; // Gamma parameter list changed MV 28.01.00
00877     fOwner->Gamma(nh, phit, &chi, &chi0, &e1, &x1, &y1, &e2, &x2, &y2, ndf);
00878     fNdf=ndf;
00879     *pchi=chi0;
00880 
00881     // Calculate CL
00882     tmplvalue=fOwner->Chi2Correct(chi0, ndf)*ndf; // nh->ndf MV 28.01.00
00883     if(tmplvalue>0.) fCL=TMath::Prob(tmplvalue, ndf);
00884     else fCL=1.; // nothing to say about this peak area
00885 
00886     // Shower Center of Gravity after shower profile fit
00887     *pxcgmin = x1*fOwner->GetModSizex();
00888     *pycgmin = y1*fOwner->GetModSizey();
00889 
00890     *pe = GetTotalEnergy();
00891     *pecore = GetECore();
00892     GetMoments( pxcg, pycg, pxx, pxy, pyy );
00893     fOwner->CorrectPosition(*pe, *pxcgmin, *pycgmin, pxc, pyc);
00894     fOwner->SectorToGlobal( *pxc, *pyc, 0, pxg, pyg, pzg );
00895     fOwner->CalculateErrors( *pe, *pxc, *pyc, pde, pdx, pdy, pdz);
00896     fOwner->CorrectEnergy( *pe, *pxcg, *pycg, pec ); // MM 02.11.2000
00897     fOwner->CorrectECore( *pecore, *pxc, *pyc, pecorec );
00898 
00899     delete [] phit;
00900 
00901 }
00902 
00903 // ///////////////////////////////////////////////////////////////////////////
00904 
00905 float EmcPeakarea::GetChi2()
00906 // Returns Hi2 after its minimization fluctuating CG position 
00907 // (i.e. after shower profile fit)
00908 {
00909     float chi, chi0, chicorr;
00910     float e1, x1, y1, e2, x2, y2;
00911     int nh;
00912     EmcModule *phit, *vv;
00913     vector<EmcModule>::iterator ph;
00914     vector<EmcModule> hl;
00915 
00916     hl = fHitList;
00917     nh = hl.size();
00918     if( nh <= 0 ) return 0;
00919 
00920     phit = new EmcModule[nh];
00921 
00922     ph = hl.begin();
00923     vv = phit;
00924     while( ph != hl.end() ) *vv++ = *ph++;
00925 
00926     chi = fgChisq*1000;
00927     int ndf; // Gamma parameter list changed MV 28.01.00
00928     fOwner->Gamma(nh, phit, &chi, &chi0, &e1, &x1, &y1, &e2, &x2, &y2, ndf);
00929     fNdf=ndf;
00930     chicorr = fOwner->Chi2Correct(chi0, ndf); // nh->ndf MV 28.01.00
00931 
00932     delete [] phit;
00933     return chi0;
00934 }
00935 
00936 // ///////////////////////////////////////////////////////////////////////////
00937 
00938 float EmcPeakarea::GetCLNew()
00939 // Conf. Level based on new chi2 calculation
00940 {
00941     float xcg, ycg, xx, xy, yy;
00942     float e1, e2, e3, e4;
00943     float e1m, e2m, e3m, e4m;
00944     float e1p, e2p, e3p, e4p;
00945     float s1, s2, s3, s4;
00946     float dx, dy, dt, et, etot, sc;
00947     float chi2, pr;
00948     int ix0, iy0, isx, isy, ndf;
00949 
00950     etot = GetTotalEnergy();
00951     GetMoments( &xcg, &ycg, &xx, &xy, &yy );
00952     xcg /= fOwner->GetModSizex();
00953     ycg /= fOwner->GetModSizey();
00954     ix0 = int(xcg+0.5);
00955     iy0 = int(ycg+0.5);
00956     dx = ABS(xcg-ix0);
00957     dy = ABS(ycg-iy0);
00958 
00959     isx = 1;
00960     if( xcg-ix0 < 0 ) isx = -1;
00961     isy = 1;
00962     if( ycg-iy0 < 0 ) isy = -1;
00963 
00964     e1 = GetTowerEnergy(ix0,     iy0    );
00965     e2 = GetTowerEnergy(ix0+isx, iy0    );
00966     e3 = GetTowerEnergy(ix0+isx, iy0+isy);
00967     e4 = GetTowerEnergy(ix0    , iy0+isy);
00968 
00969     if( dy > dx ) {
00970       et = e2;
00971       e2 = e4;
00972       e4 = et;
00973       dt = dx;
00974       dx = dy;
00975       dy = dt;
00976     }
00977 
00978     e1m = e1 + e2 + e3 + e4;
00979     e2m = e1 + e2 - e3 - e4;
00980     e3m = e1 - e2 - e3 + e4;
00981     e4m = e4 - e3;
00982 
00983     e1p = 0.932;
00984     e2p = 0.835 - 2*dy*dy/(dy+0.099);
00985     e3p = 0.835 - 2*dx*dx/(dx+0.099);
00986     e4p = 0.02;
00987 
00988     sc = sqrt(0.1*0.1/etot + 0.03*0.03)/0.04;
00989     s1 = sc*0.02;
00990     sc = sqrt(0.1*0.1/etot + 0.02*0.02)/0.04;
00991     s2 = sc*(0.056-0.026*e2p);
00992     s3 = sc*(0.056-0.026*e2p);
00993     s4 = sc*0.03;
00994 
00995     chi2 = 0.;
00996     chi2 += (e1p*etot-e1m)*(e1p*etot-e1m)/s1/s1/etot/etot;
00997     chi2 += (e2p*etot-e2m)*(e2p*etot-e2m)/s2/s2/etot/etot;
00998     chi2 += (e3p*etot-e3m)*(e3p*etot-e3m)/s3/s3/etot/etot;
00999     chi2 += (e4p*etot-e4m)*(e4p*etot-e4m)/s4/s4/etot/etot;
01000     chi2 /= 0.7;
01001 
01002     ndf = 4;
01003     pr = TMath::Prob(chi2, ndf);
01004     return pr;
01005 }
01006 
01007 // ///////////////////////////////////////////////////////////////////////////
01008 
01009 float EmcPeakarea::GetChi2New()
01010 // Conf. Level based on new chi2 calculation
01011 {
01012     float xcg, ycg, xx, xy, yy;
01013     float e1, e2, e3, e4;
01014     float e1m, e2m, e3m, e4m;
01015     float e1p, e2p, e3p, e4p;
01016     float s1, s2, s3, s4;
01017     float dx, dy, dt, et, etot, sc;
01018     float chi2;
01019     int ix0, iy0, isx, isy, ndf;
01020 
01021     etot = GetTotalEnergy();
01022     GetMoments( &xcg, &ycg, &xx, &xy, &yy );
01023     xcg /= fOwner->GetModSizex();
01024     ycg /= fOwner->GetModSizey();
01025     ix0 = int(xcg+0.5);
01026     iy0 = int(ycg+0.5);
01027     dx = ABS(xcg-ix0);
01028     dy = ABS(ycg-iy0);
01029 
01030     isx = 1;
01031     if( xcg-ix0 < 0 ) isx = -1;
01032     isy = 1;
01033     if( ycg-iy0 < 0 ) isy = -1;
01034 
01035     e1 = GetTowerEnergy(ix0,     iy0    );
01036     e2 = GetTowerEnergy(ix0+isx, iy0    );
01037     e3 = GetTowerEnergy(ix0+isx, iy0+isy);
01038     e4 = GetTowerEnergy(ix0    , iy0+isy);
01039 
01040     if( dy > dx ) {
01041       et = e2;
01042       e2 = e4;
01043       e4 = et;
01044       dt = dx;
01045       dx = dy;
01046       dy = dt;
01047     }
01048 
01049     e1m = e1 + e2 + e3 + e4;
01050     e2m = e1 + e2 - e3 - e4;
01051     e3m = e1 - e2 - e3 + e4;
01052     e4m = e4 - e3;
01053 
01054     e1p = 0.932;
01055     e2p = 0.835 - 2*dy*dy/(dy+0.099);
01056     e3p = 0.835 - 2*dx*dx/(dx+0.099);
01057     e4p = 0.02;
01058 
01059     sc = sqrt(0.1*0.1/etot + 0.03*0.03)/0.04;
01060     s1 = sc*0.02;
01061     sc = sqrt(0.1*0.1/etot + 0.02*0.02)/0.04;
01062     s2 = sc*(0.056-0.026*e2p);
01063     s3 = sc*(0.056-0.026*e2p);
01064     s4 = sc*0.03;
01065 
01066     chi2 = 0.;
01067     chi2 += (e1p*etot-e1m)*(e1p*etot-e1m)/s1/s1/etot/etot;
01068     chi2 += (e2p*etot-e2m)*(e2p*etot-e2m)/s2/s2/etot/etot;
01069     chi2 += (e3p*etot-e3m)*(e3p*etot-e3m)/s3/s3/etot/etot;
01070     chi2 += (e4p*etot-e4m)*(e4p*etot-e4m)/s4/s4/etot/etot;
01071     chi2 /= 0.7;
01072 
01073     ndf = 4;
01074     return chi2/ndf;
01075 }
01076 
01077 // ///////////////////////////////////////////////////////////////////////////
01078 
01079 void EmcPeakarea::GetCGmin( float* px, float* py )
01080 {
01081   // Gets CG coordinates corresponding to min Hi2 (after shower shape fit)
01082 
01083   float chi, chi0;
01084   float e1, x1, y1, e2, x2, y2;
01085   int nh;
01086   EmcModule *phit, *vv;
01087   vector<EmcModule>::iterator ph;
01088   vector<EmcModule> hl;
01089   
01090   *px = fgXABSURD;
01091   *py = fgYABSURD;
01092   hl = fHitList;
01093   nh = hl.size();
01094   if( nh <= 0 ) return;
01095   
01096   phit = new EmcModule[nh];
01097   
01098   ph = hl.begin();
01099   vv = phit;
01100   while( ph != hl.end() ) *vv++ = *ph++;
01101   
01102   chi = fgChisq*1000;
01103   int ndf; // Gamma parameter list changed MV 28.01.00
01104   fOwner->Gamma(nh, phit, &chi, &chi0, &e1, &x1, &y1, &e2, &x2, &y2, ndf);
01105   fNdf=ndf;
01106   *px = x1*fOwner->GetModSizex();
01107   *py = y1*fOwner->GetModSizey();
01108   
01109   delete [] phit;
01110 
01111 }
01112 
01113 // ///////////////////////////////////////////////////////////////////////////
01114 
01115 int EmcPeakarea::GetGammas( EmcEmshower* ShList)
01116 {
01117   // Splits the peakarea onto 1 or 2 EmcEmshower's
01118   // Returns Number of Showers (0, 1 or 2)
01119   //
01120   // If the Chi2 of the peakarea is less then the value determined 
01121   // in Chi2Limit(Number_of_Hits) function, 1-photon hypothesis is 
01122   // accepted, otherwise the 2-shower hypothesis is checked
01123   
01124   float chi, chi0, e1, x1, y1, e2, x2, y2, chicorr;
01125   int nh, ig;
01126   EmcModule *phit, *vv;
01127   EmcEmshower sh1(fOwner), sh2(fOwner);
01128   vector<EmcModule>::iterator ph;
01129   vector<EmcModule> hl;
01130   
01131   hl = fHitList;
01132   nh = hl.size();
01133   if( nh <= 0 ) return 0;
01134   
01135   phit = new EmcModule[nh];
01136   
01137   ph = hl.begin();
01138   vv = phit;
01139   while( ph != hl.end() ) *vv++ = *ph++;
01140   
01141   chi=fOwner->Chi2Limit(nh); // potential problem for PbGl -- ndf is not known
01142                              // beforehand
01143   int ndf; // Gamma parameter list changed MV 28.01.00
01144   fOwner->Gamma(nh, phit, &chi, &chi0, &e1, &x1, &y1, &e2, &x2, &y2, ndf);
01145   chicorr = fOwner->Chi2Correct(chi, ndf); // nh->ndf MV 28.01.00
01146   if(e1>0)
01147     sh1.ReInitialize(e1, x1*fOwner->GetModSizex(), y1*fOwner->GetModSizey(),
01148                      chi, ndf);
01149   else
01150     sh1.ReInitialize(0, fgXABSURD, fgYABSURD, 0, 0);
01151   
01152   if( e2 > 0 )
01153     sh2.ReInitialize(e2, x2*fOwner->GetModSizex(), y2*fOwner->GetModSizey(),
01154                      chi, ndf);
01155   else
01156     sh2.ReInitialize(0, fgXABSURD, fgYABSURD, 0, ndf);
01157   
01158   if( e2 > e1 ) {
01159     sh1.ReInitialize(e2, x2*fOwner->GetModSizex(), y2*fOwner->GetModSizey(),
01160                      chi, ndf);
01161     sh2.ReInitialize(e1, x1*fOwner->GetModSizex(), y1*fOwner->GetModSizey(),
01162                      chi, ndf);
01163   }
01164   
01165   ig = 0;
01166   if( e1>0 ) {
01167     ShList[ig++]=sh1;
01168     if( e2>0 ) {
01169       ShList[ig++]=sh2;
01170     }
01171   }
01172   
01173   delete [] phit;
01174   return ig;
01175 }
01176 
01177 // ///////////////////////////////////////////////////////////////////////////
01178 // EmcEmshower member functions
01179 
01180 EmcEmshower::EmcEmshower():
01181   fNdf(0), 
01182   fCL(1.),  
01183   fEnergy(0.),
01184   fXcg(0.),
01185   fYcg(0.),
01186   fChisq(999.999)
01187 {}
01188 
01189 // ///////////////////////////////////////////////////////////////////////////
01190 
01191 EmcEmshower::EmcEmshower(EmcSectorRec *sector):
01192   fOwner(sector),  
01193   fNdf(0), 
01194   fCL(1.),  
01195   fEnergy(0.),
01196   fXcg(0.),
01197   fYcg(0.),
01198   fChisq(999.999)
01199 {}
01200 
01201 // ///////////////////////////////////////////////////////////////////////////
01202 
01203 EmcEmshower::EmcEmshower(float e, float x, float y, float chi, int ndf,
01204                          EmcSectorRec *sector):
01205   fOwner(sector),  
01206   fNdf(ndf), 
01207   fCL(1.),  // This should be calculated !!!
01208   fEnergy(e),
01209   fXcg(x),
01210   fYcg(y),
01211   fChisq(chi)
01212 {}
01213 
01214 // ///////////////////////////////////////////////////////////////////////////
01215 
01216 void EmcEmshower::GetCorrPos( float* px, float* py )
01217 // Returns EmcEmshower corrected position in Sector (SM) frame
01218 {
01219    fOwner->CorrectPosition(fEnergy, fXcg, fYcg, px, py );
01220 }
01221 
01222 // ///////////////////////////////////////////////////////////////////////////
01223 
01224 void EmcEmshower::GetGlobalPos( float* px, float* py, float* pz )
01225 // Returns EmcEmshower position in PHENIX global coord system
01226 {
01227    float xc, yc;
01228 
01229    GetCorrPos( &xc, &yc );
01230 // X in Sector coord is Z in Global coord !!
01231    fOwner->SectorToGlobal( xc, yc, 0, px, py, pz );
01232 }
01233 
01234 // ///////////////////////////////////////////////////////////////////////////
01235 
01236 void EmcEmshower::GetErrors( float* pde, float* pdx, float* pdy, float* pdz)
01237 // Returns the errors for the reconstructed energy and position
01238 {
01239     float e, x, y;
01240 
01241     e = GetTotalEnergy();
01242     GetCorrPos( &x, &y );
01243     fOwner->CalculateErrors( e, x, y, pde, pdx, pdy, pdz);
01244 }
01245 
01246 // ///////////////////////////////////////////////////////////////////////////
01247 
01248 void EmcEmshower::GetChar( float* pe, 
01249                            float* pxcg, float* pycg, 
01250                            float* pxc, float* pyc, 
01251                            float* pxg, float* pyg, float* pzg, 
01252                            float* pchi,
01253                            float* pde, float* pdx, float* pdy, float* pdz  )
01254 {
01255   // This method replaces methods GetTotalEnergy, GetCG, 
01256   // GetCorrPos, GetGlobalPos, GetChi2, GetErrors
01257   
01258   float tmplvalue; // temporary lvalue
01259 
01260   *pe = GetTotalEnergy();
01261   GetCG( pxcg, pycg );
01262   fOwner->CorrectPosition( *pe, *pxcg, *pycg, pxc, pyc );
01263   fOwner->SectorToGlobal( *pxc, *pyc, 0, pxg, pyg, pzg );
01264   fOwner->CalculateErrors( *pe, *pxc, *pyc, pde, pdx, pdy, pdz);
01265   *pchi=fChisq;
01266   
01267   // Calculate CL
01268   tmplvalue=fOwner->Chi2Correct(fChisq, fNdf)*fNdf; // nh->ndf MV 28.01.00
01269   if(tmplvalue>0.) fCL=TMath::Prob(tmplvalue, fNdf);
01270   else fCL=1.; // nothing to say about this peak area
01271 
01272 }
01273 
01274 // ///////////////////////////////////////////////////////////////////////////
01275 // EOF