CMS 3D CMS Logo

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