CMS 3D CMS Logo

/data/refman/pasoursint/CMSSW_5_2_9/src/Geometry/EcalAlgo/src/EcalEndcapGeometry.cc

Go to the documentation of this file.
00001 #include "Geometry/CaloGeometry/interface/CaloGenericDetId.h"
00002 #include "Geometry/EcalAlgo/interface/EcalEndcapGeometry.h"
00003 #include "Geometry/CaloGeometry/interface/CaloCellGeometry.h"
00004 #include "Geometry/CaloGeometry/interface/TruncatedPyramid.h"
00005 #include "FWCore/Utilities/interface/Exception.h"
00006 #include <CLHEP/Geometry/Point3D.h>
00007 #include <CLHEP/Geometry/Plane3D.h>
00008 
00009 typedef CaloCellGeometry::CCGFloat CCGFloat ;
00010 typedef CaloCellGeometry::Pt3D     Pt3D     ;
00011 typedef CaloCellGeometry::Pt3DVec  Pt3DVec  ;
00012 typedef HepGeom::Plane3D<CCGFloat> Pl3D     ;
00013 
00014 EcalEndcapGeometry::EcalEndcapGeometry( void )
00015   : _nnmods( 316 ),
00016     _nncrys( 25 ),
00017     zeP( 0. ),
00018     zeN( 0. ),
00019     m_wref( 0. ),
00020     m_del( 0. ),
00021     m_nref( 0 ),
00022     m_borderMgr( 0 ),
00023     m_borderPtrVec( 0 ),
00024     m_avgZ( -1 ),
00025     m_cellVec( k_NumberOfCellsForCorners )
00026 {
00027   m_xlo[0] = 999.;
00028   m_xlo[1] = 999.;
00029   m_xhi[0] = -999.;
00030   m_xhi[1] = -999.;
00031   m_ylo[0] = 999.;
00032   m_ylo[1] = 999.;
00033   m_yhi[0] = -999.;
00034   m_yhi[1] = -999.;
00035   m_xoff[0] = 0.;
00036   m_xoff[1] = 0.;
00037   m_yoff[0] = 0.;
00038   m_yoff[0] = 0.;
00039 }
00040 
00041 EcalEndcapGeometry::~EcalEndcapGeometry() 
00042 {
00043    delete m_borderPtrVec ;
00044    delete m_borderMgr ;
00045 }
00046 
00047 unsigned int
00048 EcalEndcapGeometry::alignmentTransformIndexLocal( const DetId& id )
00049 {
00050    const CaloGenericDetId gid ( id ) ;
00051 
00052    assert( gid.isEE() ) ;
00053    unsigned int index ( EEDetId(id).ix()/51 + ( EEDetId(id).zside()<0 ? 0 : 2 ) ) ;
00054 
00055    return index ;
00056 }
00057 
00058 DetId 
00059 EcalEndcapGeometry::detIdFromLocalAlignmentIndex( unsigned int iLoc )
00060 {
00061    return EEDetId( 20 + 50*( iLoc%2 ), 50, 2*( iLoc/2 ) - 1 ) ;
00062 }
00063 
00064 unsigned int
00065 EcalEndcapGeometry::alignmentTransformIndexGlobal( const DetId& /*id*/ )
00066 {
00067    return (unsigned int)DetId::Ecal - 1 ;
00068 }
00069 
00070 void 
00071 EcalEndcapGeometry::initializeParms()
00072 {
00073   zeP=0.;
00074   zeN=0.;
00075   unsigned nP=0;
00076   unsigned nN=0;
00077   m_nref = 0 ;
00078 
00079   for( uint32_t i ( 0 ) ; i != m_cellVec.size() ; ++i )
00080   {
00081      const CaloCellGeometry* cell ( cellGeomPtr(i) ) ;
00082      if( 0 != cell )
00083      {
00084         const CCGFloat z ( cell->getPosition().z() ) ;
00085         if(z>0.)
00086         {
00087            zeP+=z;
00088            ++nP;
00089         }
00090         else
00091         {
00092            zeN+=z;
00093            ++nN;
00094         }
00095         const EEDetId myId ( EEDetId::detIdFromDenseIndex(i) ) ;
00096         const unsigned int ix ( myId.ix() ) ;
00097         const unsigned int iy ( myId.iy() ) ;
00098         if( ix > m_nref ) m_nref = ix ;
00099         if( iy > m_nref ) m_nref = iy ;
00100      }
00101   }
00102   if( 0 < nP ) zeP/=(CCGFloat)nP;
00103   if( 0 < nN ) zeN/=(CCGFloat)nN;
00104 
00105   m_xlo[0] =  999 ;
00106   m_xhi[0] = -999 ;
00107   m_ylo[0] =  999 ;
00108   m_yhi[0] = -999 ;
00109   m_xlo[1] =  999 ;
00110   m_xhi[1] = -999 ;
00111   m_ylo[1] =  999 ;
00112   m_yhi[1] = -999 ;
00113   for( uint32_t i ( 0 ) ; i != m_cellVec.size() ; ++i )
00114   {
00115      const CaloCellGeometry* cell ( cellGeomPtr(i) ) ;
00116      if( 0 != cell )
00117      {
00118         const GlobalPoint p ( cell->getPosition()  ) ;
00119         const CCGFloat z ( p.z() ) ;
00120         const CCGFloat zz ( 0 > z ? zeN : zeP ) ;
00121         const CCGFloat x ( p.x()*zz/z ) ;
00122         const CCGFloat y ( p.y()*zz/z ) ;
00123 
00124         if( 0 > z && x < m_xlo[0] ) m_xlo[0] = x ;
00125         if( 0 < z && x < m_xlo[1] ) m_xlo[1] = x ;
00126         if( 0 > z && y < m_ylo[0] ) m_ylo[0] = y ;
00127         if( 0 < z && y < m_ylo[1] ) m_ylo[1] = y ;
00128      
00129         if( 0 > z && x > m_xhi[0] ) m_xhi[0] = x ;
00130         if( 0 < z && x > m_xhi[1] ) m_xhi[1] = x ;
00131         if( 0 > z && y > m_yhi[0] ) m_yhi[0] = y ;
00132         if( 0 < z && y > m_yhi[1] ) m_yhi[1] = y ;
00133      }
00134   }
00135 
00136   m_xoff[0] = ( m_xhi[0] + m_xlo[0] )/2. ;
00137   m_xoff[1] = ( m_xhi[1] + m_xlo[1] )/2. ;
00138   m_yoff[0] = ( m_yhi[0] + m_ylo[0] )/2. ;
00139   m_yoff[1] = ( m_yhi[1] + m_ylo[1] )/2. ;
00140 
00141   m_del = ( m_xhi[0] - m_xlo[0] + m_xhi[1] - m_xlo[1] +
00142             m_yhi[0] - m_ylo[0] + m_yhi[1] - m_ylo[1]   ) ;
00143 
00144   if( 1 != m_nref ) m_wref = m_del/(4.*(m_nref-1)) ;
00145 
00146   m_xlo[0] -= m_wref/2 ;
00147   m_xlo[1] -= m_wref/2 ;
00148   m_xhi[0] += m_wref/2 ;
00149   m_xhi[1] += m_wref/2 ;
00150 
00151   m_ylo[0] -= m_wref/2 ;
00152   m_ylo[1] -= m_wref/2 ;
00153   m_yhi[0] += m_wref/2 ;
00154   m_yhi[1] += m_wref/2 ;
00155 
00156   m_del += m_wref ;
00157 /*
00158   std::cout<<"zeP="<<zeP<<", zeN="<<zeN<<", nP="<<nP<<", nN="<<nN<<std::endl ;
00159 
00160   std::cout<<"xlo[0]="<<m_xlo[0]<<", xlo[1]="<<m_xlo[1]<<", xhi[0]="<<m_xhi[0]<<", xhi[1]="<<m_xhi[1]
00161            <<"\nylo[0]="<<m_ylo[0]<<", ylo[1]="<<m_ylo[1]<<", yhi[0]="<<m_yhi[0]<<", yhi[1]="<<m_yhi[1]<<std::endl ;
00162 
00163   std::cout<<"xoff[0]="<<m_xoff[0]<<", xoff[1]"<<m_xoff[1]<<", yoff[0]="<<m_yoff[0]<<", yoff[1]"<<m_yoff[1]<<std::endl ;
00164 
00165   std::cout<<"nref="<<m_nref<<", m_wref="<<m_wref<<std::endl ;
00166 */  
00167 }
00168 
00169 
00170 unsigned int 
00171 EcalEndcapGeometry::xindex( CCGFloat x,
00172                             CCGFloat z ) const
00173 {
00174    const CCGFloat xlo ( 0 > z ? m_xlo[0]  : m_xlo[1]  ) ;
00175    const int i ( 1 + int( ( x - xlo )/m_wref ) ) ;
00176 
00177    return ( 1 > i ? 1 :
00178             ( m_nref < (unsigned int) i ? m_nref : (unsigned int) i ) ) ;
00179 
00180 }
00181 
00182 unsigned int 
00183 EcalEndcapGeometry::yindex( CCGFloat y,
00184                             CCGFloat z  ) const
00185 {
00186    const CCGFloat ylo ( 0 > z ? m_ylo[0]  : m_ylo[1]  ) ;
00187    const int i ( 1 + int( ( y - ylo )/m_wref ) ) ;
00188 
00189    return ( 1 > i ? 1 :
00190             ( m_nref < (unsigned int) i ? m_nref : (unsigned int) i ) ) ;
00191 }
00192 
00193 EEDetId 
00194 EcalEndcapGeometry::gId( float x, 
00195                          float y, 
00196                          float z ) const
00197 {
00198    const CCGFloat     fac ( fabs( ( 0 > z ? zeN : zeP )/z ) ) ;
00199    const unsigned int ix  ( xindex( x*fac, z ) ) ; 
00200    const unsigned int iy  ( yindex( y*fac, z ) ) ; 
00201    const unsigned int iz  ( z>0 ? 1 : -1 ) ;
00202 
00203    if( EEDetId::validDetId( ix, iy, iz ) ) 
00204    {
00205       return EEDetId( ix, iy, iz ) ; // first try is on target
00206    }
00207    else // try nearby coordinates, spiraling out from center
00208    {
00209       for( unsigned int i ( 1 ) ; i != 6 ; ++i )
00210       {
00211          for( unsigned int k ( 0 ) ; k != 8 ; ++k )
00212          {
00213             const int jx ( 0 == k || 4 == k || 5 == k ? +i :
00214                            ( 1 == k || 5 < k ? -i : 0 ) ) ;
00215             const int jy ( 2 == k || 4 == k || 6 == k ? +i :
00216                            ( 3 == k || 5 == k || 7 == k ? -i : 0 ) ) ;
00217             if( EEDetId::validDetId( ix + jx, iy + jy, iz ) ) 
00218             {
00219                return EEDetId( ix + jx, iy + jy, iz ) ;
00220             }
00221          }
00222       }
00223    }
00224    return EEDetId() ; // nowhere near any crystal
00225 }
00226 
00227 
00228 // Get closest cell, etc...
00229 DetId 
00230 EcalEndcapGeometry::getClosestCell( const GlobalPoint& r ) const 
00231 {
00232    try
00233    {
00234       EEDetId mycellID ( gId( r.x(), r.y(), r.z() ) ) ; // educated guess
00235 
00236       if( EEDetId::validDetId( mycellID.ix(), 
00237                                mycellID.iy(),
00238                                mycellID.zside() ) )
00239       {
00240          // now get points in convenient ordering
00241 
00242          Pt3D A;
00243          Pt3D B;
00244          Pt3D C;
00245          Pt3D point(r.x(),r.y(),r.z());
00246          // D.K. : equation of plane : AA*x+BB*y+CC*z+DD=0;
00247          // finding equation for each edge
00248          
00249          // ================================================================
00250          CCGFloat x,y,z;
00251          unsigned offset=0;
00252          int zsign=1;
00253          //================================================================
00254          std::vector<CCGFloat> SS;
00255       
00256          // compute the distance of the point with respect of the 4 crystal lateral planes
00257 
00258          
00259          if( 0 != getGeometry(mycellID) )
00260          {
00261             const GlobalPoint& myPosition=getGeometry(mycellID)->getPosition();
00262          
00263             x=myPosition.x();
00264             y=myPosition.y();
00265             z=myPosition.z();
00266          
00267             offset=0;
00268             // This will disappear when Andre has applied his fix
00269             zsign=1;
00270          
00271             if(z>0)
00272             {
00273                if(x>0&&y>0)
00274                   offset=1;
00275                else  if(x<0&&y>0)
00276                   offset=2;
00277                else if(x>0&&y<0)
00278                   offset=0;
00279                else if (x<0&&y<0)
00280                   offset=3;
00281                zsign=1;
00282             }
00283             else
00284             {
00285                if(x>0&&y>0)
00286                   offset=3;
00287                else if(x<0&&y>0)
00288                   offset=2;
00289                else if(x>0&&y<0)
00290                   offset=0;
00291                else if(x<0&&y<0)
00292                   offset=1;
00293                zsign=-1;
00294             }
00295             std::vector<GlobalPoint> corners;
00296             corners.clear();
00297             corners.resize(8);
00298             for(unsigned ic=0;ic<4;++ic)
00299             {
00300                corners[ic]=getGeometry(mycellID)->getCorners()[(unsigned)((zsign*ic+offset)%4)];
00301                corners[4+ic]=getGeometry(mycellID)->getCorners()[(unsigned)(4+(zsign*ic+offset)%4)];
00302             }
00303             
00304             for (short i=0; i < 4 ; ++i)
00305             {
00306                A = Pt3D(corners[i%4].x(),corners[i%4].y(),corners[i%4].z());
00307                B = Pt3D(corners[(i+1)%4].x(),corners[(i+1)%4].y(),corners[(i+1)%4].z());
00308                C = Pt3D(corners[4+(i+1)%4].x(),corners[4+(i+1)%4].y(),corners[4+(i+1)%4].z());
00309                Pl3D plane(A,B,C);
00310                plane.normalize();
00311                CCGFloat distance = plane.distance(point);
00312                if (corners[0].z()<0.) distance=-distance;
00313                SS.push_back(distance);
00314             }
00315          
00316             // Only one move in necessary direction
00317          
00318             const bool yout ( 0 > SS[0]*SS[2] ) ;
00319             const bool xout ( 0 > SS[1]*SS[3] ) ;
00320          
00321             if( yout || xout )
00322             {
00323                const int ydel ( !yout ? 0 :  ( 0 < SS[0] ? -1 : 1 ) ) ;
00324                const int xdel ( !xout ? 0 :  ( 0 < SS[1] ? -1 : 1 ) ) ;
00325                const unsigned int ix ( mycellID.ix() + xdel ) ;
00326                const unsigned int iy ( mycellID.iy() + ydel ) ;
00327                const unsigned int iz ( mycellID.zside()     ) ;
00328                if( EEDetId::validDetId( ix, iy, iz ) ) 
00329                   mycellID = EEDetId( ix, iy, iz ) ;
00330             }
00331   
00332             return mycellID;
00333          }
00334          return DetId(0);
00335       }
00336    }
00337    catch ( cms::Exception &e ) 
00338    { 
00339       return DetId(0);
00340    }
00341    return DetId(0);
00342 }
00343 
00344 CaloSubdetectorGeometry::DetIdSet 
00345 EcalEndcapGeometry::getCells( const GlobalPoint& r, 
00346                               double             dR ) const 
00347 {
00348    CaloSubdetectorGeometry::DetIdSet dis ; // return object
00349    if( 0.000001 < dR )
00350    {
00351       if( dR > M_PI/2. ) // this code assumes small dR
00352       {
00353          dis = CaloSubdetectorGeometry::getCells( r, dR ) ; // base class version
00354       }
00355       else
00356       {
00357          const double dR2  ( dR*dR ) ;
00358          const double reta ( r.eta() ) ;
00359          const double rphi ( r.phi() ) ;
00360          const double rx   ( r.x() ) ;
00361          const double ry   ( r.y() ) ;
00362          const double rz   ( r.z() ) ;
00363          const double fac  ( fabs( zeP/rz ) ) ;
00364          const double xx   ( rx*fac ) ; // xyz at endcap z
00365          const double yy   ( ry*fac ) ; 
00366          const double zz   ( rz*fac ) ; 
00367 
00368          const double xang  ( atan( xx/zz ) ) ;
00369          const double lowX  ( zz>0 ? zz*tan( xang - dR ) : zz*tan( xang + dR ) ) ;
00370          const double highX ( zz>0 ? zz*tan( xang + dR ) : zz*tan( xang - dR ) ) ;
00371          const double yang  ( atan( yy/zz ) ) ;
00372          const double lowY  ( zz>0 ? zz*tan( yang - dR ) : zz*tan( yang + dR ) ) ;
00373          const double highY ( zz>0 ? zz*tan( yang + dR ) : zz*tan( yang - dR ) ) ;
00374 
00375          const double refxlo ( 0 > rz ? m_xlo[0] : m_xlo[1] ) ;
00376          const double refxhi ( 0 > rz ? m_xhi[0] : m_xhi[1] ) ;
00377          const double refylo ( 0 > rz ? m_ylo[0] : m_ylo[1] ) ;
00378          const double refyhi ( 0 > rz ? m_yhi[0] : m_yhi[1] ) ;
00379 
00380          if( lowX  <  refxhi &&   // proceed if any possible overlap with the endcap
00381              lowY  <  refyhi &&
00382              highX >  refxlo &&
00383              highY >  refylo    )
00384          {
00385             const int ix_ctr ( xindex( xx, rz ) ) ;
00386             const int iy_ctr ( yindex( yy, rz ) ) ;
00387             const int iz     ( rz>0 ? 1 : -1 ) ;
00388             
00389             const int ix_hi  ( ix_ctr + int( ( highX - xx )/m_wref ) + 2 ) ;
00390             const int ix_lo  ( ix_ctr - int( ( xx - lowX  )/m_wref ) - 2 ) ;
00391             
00392             const int iy_hi  ( iy_ctr + int( ( highY - yy )/m_wref ) + 2 ) ;
00393             const int iy_lo  ( iy_ctr - int( ( yy - lowY  )/m_wref ) - 2 ) ;
00394             
00395             for( int kx ( ix_lo ) ; kx <= ix_hi ; ++kx ) 
00396             {
00397                if( kx >  0      && 
00398                    kx <= (int) m_nref    )
00399                {
00400                   for( int ky ( iy_lo ) ; ky <= iy_hi ; ++ky ) 
00401                   {
00402                      if( ky >  0      && 
00403                          ky <= (int) m_nref    )
00404                      {
00405                         if( EEDetId::validDetId( kx, ky, iz ) ) // reject invalid ids
00406                         {
00407                            const EEDetId id ( kx, ky, iz ) ;
00408                            const CaloCellGeometry* cell ( getGeometry( id ) );
00409                            if( 0 != cell )
00410                            {
00411                               const GlobalPoint& p    ( cell->getPosition() ) ;
00412                               const double       eta  ( p.eta() ) ;
00413                               const double       phi  ( p.phi() ) ;
00414                               if( reco::deltaR2( eta, phi, reta, rphi ) < dR2 ) dis.insert( id ) ;
00415                            }
00416                         }
00417                      }
00418                   }
00419                }
00420             }
00421          }
00422       }
00423    }
00424    return dis;
00425 }
00426 
00427 const EcalEndcapGeometry::OrderedListOfEBDetId*
00428 EcalEndcapGeometry::getClosestBarrelCells( EEDetId id ) const
00429 {
00430    OrderedListOfEBDetId* ptr ( 0 ) ;
00431    if( 0 != id.rawId() &&
00432        0 != getGeometry( id ) )
00433    {
00434       const float phi ( 370. +
00435                         getGeometry( id )->getPosition().phi().degrees() );
00436       const int iPhi ( 1 + int(phi)%360 ) ;
00437       const int iz ( id.zside() ) ;
00438       if( 0 == m_borderMgr )
00439       {
00440          m_borderMgr = new EZMgrFL<EBDetId>( 720*9, 9 ) ;
00441       }
00442       if( 0 == m_borderPtrVec )
00443       {
00444          m_borderPtrVec = new VecOrdListEBDetIdPtr() ;
00445          m_borderPtrVec->reserve( 720 ) ;
00446          for( unsigned int i ( 0 ) ; i != 720 ; ++i )
00447          {
00448             const int kz     ( 360>i ? -1 : 1 ) ;
00449             const int iEta   ( kz*85 ) ;
00450             const int iEtam1 ( kz*84 ) ;
00451             const int iEtam2 ( kz*83 ) ;
00452             const int jPhi   ( i%360 + 1 ) ;
00453             OrderedListOfEBDetId& olist ( *new OrderedListOfEBDetId( m_borderMgr ) );
00454             olist[0]=EBDetId( iEta  ,        jPhi     ) ;
00455             olist[1]=EBDetId( iEta  , myPhi( jPhi+1 ) ) ;
00456             olist[2]=EBDetId( iEta  , myPhi( jPhi-1 ) ) ;
00457             olist[3]=EBDetId( iEtam1,        jPhi     ) ;
00458             olist[4]=EBDetId( iEtam1, myPhi( jPhi+1 ) ) ;
00459             olist[5]=EBDetId( iEtam1, myPhi( jPhi-1 ) ) ;
00460             olist[6]=EBDetId( iEta  , myPhi( jPhi+2 ) ) ;
00461             olist[7]=EBDetId( iEta  , myPhi( jPhi-2 ) ) ;
00462             olist[8]=EBDetId( iEtam2,        jPhi     ) ;
00463             m_borderPtrVec->push_back( &olist ) ;
00464          }
00465       }
00466       ptr = (*m_borderPtrVec)[ ( iPhi - 1 ) + ( 0>iz ? 0 : 360 ) ] ;
00467    }
00468    return ptr ;
00469 }
00470 
00471 void
00472 EcalEndcapGeometry::localCorners( Pt3DVec&        lc  ,
00473                                   const CCGFloat* pv  ,
00474                                   unsigned int   /*i*/,
00475                                   Pt3D&           ref   )
00476 {
00477    TruncatedPyramid::localCorners( lc, pv, ref ) ;
00478 }
00479 
00480 void
00481 EcalEndcapGeometry::newCell( const GlobalPoint& f1 ,
00482                              const GlobalPoint& f2 ,
00483                              const GlobalPoint& f3 ,
00484                              const CCGFloat*    parm ,
00485                              const DetId&       detId   ) 
00486 {
00487    const unsigned int cellIndex ( EEDetId( detId ).denseIndex() ) ;
00488    m_cellVec[ cellIndex ] =
00489       TruncatedPyramid( cornersMgr(), f1, f2, f3, parm ) ;
00490    m_validIds.push_back( detId ) ;
00491 }
00492 
00493 
00494 CCGFloat 
00495 EcalEndcapGeometry::avgAbsZFrontFaceCenter() const
00496 {
00497    if( 0 > m_avgZ )
00498    {
00499       CCGFloat sum ( 0 ) ;
00500       for( unsigned int i ( 0 ) ; i != m_cellVec.size() ; ++i )
00501       {
00502          const CaloCellGeometry* cell ( cellGeomPtr(i) ) ;
00503          if( 0 != cell )
00504          {
00505             sum += fabs( cell->getPosition().z() ) ;
00506          }
00507       }
00508       m_avgZ = sum/m_cellVec.size() ;
00509    }
00510    return m_avgZ ;
00511 }
00512 
00513 const CaloCellGeometry* 
00514 EcalEndcapGeometry::cellGeomPtr( uint32_t index ) const
00515 {
00516    const CaloCellGeometry* cell ( &m_cellVec[ index ] ) ;
00517    return ( m_cellVec.size() < index ||
00518             0 == cell->param() ? 0 : cell ) ;
00519 }