EmcScSectorRec.cxx

Go to the documentation of this file.
00001 // Name: EmcScSectorRec.cxx
00002 // Author: A. Bazilevsky (RIKEN-BNL)
00003 // Major modifications by M. Volkov (RRC KI) Jan 27 2000
00004 
00005 // ///////////////////////////////////////////////////////////////////////////
00006 
00007 /*
00008 A.Bazilevsky (IHEP, Protvino) - Dec. 1998
00009 (from March 99 - RIKEN-BNL Research Center)
00010 
00011 shura@bnl.gov
00012 
00013 Cluster-Shower reconstruction routines based on the A.Lednev's 
00014 method developed for GAMS (IHEP-CERN).
00015 
00016 The Classes and Basic Functions description is in cluster.h
00017 
00018 The method is based on the parameterized shower profile (energy deposited 
00019 in the tower as a function of the distance between tower center and shower 
00020 Center of Gravity, shower energy and impact angle). No difference between 
00021 the shower produced by electrons or gammas is assumed.
00022 
00023 ************ The shower reconstruction follows three steps: *********
00024 
00025 1.  Cluster search. A cluster is one or several neighboring cells 
00026 separated from the other clusters with zero cells. The cluster are analyzed 
00027 independently. 
00028 Implementation: Class "cluster". The list of clusters is obtained via 
00029 "Find_Clusters" function that has the list of EmcModules as an input (look at 
00030 "EmcModule" structure description in cluster.h). For the brief description of 
00031 the "cluster" methods look in cluster.h.
00032 
00033 2.  Each cluster may contain several peaks. A peak is located in a cell whose 
00034 deposited energy is higher then that of any adjoined cell. Peak regions are 
00035 calculated by sharing the energy deposited in each cell according the  
00036 energies expected from the gammas located in each peak region. This is 
00037 iterative procedure. 
00038 Implementation: Class "EmcPeakarea"; most of the methods are inherited from 
00039 "cluster". The array of peakareas for the given cluster is obtained via 
00040 "cluster::GetPeaks( EmcPeakarea*, EmcModule* )" method. For the brief description of 
00041 the "EmcPeakarea" methods look in cluster.h.
00042 
00043 3.  Gamma reconstruction within the peak region. One or two gammas within a 
00044 peak region. Minimizes Hi**2 function in two-dimensional space ( X,Y shower 
00045 position ). If it is more then some limit, two-gamma hypothesis is taken. 
00046 The two-gamma separation is done by minimizing Hi**2 function with the 
00047 maximum slope method in three-dimensional space: a=(E1-E2)/E0, dX=X1-X2, 
00048 dY=Y1-Y2. 
00049 Implementation: Class "EmcEmshower". The array of EmcEmshower's for the given 
00050 peakarea is obtained via "EmcPeakarea::GetGammas( EmcEmshower* )" method. 
00051 For the brief description of the "EmcEmshower" methods look in cluster.h.
00052 
00053 ************* Main tips for using these library ***************
00054 
00055 1. Parameters setting
00056 
00057 SetThreshold(TowerThresh) - sets the threshold (GeV) in each tower; 
00058 needed for the calculation of sigmas of the energy fluctuation in the 
00059 towers; default value is 0.02 GeV;
00060 
00061 SetChi2Limit(i) - sets Chi2 limit for the splitting of peakarea onto 
00062 two showers; default value is 1;
00063 
00064 2. Program flow
00065 
00066 All sectors are processed independently. Everything starts with 
00067 Find_Clusters call which returns the list of clusters. It has 
00068 the list of EmcModules as an input. Towers are counted from 0. 
00069 Before every Find_Cluster call user should set the sector geometry 
00070 and vertex position via SetGeometry( SecGeom Geom, float* pVert) call. 
00071 
00072 As soon as one gets the list of clusters, he can do whatever he wants: 
00073 get cluster's characteristics, split each of them onto peakarea's, 
00074 get peakarea's characteristics, split each of them onto EmcEmshower's, 
00075 get EmcEmshower's characteristics. 
00076 
00077 3. Shower Profile
00078 
00079 The parameterized Shower Profile is used when splitting cluster onto 
00080 peakareas and peakarea onto EmcEmshowers. The parameters for the Shower 
00081 Profile calculation are set via SetProfileParameters(...) function for 
00082 each peakarea object. The energy deposited in the particular tower is 
00083 obtained via PredictEnergy(...) function (based on the Shower Profile)
00084 
00085 */
00086 
00087 #include "EmcScSectorRec.h"
00088 #include "EmcCluster.h"
00089 
00090 // ///////////////////////////////////////////////////////////////////////////
00091 // Define and initialize static members
00092 
00093 // Parameters for sigma in Hi2 calculations (p.36-37 v.3)
00094 float EmcScSectorRec::fgEpar00 = 0.005;
00095 float EmcScSectorRec::fgEpar0 = 0.0014;
00096 float EmcScSectorRec::fgEpar1 = 0.03;
00097 float EmcScSectorRec::fgEpar2 = -0.03;
00098 // This is for PPLO mode !!!
00099 float EmcScSectorRec::fgEpar3 = 0.;
00100 float EmcScSectorRec::fgEpar4 = 4.0;
00101 
00102 // ///////////////////////////////////////////////////////////////////////////
00103 // EmcScSectorRec member functions
00104 
00105 void EmcScSectorRec::CorrectEnergy(float Energy, float x, float y, 
00106                                    float* Ecorr)
00107 {
00108   // Corrects the EM Shower Energy for attenuation in fibers and 
00109   // long energy leakage
00110   //
00111   // (x,y) - impact position (cm) in Sector frame
00112 
00113   float sinT;
00114   float att, leak, corr;
00115   const float leakPar = 0.0033; // parameter from fit
00116   const float attPar = 120; // Attenuation in module (cm)
00117   const float X0 = 2; // radiation length (cm)
00118 
00119   *Ecorr = Energy;
00120   if( Energy < 0.01 ) return;
00121 
00122   GetImpactAngle(x, y, &sinT); // sinT not used so far
00123   leak = 2-sqrt(1+leakPar*log(1+Energy)*log(1+Energy));
00124   att = exp(log(Energy)*X0/attPar);
00125   corr = leak*att;
00126   *Ecorr = Energy/corr;
00127 }
00128 
00130 
00131 void EmcScSectorRec::CorrectECore(float Ecore, float x, float y, float* Ecorr)
00132 {
00133   // Corrects the EM Shower Core Energy for attenuation in fibers, 
00134   // long energy leakage and angle dependance
00135   //
00136   // (x,y) - impact position (cm) in Sector frame
00137 
00138   float ec, ec2, corr;
00139   float sinT;
00140   const float par1 = 0.918;
00141   const float par2 = 1.35;
00142   const float par3 = 0.003;
00143 
00144   *Ecorr = Ecore;
00145   if( Ecore < 0.01 ) return;
00146 
00147   GetImpactAngle(x, y, &sinT );
00148   corr = par1 * ( 1 - par2*sinT*sinT*sinT*sinT*(1 - par3*log(Ecore)) );
00149   ec = Ecore/corr;
00150 
00151   CorrectEnergy( ec, x, y, &ec2);
00152   *Ecorr = ec2;
00153 }
00154 
00156 
00157 void EmcScSectorRec::CorrectPosition(float Energy, float x, float y,
00158                                      float* pxc, float* pyc, bool callSetPar)
00159 {
00160   // Corrects the Shower Center of Gravity for the systematic error due to 
00161   // the limited tower size and angle shift
00162   //
00163   // Everything here is in cm. 
00164   // (x,y) - CG position, (*pxc,*pyc) - corrected position
00165 
00166   float xShift, yShift, xZero, yZero, bx, by;
00167   float t, x0, y0;
00168   int ix0, iy0;
00169   int signx, signy;
00170 
00171   SetProfileParameters( 0, Energy, x/GetModSizex(), y/GetModSizey() );
00172   if( fSinTx > 0 ) signx =  1;
00173   else     signx = -1;
00174   if( fSinTy > 0 ) signy =  1;
00175   else     signy = -1;
00176   t = 1.93+0.383*log(Energy);
00177   xShift = t*fSinTx;
00178   yShift = t*fSinTy;
00179   xZero=xShift-(0.417*EmcCluster::ABS(fSinTx)+1.500*fSinTx*fSinTx)*signx;
00180   yZero=yShift-(0.417*EmcCluster::ABS(fSinTy)+1.500*fSinTy*fSinTy)*signy;
00181   t = 0.98 + 0.98*sqrt(Energy);
00182   bx = 0.16 + t*fSinTx*fSinTx;
00183   by = 0.16 + t*fSinTy*fSinTy;
00184   
00185   x0 = x/GetModSizex();
00186   x0 = x0 - xShift + xZero;
00187   ix0 = EmcCluster::lowint(x0 + 0.5);
00188   if( EmcCluster::ABS(x0-ix0) <= 0.5 ) {
00189     x0 = (ix0-xZero)+bx*asinh( 2.*(x0-ix0)*sinh(0.5/bx) );
00190     *pxc = x0*GetModSizex();
00191   }
00192   else {
00193     *pxc =  x - xShift*GetModSizex();
00194     printf("????? Something wrong in CorrectPosition of EMCalClusterChi2: x=%f  dx=%f\n", x, x0-ix0);
00195   }
00196 
00197   y0 = y/GetModSizey();
00198   y0 = y0 - yShift + yZero;
00199   iy0 = EmcCluster::lowint(y0 + 0.5);
00200 
00201   if( EmcCluster::ABS(y0-iy0) <= 0.5 ) {
00202 
00203     y0 = (iy0-yZero)+by*asinh( 2.*(y0-iy0)*sinh(0.5/by) );
00204     *pyc = y0*GetModSizey();
00205 
00206   }
00207   else {
00208 
00209     *pyc = y - yShift*GetModSizey();
00210     printf("????? Something wrong in CorrectPosition of EMCalClusterChi2: y=%f  dy=%f\n", y, y0-iy0);
00211 
00212   }
00213   
00214 }
00215 
00216 // ///////////////////////////////////////////////////////////////////////////
00217 
00218 void EmcScSectorRec::CalculateErrors( float e, float x, float y, float* pde,
00219                                    float* pdx, float* pdy, float* pdz)
00220 {
00221   // Returns the errors for the reconstructed energy and position 
00222   // (in the hypothesis of EM shower)
00223   // Should be called only just after CorrectPosition !!!
00224 
00225   float de, dy, dz, dxg, dyg, dzg;
00226   static float ae = 0.076, be = 0.022;          // de/E = a/sqrt(E)&b
00227   static float a = 0.57, b = 0.155, d = 1.6;    // dx = a/sqrt(E)+b (cm)
00228   static float dx = 0.1;  // (cm)
00229   
00230   de = sqrt( ae*ae*e + be*be*e*e );
00231   dz = a/sqrt(e) + b;
00232   dy = dz;
00233   dz = sqrt( dz*dz + d*d*fSinTx*fSinTx );
00234   dy = sqrt( dy*dy + d*d*fSinTy*fSinTy );
00235   
00236   SectorToGlobalErr( dx, dy, dz, &dxg, &dyg, &dzg );
00237   
00238   *pde = de;
00239   *pdx = dxg;
00240   *pdy = dyg;
00241   *pdz = dzg;
00242 
00243 }
00244 
00245 // ///////////////////////////////////////////////////////////////////////////
00246 
00247 void EmcScSectorRec::SetProfileParameters(int sec, float Energy, float x,
00248                                         float y )
00249 {
00250   // Axis Z here means X in two dim Sector coord system !!! 
00251   // So one has to supply (x,y) coordinates in cell units (x instead of z)
00252   // If sec < 0 this routine changes only Energy dependent parameters - 
00253   // the angle dependent ones are set in the previous call
00254 
00255   float t;
00256   static float sin2ax, sin2ay, sin2a, lgE;
00257   float vx, vy, vz;
00258   float xVert, yVert, zVert;
00259   int sign;
00260   
00261   if( sec >= 0 ) {
00262     // Vertex coordinates in Sector coordinate system
00263     GlobalToSector( fVx, fVy, fVz, &xVert, &yVert, &zVert );
00264     vz = -zVert;
00265     // It is if we use the coordinates of the Sector Center (not zero-tower)
00266     vy = y*fModSizey - yVert;
00267     vx = x*fModSizex - xVert;
00268     // From this point X coord in sector frame is Z coord in Global Coord System !!!
00269     fSinTx = vx/sqrt(vx*vx+vz*vz);
00270     fSinTy = vy/sqrt(vy*vy+vz*vz);
00271     if( EmcCluster::ABS(fSinTx) > 0.7 || EmcCluster::ABS(fSinTy) > 0.7 ) 
00272       printf("!!!!! Something strange in SetProfileParmeters of mEmcClusterChi2: fSinTx=%f  fSinTy=%f\n",fSinTx, fSinTy);
00273     t = (vx*vx+vy*vy)/(vx*vx+vy*vy+vz*vz);
00274     sin2a=t;
00275     fSin4T=t*t;
00276     sin2ax=fSinTx*fSinTx;
00277     sin2ay=fSinTy*fSinTy;
00278   }
00279   
00280   if( Energy <= 1.e-10 ) lgE=0;
00281   else lgE=log(Energy);
00282   
00283   fPpar1=0.59-(1.45+0.13*lgE)*sin2a;
00284   fPpar2=0.265+(0.80+0.32*lgE)*sin2a;
00285   fPpar3=0.25+(0.45-0.036*lgE)*sin2a;
00286   fPpar4=0.42;
00287   
00288   if( fSinTx > 0 ) sign = 1;
00289   else sign = -1;
00290   fPshiftx = (1.05+0.12*lgE) * sin2ax * sign;
00291   
00292   if( fSinTy > 0 ) sign = 1;
00293   else sign = -1;
00294   fPshifty = (1.05+0.12*lgE) * sin2ay * sign;
00295 }
00296 
00297 // ///////////////////////////////////////////////////////////////////////////
00298 
00299 float EmcScSectorRec::PredictEnergy(float xc, float yc, float en)
00300 {
00301   // Calculates the energy deposited in the tower, the distance between 
00302   // its center and shower Center of Gravity being (xc,yc)
00303   // en - shower energy
00304   // If en<0 -> no Shower Profile parameters change is needed
00305 
00306   float dx, dy, r1, r2, r3, e;
00307   
00308   if( en > 0 ) SetProfileParameters(-1,en,xc,yc);
00309   dx=fabs(xc-fPshiftx);
00310   dy=EmcCluster::ABS(yc-fPshifty);
00311   e=0;
00312   r2=dx*dx+dy*dy;
00313   r1=sqrt(r2);
00314   r3=r2*r1;
00315   e=fPpar1*exp(-r3/fPpar2)+fPpar3*exp(-r1/fPpar4);
00316   
00317   return e;
00318 
00319 }
00320 
00321 // ///////////////////////////////////////////////////////////////////////////
00322 
00323 void EmcScSectorRec::TwoGamma(int nh, EmcModule* phit, float* pchi, float* pe1,
00324                            float* px1, float* py1, float* pe2, float* px2,
00325                            float* py2)
00326 {
00327 
00328   float e0, x0, y0, xx, yy, yx;
00329   float dxy, rsg2, rsq;
00330   float dxc, dyc, r, epsc;
00331   int ix, iy, ixy, in, iter, dof;
00332   float step, cosi, chisq2, u;
00333   float e1c, x1c, y1c, e2c, x2c, y2c;
00334   float eps0 = 0.0;
00335   float eps1, eps2, chisqc, ex;
00336   float dx1, dy1, dx2, dy2, a0, d;
00337   float dchi, dchi0, dd, dchida, a1, a2;
00338   float gr = 0.0;
00339   float grec, grxc, gryc, grc, gx1, gx2, gy1, gy2;
00340   float gre = 0.0;
00341   float grx = 0.0;
00342   float gry = 0.0;
00343   float scal;
00344   float dx0 = 0.0;
00345   float dy0 = 0.0;
00346   
00347   const float epsmax=0.9999;
00348   const float stpmin=0.025;
00349   const float delch=2;
00350   
00351   Momenta(nh,phit,&e0,&x0,&y0,&xx,&yy,&yx);
00352   *pe2 = 0;
00353   *px2 = 0;
00354   *py2 = 0;
00355   if( nh <= 0 ) return;
00356   //  choosing of the starting point
00357   dxy = xx-yy;
00358   rsg2 = dxy*dxy + 4*yx*yx;
00359   if( rsg2 < 1e-20 ) rsg2 = 1e-20;
00360   rsq = sqrt(rsg2);
00361   dxc = -sqrt((rsq+dxy)*2);
00362   dyc =  sqrt((rsq-dxy)*2);
00363   if( yx >= 0 ) dyc = -dyc;
00364   r = sqrt(dxc*dxc + dyc*dyc);
00365   epsc = 0;
00366   for( in=0; in<nh; in++ ) {
00367     ixy = phit[in].ich;
00368     iy = ixy/fNx;
00369     ix = ixy - iy*fNx;
00370     u = (ix-x0)*dxc/r + (iy-y0)*dyc/r;
00371     epsc -= phit[in].amp * u * EmcCluster::ABS(u);
00372   }
00373   epsc /= (e0*rsq);
00374   if( epsc >  0.8 ) epsc = 0.8;
00375   if( epsc < -0.8 ) epsc =-0.8;
00376   dxc /= sqrt(1-epsc*epsc);
00377   dyc /= sqrt(1-epsc*epsc);
00378   //  Start of iterations
00379   step = 0.1;
00380   cosi = 0;
00381   chisq2 = 1.e35;
00382   for( iter=0; iter<100; iter++)
00383     {
00384       c3to5(e0,x0,y0,epsc,dxc,dyc,&e1c,&x1c,&y1c,&e2c,&x2c,&y2c);
00385       eps1 = (1+epsc)/2;
00386       eps2 = (1-epsc)/2;
00387       chisqc = 0;
00388       for( in=0; in<nh; in++ ) {
00389         ex = phit[in].amp;
00390         ixy = phit[in].ich;
00391         iy = ixy/fNx;
00392         ix = ixy - iy*fNx;
00393         dx1 = x1c - ix;
00394         dy1 = y1c - iy;
00395         dx2 = x2c - ix;
00396         dy2 = y2c - iy;
00397         a0 = e1c*PredictEnergy(dx1, dy1, e1c) + e2c*PredictEnergy(dx2, dy2, e2c);
00398         d = fgEpar00*fgEpar00 + e0*( fgEpar1*a0/e0 + fgEpar2*a0*a0/e0/e0 +fgEpar3*a0*a0*a0/e0/e0/e0 ) + e0*sqrt(e0)*fgEpar4*a0/e0*(1-a0/e0)*fSin4T + e0*e0*fgEpar0*fgEpar0;
00399         chisqc += (a0-ex)*(a0-ex)/d;
00400       }
00401       if( chisqc >= chisq2 ) {
00402         if( iter > 0 ) {
00403           dchi = chisqc-chisq2;
00404           dchi0 = gr*step;
00405           step /= (2*sqrt(1+dchi/dchi0));
00406         }
00407         step /= 2;
00408       }
00409       else {
00410         // Calculation of gradient
00411         grec = 0;
00412         grxc = 0;
00413         gryc = 0;
00414         for( in=0; in<nh; in++ ) {
00415           ex = phit[in].amp;
00416           ixy = phit[in].ich;
00417           iy = ixy/fNx;
00418           ix = ixy - iy*fNx;
00419           dx1 = x1c - ix;
00420           dy1 = y1c - iy;
00421           dx2 = x2c - ix;
00422           dy2 = y2c - iy;
00423           a1 = e1c*PredictEnergy(dx1,dy1,e1c);
00424           a2 = e2c*PredictEnergy(dx2,dy2,e2c);
00425           a0 = a1 + a2;
00426           d = fgEpar00*fgEpar00 + e0*( fgEpar1*a0/e0 + fgEpar2*a0*a0/e0/e0 +fgEpar3*a0*a0*a0/e0/e0/e0 ) + e0*sqrt(e0)*fgEpar4*a0/e0*(1-a0/e0)*fSin4T + e0*e0*fgEpar0*fgEpar0;
00427           dd = (a0-ex)/d;
00428           dchida = dd*( 2 - dd*(fgEpar1 + 2*fgEpar2*a0/e0 + 3*fgEpar3*a0*a0/e0/e0 + e0*sqrt(e0)*fgEpar4*fSin4T*(1-2*a0/e0) + 2*fgEpar0*fgEpar0*a0) );
00429           gx1 = ( e1c*PredictEnergy(x1c+0.05-ix,dy1,e1c) - a1 )*20;
00430           gx2 = ( e2c*PredictEnergy(x2c+0.05-ix,dy2,e2c) - a2 )*20;
00431           gy1 = ( e1c*PredictEnergy(dx1, y1c+0.05-iy,e1c) - a1 )*20;
00432           gy2 = ( e2c*PredictEnergy(dx2, y2c+0.05-iy,e2c) - a2 )*20;
00433           grec += (dchida*((a1/e1c-a2/e2c)*e0 - (gx1+gx2)*dxc -(gy1+gy2)*dyc)/2);
00434           grxc += (dchida*(gx1*eps2-gx2*eps1));
00435           gryc += (dchida*(gy1*eps2-gy2*eps1));
00436         }
00437         grc = sqrt(grec*grec + grxc*grxc + gryc*gryc);
00438         if( grc < 1e-10 ) grc = 1e-10;
00439         if( iter > 0 ) {
00440           cosi = (gre*grec + grx*grxc + gry*gryc ) / (gr*grc);
00441           scal = EmcCluster::ABS(gr/grc - cosi);
00442           if( scal < 0.1 ) scal = 0.1;
00443           step /= scal;
00444         }
00445         chisq2 = chisqc;
00446         eps0 = epsc;
00447         dx0 = dxc;
00448         dy0 = dyc;
00449         gre = grec;
00450         grx = grxc;
00451         gry = gryc;
00452         gr = grc;
00453       }
00454       epsc = eps0 - step*gre/gr;
00455       while( EmcCluster::ABS(epsc) >= epsmax ) {
00456         step /= 2;
00457         epsc = eps0 - step*gre/gr;
00458       }
00459       dxc = dx0 - step*grx/gr;
00460       dyc = dy0 - step*gry/gr;
00461       if( step*gr < stpmin ) break;
00462     }
00463   if( (*pchi)*nh-chisq2 < delch ) return;
00464   dof = nh;
00465   if( dof < 1 ) dof = 1;
00466   *pchi = chisq2/dof;
00467   c3to5(e0,x0,y0,eps0,dx0,dy0,pe1,px1,py1,pe2,px2,py2);
00468 
00469 }
00470 
00471 // ///////////////////////////////////////////////////////////////////////////
00472 
00473 float EmcScSectorRec::ClusterChisq(int nh, EmcModule* phit, float e, float x,
00474                                 float y, int &ndf)
00475 {
00476 
00477   float chi=0;
00478   int ixy, ix, iy;
00479   float et, a, d;
00480   
00481   for( int in=0; in<nh; in++ ) {
00482     ixy = phit[in].ich;
00483     iy = ixy/fNx;
00484     ix = ixy - iy*fNx;
00485     et = phit[in].amp;
00486     a = PredictEnergy(x-ix, y-iy, -1);
00487     d = fgEpar00*fgEpar00 + e*(fgEpar1*a + fgEpar2*a*a + fgEpar3*a*a*a) + 
00488       e*sqrt(e)*fgEpar4*a*(1-a)*fSin4T + e*e*fgEpar0*fgEpar0;
00489     a *= e;
00490     chi += (et-a)*(et-a)/d;
00491   }
00492 
00493   ndf=nh; // change needed for PbGl MV 28.01.00
00494   return chi;
00495 
00496 }
00497 
00498 // ///////////////////////////////////////////////////////////////////////////
00499 
00500 
00501 float EmcScSectorRec::Chi2Limit(int ND)
00502 {
00503   //  Here the reverse Chi2Correct function is used
00504   
00505   float rn, a, b, chi2;
00506   
00507   if( ND < 1 ) return 9999.;  // Should we put 0. here?
00508   
00509   chi2 = fgChi2Level[EmcCluster::min(ND,50)-1];
00510   if( chi2 > 100 ) return 9999.; // Why should chi2 ever be >100?
00511   
00512   rn = ND;
00513   b = 0.072*sqrt(rn);
00514   a = 6.21/(sqrt(rn)+4.7);
00515   
00516   return chi2*a/(1.-chi2*b);
00517 
00518 }
00519 
00520 // ///////////////////////////////////////////////////////////////////////////
00521 
00522 float EmcScSectorRec::Chi2Correct(float Chi2, int ND)
00523 {
00524   // Chi2 - is reduced Chi2: Chi2/ND !!
00525   // MV 02.22.2000: Actually the above is not true. The supplied value of Chi2
00526   // has been already divided by ND. So Chi2 here is only corrected.
00527 
00528   float rn, a, b, c;
00529   
00530   if( ND < 1 ) return 9999.; // Should we put 0. here?
00531   
00532   rn = ND;
00533   b = 0.072*sqrt(rn);
00534   a = 6.21/(sqrt(rn)+4.7);
00535   c = a + b*Chi2;
00536   if( c < 1 ) c=1;
00537   
00538   return Chi2/c;
00539 
00540 }
00541 
00542 // ///////////////////////////////////////////////////////////////////////////
00543 
00544 void EmcScSectorRec::SetTowerThreshold(float Thresh)
00545 {
00546   fgTowerThresh = Thresh;
00547   fgEpar0 = Thresh*0.07;
00548   fgEpar00 = EmcCluster::max( (double)Thresh/3, 0.005 );
00549 }
00550 
00551 // **********************************************************************
00552 
00553 void EmcScSectorRec::getTowerPos(int ix, int iy, float &x, float & y){
00554   x = 2.859+5.562*ix+int(ix/12)*0.256;
00555   y = 2.859+5.562*iy+int(iy/12)*0.156;
00556 }
00557 
00558 // **********************************************************************
00559 
00560 
00562 void   EmcScSectorRec::TowersToSector(float xT, float yT, float & xS, float & yS){
00563   int   x  = int(xT);
00564   float dx = xT - x;
00565   int   y  = int(yT);
00566   float dy = yT - y;
00567   xS = fModSizex*(x+0.5) + int(xT/12)*0.256 + fModSizex*dx;
00568   yS = fModSizey*(y+0.5) + int(yT/12)*0.156 + fModSizey*dy;
00569 }
00570 
00571 // **********************************************************************
00573 void   EmcScSectorRec::TowersToSector(int xT,   int yT,   float & xS, float & yS){
00574     xS = fModSizex*(xT+0.5) + int(xT/12)*0.256;
00575     yS = fModSizey*(yT+0.5) + int(yT/12)*0.156;
00576 }
00577 
00578 // **********************************************************************
00580 void   EmcScSectorRec::SectorToTowers(float xS, float yS, int & xT,   int & yT){
00581   // PbSc
00582   xT = int(((xS-int(xS/67.0)*67.0)-0.078)/fModSizex) + 12*int(xS/67.0);
00583   yT = int(((yS-int(yS/66.9)*66.9)-0.078)/fModSizey) + 12*int(yS/66.9);
00584 
00585 }
00586 // ///////////////////////////////////////////////////////////////////////////
00587 // EOF