EmcSectorRec.cxx

Go to the documentation of this file.
00001 // Name: EmcSectorRec.cxx
00002 // Author: A. Bazilevsky (RIKEN-BNL)
00003 // Major modifications by M. Volkov (RRC KI) Jan 27 2000
00004 
00005 // EmcSectorRec -- abstract base class for both PbSc and PbGl
00006 
00007 // ///////////////////////////////////////////////////////////////////////////
00008 
00009 /* This package consists of the following files:
00010 
00011        EmcCluster.cxx (clusters, peakareas, modules etc.)
00012        EmcCluster.h
00013        EmcGlSectorRec.cxx (PbGl specific code)
00014        EmcGlSectorRec.h
00015        EmcScSectorRec.cxx (PbSc specific code)
00016        EmcScSectorRec.h
00017        EmcSectorRec.cxx (generic interface to calorimeter reconstruction)
00018        EmcSectorRec.h
00019 
00020 For the original description of the algorithm by A. Bazilevsky see
00021 EmcCluster.cxx.
00022        The package can be used independently of anything else. Here is an
00023 example application code (<...> means "do your stuff here").
00024 
00025 // Beginning of example
00026 // Local includes
00027 #include "EmcGlSectorRec.h"
00028 
00029 int main(int argc, char **argv)
00030 {
00031 
00032 <...>
00033 
00034   float vertex[3]; // assume that the vertex changes from event to event
00035 
00036   SecGeom SectorGeometry; // geometry doesn't change
00037   SectorGeometry.nx=17;
00038   SectorGeometry.ny=17;
00039   SectorGeometry.Tower_xSize=4.1; // cm
00040   SectorGeometry.Tower_ySize=4.1; // cm
00041   SectorGeometry.xyz0[0]=0.;
00042   SectorGeometry.xyz0[1]=-(SectorGeometry.ny/2-((SectorGeometry.ny+1)%2)*0.5)*
00043     SectorGeometry.Tower_ySize;
00044   SectorGeometry.xyz0[2]=-(SectorGeometry.nx/2-((SectorGeometry.nx+1)%2)*0.5)*
00045     SectorGeometry.Tower_xSize;
00046   SectorGeometry.nxyz[0]=1.;
00047   SectorGeometry.nxyz[1]=0.;
00048   SectorGeometry.nxyz[2]=0.;
00049 
00050 <...>
00051 
00052   EmcPeakarea pPList[MaxNofPeaks];
00053   EmcModule peaks[MaxNofPeaks];
00054   EmcEmshower pShList[2];
00055   
00056   list<EmcModule> *moduleList=new list<EmcModule>();
00057   list<EmcCluster> *clusterList;
00058   list<EmcCluster>::iterator pc;
00059   EmcPeakarea* pp;
00060   EmcEmshower* ps;
00061 
00062   float e, xcg, ycg, xcgm, ycgm, xc, yc, xgl, ygl, zgl,
00063     xx, xy, yy, chi2, de, dx, dy, dz;
00064   
00065   
00066   // Create sector here. It can be either EmcGlSectorRec (PbGl) or
00067   // EmcScSectorRec (PbSc).
00068   EmcSectorRec *sector=new EmcGlSectorRec();
00069   
00070   // Sets threshold in each tower (GeV)
00071   sector->SetThreshold(0.02);
00072 
00073   //====================> Event loop <====================
00074 
00075   int nanal=atoi(argv[2]);
00076   for (int evtCount=0; evtCount<nanal; evtCount++){
00077 
00078 <... Get event here ...>
00079 
00080     sector->SetGeometry(SectorGeometry, vertex);
00081 
00082 <... Fill the list of fired modules here ...>
00083 
00084     sector->SetModules(moduleList);
00085     int ncl=sector->FindClusters();
00086     clusterList=sector->GetClusters();
00087 
00088 <...>
00089 
00090     // Loop over clusters
00091     for(pc=clusterList->begin(); pc!=clusterList->end(); pc++){
00092 
00093 <...>
00094 
00095       e = pc->GetTotalEnergy();
00096       nh = pc->GetNofHits();
00097 
00098 <...>
00099 
00100       // Get PeakAreas - 2-st Clustering Level
00101       npk=pc->GetPeaks(pPList, peaks);
00102       pp=pPList;
00103 
00104       // Loop over peak areas
00105       for(int ipk=0; ipk<npk; ipk++){
00106 
00107         // Get peak area parameters
00108         pp->GetChar(&e, &xcg, &ycg, &xcgm, &ycgm, &xc, &yc, &xgl, &ygl, &zgl,
00109                     &xx, &xy, &yy, &chi2, &de, &dx, &dy, &dz);
00110 
00111 <...>
00112 
00113         // Gets EMShower - 3-d Clustering Level
00114         nsh=pp->GetGammas(pShList);
00115         ps=pShList;
00116         
00117         for(int ish=0; ish<nsh; ish++){ // Loop over EMShowers (can be 1 or 2)
00118           
00119           e=ps->GetTotalEnergy();
00120           chi2=ps->GetChi2();
00121           ps++;
00122           
00123         } // Loop over EMShowers
00124 
00125         pp++; // to next peakarea
00126         
00127       } // Loop over peak areas
00128     } // Loop over clusters
00129   } // Event loop
00130 
00131   //=========> End of event loop <==========
00132 
00133   // Clean up
00134   if(moduleList){
00135 
00136     delete moduleList;
00137     moduleList=NULL;
00138 
00139   }
00140 
00141   if(sector){
00142 
00143     delete sector;
00144     sector=NULL;
00145 
00146   }
00147 
00148   return(0);
00149   
00150 }
00151 // End of example
00152 
00153 MV March 6 2000.
00154 */
00155 
00156 // ///////////////////////////////////////////////////////////////////////////
00157 
00158 #include "EmcSectorRec.h"
00159 #include "EmcCluster.h"
00160 
00161 //INCLUDECHECKER: Removed this line: #include "PHFrame.h"
00162 #include "PHGeometry.h"
00163 
00164 using namespace std;
00165 
00166 // Define and initialize static members
00167 
00168 // Minimal shower energy when splitting peakarea onto showers, used in Gamma()
00169 float const EmcSectorRec::fgMinShowerEnergy=0.1;
00170 
00171 // Max number of clusters in sector, used in Find_Clusters()
00172 int const EmcSectorRec::fgMaxLen=1000;
00173 
00174 // Default level, now for the Conf Level: 1% for GEANT, 2%-5% for TestBeam
00175 
00176 float EmcSectorRec::fgChi2Level[50]={
00177     6.634899, 4.605171, 3.780564, 3.318915, 3.017103,    
00178     2.801872, 2.639259, 2.511249, 2.407341, 2.320967,    
00179     2.247720, 2.184744, 2.129863, 2.081515, 2.038526,    
00180     1.999994, 1.965214, 1.933627, 1.904781, 1.878311,    
00181     1.853912, 1.831334, 1.810365, 1.790825, 1.772564, 
00182     1.755449, 1.739367, 1.724222, 1.709926, 1.696406,    
00183     1.683593, 1.671430, 1.659864, 1.648850, 1.638344,    
00184     1.628311, 1.618716, 1.609528, 1.600721, 1.592268,    
00185     1.584148, 1.576338, 1.568822, 1.561579, 1.554596,    
00186     1.547856, 1.541346, 1.535055, 1.528968, 1.523077 };   
00187 
00188 // For the Conf Level: 1% for GEANT, 2%-5% for TestBeam
00189 float EmcSectorRec::fgChi2Level1[50]={
00190     6.634899, 4.605171, 3.780564, 3.318915, 3.017103,    
00191     2.801872, 2.639259, 2.511249, 2.407341, 2.320967,    
00192     2.247720, 2.184744, 2.129863, 2.081515, 2.038526,    
00193     1.999994, 1.965214, 1.933627, 1.904781, 1.878311,    
00194     1.853912, 1.831334, 1.810365, 1.790825, 1.772564, 
00195     1.755449, 1.739367, 1.724222, 1.709926, 1.696406,    
00196     1.683593, 1.671430, 1.659864, 1.648850, 1.638344,    
00197     1.628311, 1.618716, 1.609528, 1.600721, 1.592268,    
00198     1.584148, 1.576338, 1.568822, 1.561579, 1.554596,    
00199     1.547856, 1.541346, 1.535055, 1.528968, 1.523077 };   
00200 
00201 // For the Conf Level: 2% for GEANT, 4%-7% for TestBeam
00202 float EmcSectorRec::fgChi2Level2[50]={
00203     5.411895, 3.912024, 3.278443, 2.916812, 2.677547,    
00204     2.505458, 2.374582, 2.271008, 2.186567, 2.116065,    
00205     2.056169, 2.004491, 1.959343, 1.919481, 1.883964,    
00206     1.852072, 1.823237, 1.797008, 1.773021, 1.750981,    
00207     1.730640, 1.711795, 1.694274, 1.677931, 1.662643,    
00208     1.648301, 1.634814, 1.622101, 1.610093, 1.598727,    
00209     1.587948, 1.577709, 1.567968, 1.558684, 1.549824,    
00210     1.541357, 1.533256, 1.525494, 1.518051, 1.510903,    
00211     1.504033, 1.497424, 1.491059, 1.484924, 1.479006,    
00212     1.473292, 1.467771, 1.462433, 1.457267, 1.452265 };
00213 
00214 // ///////////////////////////////////////////////////////////////////////////
00215 // EmcSectorRec member functions
00216 
00217 EmcSectorRec::EmcSectorRec()
00218 {
00219   fModules=new vector<EmcModule>;
00220   fClusters=new vector<EmcCluster>;
00221   SetPeakThreshold(0.08);
00222   SetChi2Limit(2);
00223 }
00224 
00225 // ///////////////////////////////////////////////////////////////////////////
00226 
00227 EmcSectorRec::~EmcSectorRec()
00228 {
00229 
00230   if(fModules){
00231 
00232     fModules->clear();
00233     delete fModules;
00234 
00235   }
00236 
00237   if(fClusters){
00238 
00239     fClusters->clear();
00240     delete fClusters;
00241 
00242   }
00243 }
00244 
00245 // ///////////////////////////////////////////////////////////////////////////
00246 
00247 void  EmcSectorRec::SetGeometry(SecGeom const &geom, PHMatrix * rm, PHVector * tr )
00248 {
00249   // Sets the sector geometry.
00250   // Should be called before Find_Clusters(...)
00251   // Note: static data members are initialized => has to be called after
00252   // a new EmcSectorRec has been created.
00253 
00254   emcrm = *rm; 
00255   emctr = *tr; 
00256   PHFrame local;
00257   PHFrame global=PHGeometry::MatrixAndVector2frames(local,emcrm,emctr);
00258   PHGeometry::frames2MatrixAndVector(global,local,invemcrm,invemctr);
00259 
00260   // The number of towers in X and Y dir.
00261   fNx = geom.nx;
00262   fNy = geom.ny;
00263 
00264   // Tower size in X and Y dir.
00265   fModSizex = geom.Tower_xSize;
00266   fModSizey = geom.Tower_ySize;
00267 
00268 }
00269 
00270 // ///////////////////////////////////////////////////////////////////////////
00271 
00272 void EmcSectorRec::SetModules(vector<EmcModule> const *modules)
00273 {
00274 
00275   *fModules=*modules;
00276 
00277 #if 0
00278   // Make sure that each hit(fired module) knows what sector it belogs to
00279   vector<EmcModule>::iterator listIter;
00280   for(listIter=fModules->begin(); listIter!=fModules->end(); listIter++)
00281     listIter->fOwner=this;
00282 #endif // #if 0
00283 
00284 }
00285 
00286 // ///////////////////////////////////////////////////////////////////////////
00287 
00288 int EmcSectorRec::FindClusters()
00289 {
00290   // Cluster search algorithm based on Lednev's one developed for GAMS.
00291   // Returns -1 if fgMaxLen parameter is too small (just increase it)
00292   
00293   int nhit, nCl;
00294   int LenCl[fgMaxLen];
00295   int next, ib, ie, iab, iae, last, LastCl, leng, ich;
00296   int ia = 0;
00297   
00298   EmcModule *vv;
00299   EmcModule *vhit, *vt;
00300   EmcCluster Clt(this);
00301   vector<EmcModule>::iterator ph;
00302   vector<EmcModule> hl;
00303   
00304   (*fClusters).erase(  (*fClusters).begin(),  (*fClusters).end() );
00305   nhit = (*fModules).size();
00306   
00307   if( nhit <= 0 ) return 0;
00308   if( nhit == 1 ) {
00309     Clt.ReInitialize( (*fModules) );
00310     fClusters->push_back(Clt);
00311     return 1;
00312   }
00313 
00314   vt = new EmcModule[nhit];
00315   vhit = new EmcModule[nhit];
00316   
00317   ph = (*fModules).begin();
00318   vv = vhit;
00319   while( ph != (*fModules).end() ) *vv++ = *ph++;
00320   
00321   qsort( vhit, nhit, sizeof(EmcModule), HitNCompare );
00322   
00323   nCl=0;
00324   next = 0;
00325   for( ich=1; ich<nhit+1; ich++ ){
00326     if( ich<nhit ) ia=vhit[ich].ich;
00327     // Protect against gluing together edges of the different rows
00328 
00329     if( (ia-vhit[ich-1].ich > 1) || (ich >= nhit)
00330         ||(ia-ia/fNx*fNx == 0) ){
00331       ib=next;
00332       ie=ich-1;
00333       next=ich;
00334       if( nCl >= fgMaxLen ) {
00335         return -1;
00336       }
00337       nCl++;
00338       LenCl[nCl-1]=next-ib;
00339       if( nCl > 1 ) {
00340         // Job to glue the subclusters
00341         iab=vhit[ib].ich;       // The last subcl begin
00342         iae=vhit[ie].ich;       // The last subcl end
00343         last=ib-1;              // The prelast subcl end
00344         LastCl=nCl-2;
00345         for( int iCl=LastCl; iCl>=0; iCl-- ){
00346           leng=LenCl[iCl];
00347 
00348 #ifdef GLUE_CLUSTER_CORNER
00349           //*********** Begin: glue clusters with adjacent corner **********
00350           //
00351                   if( (iab-vhit[last].ich > fNx+1) || 
00352           //          // This is if iab-channel is on the left edge
00353                       ( (iab-vhit[last].ich == fNx+1) &&
00354                         (iab-iab/fNx*fNx == 0) ) ) goto new_ich;
00355                   for( int ichc=last; ichc >= last-leng+1; ichc-- ) {
00356           //
00357                     if( (iab-vhit[ichc].ich >  fNx+1) ||  
00358           //            // This is if iab-channel is on the left edge
00359                         ( (iab-vhit[ichc].ich == fNx+1) &&
00360                           (iab-iab/fNx*fNx == 0) ) ) goto new_icl;
00361           //
00362                     if( (iae-vhit[ichc].ich >= fNx-1) && 
00363           //            // This is if iae-channel is not on the right edge
00364                         ( (iae-vhit[ichc].ich != fNx-1) || 
00365                           ((iae+1)-(iae+1)/fNx*fNx != 0) ) ) {
00366           //*********** End: glue clusters with adjacent corner **********
00367 #else
00368           //*********** Begin: glue clusters with adjacent edge **********
00369           if( iab-vhit[last].ich > fNx ) goto new_ich;
00370           for( int ichc=last; ichc >= last-leng+1; ichc-- ) {
00371             if( iab-vhit[ichc].ich > fNx ) goto new_icl;
00372             if( iae-vhit[ichc].ich >= fNx ) {
00373               //*********** End: glue clusters with adjacent edge **********
00374 #endif
00375               CopyVector( &vhit[last+1-leng], vt, leng );
00376               CopyVector( &vhit[last+1], &vhit[last+1-leng], ib-1-last )
00377                 ;
00378               CopyVector( vt, &vhit[ib-leng], leng );
00379               for( int i=iCl; i<nCl-2; i++ ) LenCl[i]=LenCl[i+1];
00380               ib -= leng;
00381               LenCl[nCl-2]=LenCl[nCl-1]+leng;
00382               nCl--;
00383               goto new_icl;
00384             }
00385           }
00386         new_icl:           last=last-leng;
00387         }
00388       }
00389     }
00390   new_ich:   continue;
00391   }
00392   if( nCl > 0 ) {
00393     ib=0;
00394     for( int iCl=0; iCl<nCl; iCl++ ) { 
00395       leng=LenCl[iCl];
00396       hl.erase( hl.begin(), hl.end() );
00397       for( ich=0; ich<leng; ich++ ) hl.push_back(vhit[ib+ich]);
00398       Clt.ReInitialize(hl);
00399       ib += LenCl[iCl];
00400       fClusters->push_back(Clt);
00401     }
00402   }
00403   delete [] vhit;
00404   delete [] vt;
00405 
00406   return nCl;
00407   
00408 }
00409 
00410 // ///////////////////////////////////////////////////////////////////////////
00411 void EmcSectorRec::GetImpactAngle(float x, float y, float *sinT )
00412   // Get impact angle, (x,y) - position in Sector frame (cm)
00413 {
00414   float xVert, yVert, zVert;
00415   float vx, vy, vz;
00416 
00417   GlobalToSector( fVx, fVy, fVz, &xVert, &yVert, &zVert );
00418   vz = -zVert;
00419   vy = y - yVert;
00420   vx = x - xVert;
00421   // From this point X coord in sector frame is Z coord in Global Coord System !!!
00422   *sinT = sqrt((vx*vx+vy*vy)/(vx*vx+vy*vy+vz*vz));
00423 }
00424 
00425 
00426 void EmcSectorRec::GlobalToSector(float xgl, float ygl, float zgl, float* px,
00427                                  float* py, float* pz)
00428 {
00429 
00430   PHPoint phnxHit(xgl, ygl, zgl);
00431   PHPoint emcHit  = PHGeometry::transformPoint(invemcrm, invemctr, phnxHit);
00432   *px =  emcHit.getX();
00433   *py =  emcHit.getY();
00434   *pz =  emcHit.getZ();
00435 
00436 }
00437 
00438 // ///////////////////////////////////////////////////////////////////////////
00439 
00440 void EmcSectorRec::SectorToGlobal(float xsec, float ysec, float zsec,
00441                                  float* px, float* py, float* pz ) 
00442 {
00443   PHPoint emcHit(xsec, ysec, zsec);
00444   PHPoint phnxHit  = PHGeometry::transformPoint(emcrm, emctr, emcHit);
00445   *px =  phnxHit.getX();
00446   *py =  phnxHit.getY();
00447   *pz =  phnxHit.getZ();
00448   
00449 }
00450 
00451 
00452 // ///////////////////////////////////////////////////////////////////////////
00453 
00454 void EmcSectorRec::SectorToGlobalErr( float dxsec, float dysec, float dzsec,
00455                                      float* pdx, float* pdy, float* pdz ) 
00456 {
00457   *pdx = 0.;
00458   *pdy = 0.;
00459   *pdz = 0.;
00460 }
00461 
00462 // ///////////////////////////////////////////////////////////////////////////
00463 
00464 void EmcSectorRec::Gamma(int nh, EmcModule* phit, float* pchi, float* pchi0,
00465                         float* pe1, float* px1, float* py1, float* pe2,
00466                         float* px2, float* py2, int &ndf)
00467 {
00468   // Tests for 1 or 2 photon hypothesis by minimizing the chi2.
00469   // If the energy of one of two showers is less then fgMinShowerEnergy 
00470   // they are merged
00471   //
00472   // Returns two shower parameters (pe1,px1,py1,pe2,px2,py2). 
00473   // If one shower hypothesis accepted -> *pe2=0
00474   // *pchi  - chi2 after splitting
00475   // *pchi0 - chi2 before splitting
00476   // ndf contains number of degrees of freedom (not equal to number of cluster
00477   // modules for PbGl).
00478 
00479   float e1, x1, y1, e2, x2, y2;
00480   float chi, chi0, chi00, chisq0, chisave;
00481   float chir, chil, chiu, chid;
00482   int dof;
00483   float x0, y0, d2, xm2;
00484   float stepx, stepy, parx, pary;
00485   const float dxy=0.06;
00486   const float stepmin=0.01;
00487   const float zTG=100;
00488   const float xmcut=0.0015; // (GeV), for overlapping showers separation
00489 
00490   *pe1=0;
00491   *px1=0;
00492   *py1=0;
00493   *pe2=0;
00494   *px2=0;
00495   *py2=0;
00496   if( nh <= 0 ) return;
00497   Mom1(nh,phit,&e1,&x1,&y1);
00498   *pe1=e1;     
00499   if( e1 <= 0 ) return;
00500   
00501   SetProfileParameters(0, e1,x1,y1);
00502 
00503   chisave = *pchi;
00504   chi = *pchi;
00505   // ClusterChisq parameter list changed MV 28.01.00
00506   chi0 = ClusterChisq(nh, phit, e1, x1, y1, ndf);
00507 
00508   chisq0 = chi0;
00509   dof = ndf; // nh->ndf MV 28.01.00
00510 
00511   // ndf=0 means the cluster's chi2 cannot be found; in this case chi0=0.
00512   if( dof < 1 ) dof=1;
00513   chi = chisq0/dof;
00514   x0 = x1;
00515   y0 = y1;
00516   for(;;){
00517 
00518     chir = ClusterChisq(nh, phit, e1, x0+dxy, y0, ndf);
00519     chil = ClusterChisq(nh, phit, e1, x0-dxy, y0, ndf);
00520     chiu = ClusterChisq(nh, phit, e1, x0, y0+dxy, ndf);
00521     chid = ClusterChisq(nh, phit, e1, x0, y0-dxy, ndf);
00522     
00523     if( (chi0 > chir) || (chi0 > chil) ) {
00524       stepx = dxy;
00525       if( chir > chil ) stepx = -stepx;
00526     }
00527     else {
00528       stepx = 0;
00529       parx = chir+chil-2*chi0;
00530       if( parx > 0 ) stepx = -dxy*(chir-chil)/2/parx;
00531     }
00532     
00533     if( (chi0 > chiu) || (chi0 > chid) ) {
00534       stepy = dxy;
00535       if( chiu > chid ) stepy = -stepy;
00536     }
00537     else {
00538       stepy = 0;
00539       pary = chiu+chid-2*chi0;
00540       if( pary > 0 ) stepy = -dxy*(chiu-chid)/2/pary;
00541     }
00542     if( (EmcCluster::ABS(stepx) < stepmin) && (EmcCluster::ABS(stepy) < stepmin) ) break;
00543     chi00 = ClusterChisq(nh, phit, e1, x0+stepx, y0+stepy, ndf);
00544 
00545     if( chi00 >= chi0 ) break;
00546     chi0 = chi00;
00547     x0 += stepx;
00548     y0 += stepy;
00549   }
00550   if( chi0 < chisq0 ) {
00551     x1 = x0;
00552     y1 = y0;
00553     chi = chi0/dof;
00554   }
00555   
00556   *pchi0 = chi;
00557   *pchi = chi;
00558   *px1 = x1;
00559   *py1 = y1;
00560 
00561   if( e1 <= fgMinShowerEnergy ) return;
00562   
00563   if( chi > chisave ) {
00564     TwoGamma(nh,phit,&chi,&e1,&x1,&y1,&e2,&x2,&y2);
00565     if( e2 > 0 ) {
00566       d2 = ((x1-x2)*(x1-x2) + (y1-y2)*(y1-y2))/zTG/zTG;
00567       xm2 = e1*e2*d2;
00568       if( xm2 > 0 ) xm2 = sqrt(xm2);
00569       if( xm2 > xmcut && e1 > fgMinShowerEnergy && e2 > fgMinShowerEnergy) {
00570         *pe1 = e1;
00571         *px1 = x1;
00572         *py1 = y1;
00573         *pe2 = e2;
00574         *px2 = x2;
00575         *py2 = y2;
00576         *pchi = chi;
00577       }
00578     }   
00579   }
00580 }
00581 
00582 // ///////////////////////////////////////////////////////////////////////////
00583 
00584 void EmcSectorRec::Mom1(int nh, EmcModule* phit, float* pe, float* px,
00585                        float* py)
00586 {
00587   // First momentum calculation
00588 
00589   float a, xw, yw, e;
00590   int ix, iy;
00591   EmcModule* p;
00592   
00593   *pe=0;
00594   *px=0;
00595   *py=0;
00596   if( nh <= 0 ) return;
00597   p=phit;
00598   xw=0;
00599   yw=0;
00600   e=0;
00601   for( int i=0; i<nh; i++ ) {
00602     a = p->amp;
00603     iy = p->ich / fNx;
00604     ix = p->ich - iy*fNx;
00605     e += a;
00606     xw += ix*a;
00607     yw += iy*a;
00608     p++;
00609   }
00610   *pe = e;
00611   if( e <= 0 ) return;
00612   *px = xw/e;
00613   *py = yw/e;
00614 
00615 }
00616 
00617 // ///////////////////////////////////////////////////////////////////////////
00618 
00619 void EmcSectorRec::Momenta(int nh, EmcModule* phit, float* pe, float* px,
00620                           float* py, float* pxx, float* pyy, float* pyx )
00621 {
00622   // First and second momenta calculation
00623   
00624   float a, x, y, e, xx, yy, yx;
00625   int ix, iy, i;
00626   EmcModule* p;
00627   
00628   *pe=0;
00629   *px=0;
00630   *py=0;
00631   *pxx=0;
00632   *pyy=0;
00633   *pyx=0;
00634   if( nh <= 0 ) return;
00635   
00636   p=phit;
00637   x=0;
00638   y=0;
00639   e=0;
00640   xx=0;
00641   yy=0;
00642   yx=0;
00643   for( i=0; i<nh; i++ ) {
00644     a = p->amp;
00645     iy = p->ich / fNx;
00646     ix = p->ich - iy*fNx;
00647     e += a;
00648     x += ix*a;
00649     y += iy*a;
00650     xx += a*ix*ix;
00651     yy += a*iy*iy;
00652     yx += a*ix*iy;
00653     p++;
00654   }
00655   *pe = e;
00656   if( e <= 0 ) return;
00657   x /= e;
00658   y /= e;
00659   xx = xx/e - x*x;
00660   yy = yy/e - y*y;
00661   yx = yx/e - y*x;
00662   
00663   *px = x;
00664   *py = y;
00665   *pxx = xx;
00666   *pyy = yy;
00667   *pyx = yx;
00668 
00669 }
00670 // ///////////////////////////////////////////////////////////////////////////
00671 // Static functions
00672 
00673 int EmcSectorRec::HitNCompare(const void* h1, const void* h2)
00674 {
00675 
00676   return ( ((EmcModule*)h1)->ich - ((EmcModule*)h2)->ich );
00677 
00678 }
00679 
00680 // ///////////////////////////////////////////////////////////////////////////
00681 
00682 int EmcSectorRec::HitACompare(const void* h1, const void* h2)
00683 {
00684 
00685   float amp1 = ((EmcModule*)h1)->amp;
00686   float amp2 = ((EmcModule*)h2)->amp;
00687   return (amp1<amp2) ? 1: (amp1>amp2) ? -1 : 0;
00688 
00689 }
00690 
00691 // ///////////////////////////////////////////////////////////////////////////
00692 
00693 void EmcSectorRec::ZeroVector(int* v, int N)
00694 {
00695 
00696   int* p = v;
00697   for(int i=0; i<N; i++) *p++ = 0;
00698 
00699 }
00700 
00701 // ///////////////////////////////////////////////////////////////////////////
00702 
00703 void EmcSectorRec::ZeroVector(float* v, int N)
00704 {
00705 
00706   float* p = v;
00707   for(int i=0; i<N; i++) *p++ = 0;
00708 
00709 }
00710 
00711 // ///////////////////////////////////////////////////////////////////////////
00712 
00713 void EmcSectorRec::ZeroVector(EmcModule* v, int N)
00714 {
00715   memset(v, 0, N*sizeof(EmcModule));
00716 }
00717 
00718 // ///////////////////////////////////////////////////////////////////////////
00719 
00720 void EmcSectorRec::ResizeVector(int* Vector, int OldSize, int NewSize)
00721 {
00722 
00723   int* vsave;
00724 
00725   if( OldSize <= 0 ) { Vector = new int[NewSize]; return; }
00726   vsave = new int[OldSize];
00727   CopyVector( Vector, vsave, OldSize );
00728   delete [] Vector;
00729   Vector = new int[NewSize];
00730   if( NewSize > OldSize ) CopyVector( vsave, Vector, OldSize );
00731   else                  CopyVector( vsave, Vector, NewSize );
00732   delete [] vsave;
00733   return;
00734 
00735 }
00736 
00737 // ///////////////////////////////////////////////////////////////////////////
00738 
00739 void EmcSectorRec::CopyVector(int* from, int* to, int N)
00740 {
00741 
00742   if( N <= 0 ) return;
00743   for( int i=0; i<N; i++ ) to[i]=from[i];
00744 
00745 }
00746 
00747 // ///////////////////////////////////////////////////////////////////////////
00748 
00749 void EmcSectorRec::CopyVector(EmcModule* from, EmcModule* to, int N)
00750 {
00751 
00752   if( N <= 0 ) return;
00753   for( int i=0; i<N; i++ ) to[i]=from[i];
00754 
00755 }
00756 
00757 // ///////////////////////////////////////////////////////////////////////////
00758 
00759 void EmcSectorRec::c3to5(float e0, float x0, float y0, float eps,
00760                       float dx, float dy,
00761                       float* pe1, float* px1, float* py1,
00762                       float* pe2, float* px2, float* py2)
00763 {
00764   // 3 to 5-dim space conversion subroutine.
00765   // eps=(e1-e2)/e0,  (e0=e1+e2), x0*e0=x1*e1+x2*e2, dx=x1-x2
00766 
00767   *pe1 = e0*(1+eps)/2;
00768   *pe2 = e0 - *pe1;
00769   *px1 = x0 + dx*(1-eps)/2;
00770   *py1 = y0 + dy*(1-eps)/2;
00771   *px2 = x0 - dx*(1+eps)/2;
00772   *py2 = y0 - dy*(1+eps)/2;
00773 
00774 }
00775 
00776 // ///////////////////////////////////////////////////////////////////////////
00777 
00778 void EmcSectorRec::SetChi2Limit(int limit)
00779 {
00780   // Sets the limit for PeakArea splitting onto 2 EMShowers:
00781   // limit=0 -> For the Conf Level: 0%
00782   // limit=1 -> For the Conf Level: 1% for GEANT, 2%-5% for TestBeam
00783   // limit=2 -> For the Conf Level: 2% for GEANT, 4%-7% for TestBeam
00784   
00785   int i;
00786   
00787   switch ( limit ) {
00788 
00789   case 0:
00790     for( i=0; i<50; i++ ) fgChi2Level[i]=9999.;
00791     break;
00792   case 1:
00793     for( i=0; i<50; i++ ) fgChi2Level[i]=fgChi2Level1[i];
00794     break;
00795   case 2:
00796     for( i=0; i<50; i++ ) fgChi2Level[i]=fgChi2Level2[i];
00797     break;
00798   default:
00799     for( i=0; i<50; i++ ) fgChi2Level[i]=fgChi2Level1[i];
00800     break;
00801 
00802   }
00803 }
00804 
00805 // ///////////////////////////////////////////////////////////////////////////
00806 
00807 /* Future improvements:
00808 
00809 1. FindClusters(): to ensure that all EmcModules are above energy threshold 
00810 set by SetThreshold routine (or default one)
00811 
00812 */
00813 
00814 // ///////////////////////////////////////////////////////////////////////////
00815 // EOF