CMS 3D CMS Logo

/data/refman/pasoursint/CMSSW_6_1_2_SLHC2/src/Geometry/EcalAlgo/src/EcalBarrelGeometry.cc

Go to the documentation of this file.
00001 #include "Geometry/CaloGeometry/interface/CaloGenericDetId.h"
00002 #include "Geometry/CaloGeometry/interface/TruncatedPyramid.h"
00003 #include "Geometry/EcalAlgo/interface/EcalBarrelGeometry.h"
00004 #include "Geometry/CaloGeometry/interface/CaloCellGeometry.h"
00005 #include "FWCore/Utilities/interface/Exception.h"
00006 #include "DataFormats/EcalDetId/interface/EBDetId.h"
00007 
00008 #include <CLHEP/Geometry/Point3D.h>
00009 #include <CLHEP/Geometry/Plane3D.h>
00010 #include <CLHEP/Geometry/Vector3D.h>
00011 
00012 #include <iomanip>
00013 #include <iostream>
00014 
00015 typedef CaloCellGeometry::CCGFloat CCGFloat ;
00016 typedef CaloCellGeometry::Pt3D     Pt3D     ;
00017 typedef CaloCellGeometry::Pt3DVec  Pt3DVec  ;
00018 typedef HepGeom::Plane3D<CCGFloat> Pl3D     ;
00019 
00020 EcalBarrelGeometry::EcalBarrelGeometry() :
00021    _nnxtalEta     ( 85 ) ,
00022    _nnxtalPhi     ( 360 ) ,
00023    _PhiBaskets    ( 18 ) ,
00024    m_borderMgr    ( 0 ),
00025    m_borderPtrVec ( 0 ) ,
00026    m_radius       ( -1. ),
00027    m_cellVec      ( k_NumberOfCellsForCorners )
00028 {
00029    const int neba[] = {25,45,65,85} ;
00030    _EtaBaskets = std::vector<int>( neba, neba+4 ) ;
00031 }
00032 
00033 
00034 EcalBarrelGeometry::~EcalBarrelGeometry() 
00035 {
00036    delete m_borderPtrVec ;
00037    delete m_borderMgr ;
00038 }
00039 
00040 
00041 unsigned int
00042 EcalBarrelGeometry::alignmentTransformIndexLocal( const DetId& id )
00043 {
00044    const CaloGenericDetId gid ( id ) ;
00045 
00046    assert( gid.isEB() ) ;
00047 
00048    unsigned int index ( EBDetId(id).ism() - 1 ) ;
00049 
00050    return index ;
00051 }
00052 
00053 DetId 
00054 EcalBarrelGeometry::detIdFromLocalAlignmentIndex( unsigned int iLoc )
00055 {
00056    return EBDetId( iLoc + 1, 1, EBDetId::SMCRYSTALMODE ) ;
00057 }
00058 
00059 unsigned int
00060 EcalBarrelGeometry::alignmentTransformIndexGlobal( const DetId& /*id*/ )
00061 {
00062    return (unsigned int)DetId::Ecal - 1 ;
00063 }
00064 // Get closest cell, etc...
00065 DetId 
00066 EcalBarrelGeometry::getClosestCell(const GlobalPoint& r) const 
00067 {
00068 
00069   // z is the easy one
00070   int leverx = 1;
00071   int levery = 1;
00072   CCGFloat pointz = r.z();
00073   int zbin=1;
00074   if(pointz<0)
00075     zbin=-1;
00076 
00077   // Now find the closest eta
00078   CCGFloat pointeta = r.eta();
00079   //  double eta;
00080   CCGFloat deta=999.;
00081   int etabin=1;
00082   
00083   int guessed_eta = (int)( fabs(pointeta) / 0.0174)+1;
00084   int guessed_eta_begin = guessed_eta-1;
00085   int guessed_eta_end   = guessed_eta+1;
00086   if (guessed_eta_begin < 1) guessed_eta_begin = 1;
00087   if (guessed_eta_end > 85) guessed_eta_end = 85;
00088 
00089     for(int bin=guessed_eta_begin; bin<= guessed_eta_end; bin++)
00090       {
00091         try
00092           {
00093             if (!present(EBDetId(zbin*bin,1,EBDetId::ETAPHIMODE)))
00094               continue;
00095 
00096             CCGFloat eta = getGeometry(EBDetId(zbin*bin,1,EBDetId::ETAPHIMODE))->etaPos();
00097 
00098             if(fabs(pointeta-eta)<deta)
00099               {
00100                 deta=fabs(pointeta-eta);
00101                 etabin=bin;
00102               }
00103             else break;
00104           }
00105         catch ( cms::Exception &e ) 
00106           {
00107           }
00108       }
00109     
00110 
00111   // Now the closest phi. always same number of phi bins(!?)
00112   constexpr CCGFloat twopi = M_PI+M_PI;
00113   // 10 degree tilt
00114   constexpr CCGFloat tilt=twopi/36.;
00115 
00116   CCGFloat pointphi = r.phi()+tilt;
00117 
00118   // put phi in correct range (0->2pi)
00119   if(pointphi > twopi)
00120     pointphi -= twopi;
00121   if(pointphi < 0)
00122     pointphi += twopi;
00123 
00124   //calculate phi bin, distinguish + and - eta
00125   int phibin = static_cast<int>(pointphi / (twopi/_nnxtalPhi)) + 1;
00126   //   if(point.z()<0.0)
00127   //     {
00128   //       phibin = nxtalPhi/2 - 1 - phibin;
00129   //       if(phibin<0)
00130   //         phibin += nxtalPhi;
00131   //     }
00132   try
00133     {
00134       EBDetId myCell(zbin*etabin,phibin,EBDetId::ETAPHIMODE);
00135 
00136       if (!present(myCell))
00137         return DetId(0);
00138       
00139       Pt3D A;
00140       Pt3D B;
00141       Pt3D C;
00142       Pt3D point(r.x(),r.y(),r.z());
00143 
00144       // D.K. : equation of plane : AA*x+BB*y+CC*z+DD=0;
00145       // finding equation for each edge
00146 
00147       // Since the point can lie between crystals, it is necessary to keep track of the movements
00148       // to avoid infinite loops
00149       CCGFloat history[4]{0.f};
00150 
00151       //
00152       // stop movement in eta direction when closest cell was found (point between crystals)
00153       int start = 1;
00154       int counter = 0;
00155       // Moving until find closest crystal in eta and phi directions (leverx and levery)
00156       while  (leverx==1 || levery == 1)
00157         {
00158           leverx = 0;
00159           levery = 0;
00160           const CaloCellGeometry::CornersVec& corners 
00161              ( getGeometry(myCell)->getCorners() ) ;
00162           CCGFloat SS[4];
00163 
00164           // compute the distance of the point with respect of the 4 crystal lateral planes
00165           for (short i=0; i < 4 ; ++i)
00166             {
00167               A = Pt3D(corners[i%4].x(),corners[i%4].y(),corners[i%4].z());
00168               B = Pt3D(corners[(i+1)%4].x(),corners[(i+1)%4].y(),corners[(i+1)%4].z());
00169               C = Pt3D(corners[4+(i+1)%4].x(),corners[4+(i+1)%4].y(),corners[4+(i+1)%4].z());
00170               Pl3D plane(A,B,C);
00171               plane.normalize();
00172               CCGFloat distance = plane.distance(point);
00173               if(plane.d()>0.) distance=-distance;
00174               if (corners[0].z()<0.) distance=-distance;
00175               SS[i] = distance;
00176             }
00177 
00178           // SS's - normals
00179           // check position of the point with respect to opposite side of crystal
00180           // if SS's have opposite sign, the  point lies inside that crystal
00181 
00182           if ( ( SS[0]>0.&&SS[2]>0. )||( SS[0]<0.&&SS[2]<0. ) )
00183             {
00184               levery = 1;
00185               if ( history[0]>0. && history[2]>0. && SS[0]<0 && SS[2]<0 &&
00186                    (fabs(SS[0])+fabs(SS[2]))> (fabs(history[0])+fabs(history[2]))) levery = 0  ;
00187               if ( history[0]<0. && history[2]<0. && SS[0]>0 && SS[2]>0 &&
00188                    (fabs(SS[0])+fabs(SS[2]))> (fabs(history[0])+fabs(history[2]))) levery = 0  ;
00189 
00190 
00191               if (SS[0]>0. )
00192                 {
00193                   EBDetId nextPoint;
00194                   if (myCell.iphi()==EBDetId::MIN_IPHI) 
00195                     nextPoint=EBDetId(myCell.ieta(),EBDetId::MAX_IPHI);
00196                   else 
00197                     nextPoint=EBDetId(myCell.ieta(),myCell.iphi()-1);
00198                   if (present(nextPoint))
00199                     myCell=nextPoint;
00200                   else
00201                     levery=0;             
00202                 }
00203               else
00204                 {
00205                   EBDetId nextPoint;
00206                   if (myCell.iphi()==EBDetId::MAX_IPHI)
00207                     nextPoint=EBDetId(myCell.ieta(),EBDetId::MIN_IPHI);
00208                   else
00209                     nextPoint=EBDetId(myCell.ieta(),myCell.iphi()+1);
00210                   if (present(nextPoint))
00211                     myCell=nextPoint;
00212                   else
00213                     levery=0;
00214                 }
00215             }
00216 
00217 
00218           if ( ( ( SS[1]>0.&&SS[3]>0. )||( SS[1]<0.&&SS[3]<0. )) && start==1  )
00219             {
00220               leverx = 1;
00221 
00222               if ( history[1]>0. && history[3]>0. && SS[1]<0 && SS[3]<0 &&
00223                    (fabs(SS[1])+fabs(SS[3]))> (fabs(history[1])+fabs(history[3])) )
00224                 {
00225                   leverx = 0;
00226                   start = 0;
00227                 }
00228 
00229               if ( history[1]<0. && history[3]<0. && SS[1]>0 && SS[3]>0 &&
00230                    (fabs(SS[1])+fabs(SS[3]))> (fabs(history[1])+fabs(history[3])) )
00231                 {
00232                   leverx = 0;
00233                   start = 0;
00234                 }
00235 
00236 
00237               if (SS[1]>0.)
00238                 {
00239                   EBDetId nextPoint;
00240                   if (myCell.ieta()==-1) 
00241                     nextPoint=EBDetId (1,myCell.iphi());
00242                   else 
00243                     {
00244                       int nieta= myCell.ieta()+1;
00245                       if(nieta==86) nieta=85;
00246                       nextPoint=EBDetId(nieta,myCell.iphi());
00247                     }
00248                   if (present(nextPoint))
00249                     myCell = nextPoint;
00250                   else
00251                     leverx = 0;
00252                 }
00253               else
00254                 {
00255                   EBDetId nextPoint;
00256                   if (myCell.ieta()==1) 
00257                     nextPoint=EBDetId(-1,myCell.iphi());
00258                   else 
00259                     {
00260                       int nieta=myCell.ieta()-1;
00261                       if(nieta==-86) nieta=-85;
00262                       nextPoint=EBDetId(nieta,myCell.iphi());
00263                     }
00264                   if (present(nextPoint))
00265                     myCell = nextPoint;
00266                   else
00267                     leverx = 0;
00268                 }
00269             }
00270           
00271           // Update the history. If the point lies between crystals, the closest one
00272           // is returned
00273           std::copy(SS,SS+4,history);
00274           
00275           counter++;
00276           if (counter == 10)
00277             {
00278               leverx=0;
00279               levery=0;
00280             }
00281         }
00282       // D.K. if point lies netween cells, take a closest cell.
00283       return DetId(myCell);
00284     }
00285   catch ( cms::Exception &e ) 
00286     { 
00287       return DetId(0);
00288     }
00289 
00290 }
00291 
00292 CaloSubdetectorGeometry::DetIdSet 
00293 EcalBarrelGeometry::getCells( const GlobalPoint& r, 
00294                               double             dR ) const 
00295 {
00296    constexpr int maxphi ( EBDetId::MAX_IPHI ) ;
00297    constexpr int maxeta ( EBDetId::MAX_IETA ) ;
00298    constexpr float scale( maxphi/(2*M_PI) ) ; // angle to index
00299 
00300    CaloSubdetectorGeometry::DetIdSet dis;  // this is the return object
00301 
00302    if( 0.000001 < dR )
00303    {
00304       if( dR > M_PI/2. ) // this version needs "small" dR
00305       {
00306          dis = CaloSubdetectorGeometry::getCells( r, dR ) ; // base class version
00307       }
00308       else
00309       {
00310          const float dR2     ( dR*dR ) ;
00311          const float reta    ( r.eta() ) ;
00312          const float rz      ( r.z()   ) ;
00313          const float rphi    ( r.phi() ) ;
00314          const float lowEta  ( reta - dR ) ;
00315          const float highEta ( reta + dR ) ;
00316          
00317          if( highEta > -1.5 &&
00318              lowEta  <  1.5    ) // in barrel
00319          {
00320            const int    ieta_center ( int( reta*scale + ((rz<0)?(-1):(1))) ) ;
00321            const float phi         ( rphi<0 ? rphi + float(2*M_PI) : rphi ) ;
00322            const int    iphi_center ( int( phi*scale + 11.f ) ) ; // phi=-9.4deg is iphi=1
00323 
00324            const float fr    ( dR*scale    ) ; // # crystal widths in dR
00325            const float frp   ( 1.08f*fr + 1.f ) ; // conservatively above fr 
00326            const float frm   ( 0.92f*fr - 1.f ) ; // conservatively below fr
00327            const int    idr   ( (int)frp        ) ; // integerize
00328            const int    idr2p ( (int)(frp*frp)     ) ;
00329            const int    idr2m ( frm > 0 ? int(frm*frm) : 0 ) ;
00330            
00331            for( int de ( -idr ) ; de <= idr ; ++de ) // over eta limits
00332              {
00333                int ieta ( de + ieta_center ) ;
00334                
00335                if( std::abs(ieta) <= maxeta &&
00336                    ieta      != 0         ) // eta is in EB
00337                  {
00338                    const int de2 ( de*de ) ;
00339                    for( int dp ( -idr ) ; dp <= idr ; ++dp )  // over phi limits
00340                      {
00341                        const int irange2 ( dp*dp + de2 ) ;
00342                        
00343                        if( irange2 <= idr2p ) // cut off corners that must be too far away
00344                          {
00345                            const int iphi ( ( iphi_center + dp + maxphi - 1 )%maxphi + 1 ) ;
00346                            
00347                            if( iphi != 0 )
00348                              {
00349                                const EBDetId id ( ieta, iphi ) ;
00350                                
00351                                bool ok ( irange2 < idr2m ) ;  // no more calculation necessary if inside this radius
00352                            
00353                                if( !ok ) // if not ok, then we have to test this cell for being inside cone
00354                                  {
00355                                    const CaloCellGeometry* cell  = &m_cellVec[ id.denseIndex()];
00356                                    const float       eta ( cell->etaPos() ) ;
00357                                    const float       phi ( cell->phiPos() ) ;
00358                                    ok = ( reco::deltaR2( eta, phi, reta, rphi ) < dR2 ) ;
00359                            }
00360                                if( ok ) dis.insert( id ) ;
00361                              }
00362                          }
00363                      }
00364                  }
00365              }
00366          }
00367       }
00368    }
00369    return dis;
00370 }
00371 
00372 const EcalBarrelGeometry::OrderedListOfEEDetId* 
00373 EcalBarrelGeometry::getClosestEndcapCells( EBDetId id ) const
00374 {
00375    OrderedListOfEEDetId* ptr ( 0 ) ;
00376    if( 0 != id.rawId() )
00377    {
00378       const int iPhi     ( id.iphi() ) ;
00379 
00380       const int iz       ( id.ieta()>0 ? 1 : -1 ) ;
00381       const EEDetId eeid ( EEDetId::idOuterRing( iPhi, iz ) ) ;
00382 
00383 //      const int ix ( eeid.ix() ) ;
00384 //      const int iy ( eeid.iy() ) ;
00385 
00386       const int iq ( eeid.iquadrant() ) ;
00387       const int xout ( 1==iq || 4==iq ? 1 : -1 ) ;
00388       const int yout ( 1==iq || 2==iq ? 1 : -1 ) ;
00389       if( 0 == m_borderMgr )
00390       {
00391          m_borderMgr = new EZMgrFL<EEDetId>( 720*9, 9 ) ;
00392       }
00393       if( 0 == m_borderPtrVec )
00394       {
00395          m_borderPtrVec = new VecOrdListEEDetIdPtr() ;
00396          m_borderPtrVec->reserve( 720 ) ;
00397          for( unsigned int i ( 0 ) ; i != 720 ; ++i )
00398          {
00399             const int kz ( 360>i ? -1 : 1 ) ;
00400             const EEDetId eeid ( EEDetId::idOuterRing( i%360+1, kz ) ) ;
00401 
00402             const int jx ( eeid.ix() ) ;
00403             const int jy ( eeid.iy() ) ;
00404 
00405             OrderedListOfEEDetId& olist ( *new OrderedListOfEEDetId( m_borderMgr ) );
00406             int il ( 0 ) ;
00407 
00408             for( unsigned int k ( 1 ) ; k <= 25 ; ++k )
00409             {
00410                const int kx ( 1==k || 2==k || 3==k || 12==k || 13==k ? 0 :
00411                               ( 4==k || 6==k || 8==k || 15==k || 20==k ? 1 :
00412                                 ( 5==k || 7==k || 9==k || 16==k || 19==k ? -1 :
00413                                   ( 10==k || 14==k || 21==k || 22==k || 25==k ? 2 : -2 )))) ;
00414                const int ky ( 1==k || 4==k || 5==k || 10==k || 11==k ? 0 :
00415                               ( 2==k || 6==k || 7==k || 14==k || 17==k ? 1 :
00416                                 ( 3==k || 8==k || 9==k || 18==k || 21==k ? -1 :
00417                                   ( 12==k || 15==k || 16==k || 22==k || 23==k ? 2 : -2 )))) ;
00418 
00419                if( 8>=il && EEDetId::validDetId( jx + kx*xout ,
00420                                                  jy + ky*yout , kz ) ) 
00421                {
00422                   olist[il++]=EEDetId( jx + kx*xout ,
00423                                        jy + ky*yout , kz ) ;
00424                }
00425             }
00426             m_borderPtrVec->push_back( &olist ) ;
00427          }
00428       }
00429       ptr = (*m_borderPtrVec)[ iPhi - 1 + ( 0>iz ? 0 : 360 ) ] ;
00430    }
00431    return ptr ;
00432 }
00433 
00434 void
00435 EcalBarrelGeometry::localCorners( Pt3DVec&        lc  ,
00436                                   const CCGFloat* pv  , 
00437                                   unsigned int    i   ,
00438                                   Pt3D&           ref   )
00439 {
00440    const bool negz ( EBDetId::kSizeForDenseIndexing/2 >  i ) ;
00441    const bool odd  ( 1 == i%2 ) ;
00442 
00443    if( ( ( negz  && !odd ) ||
00444          ( !negz && odd  )    ) )
00445    {
00446       TruncatedPyramid::localCornersReflection( lc, pv, ref ) ;
00447    }
00448    else
00449    {
00450       TruncatedPyramid::localCornersSwap( lc, pv, ref ) ;
00451    }
00452 }
00453 
00454 void
00455 EcalBarrelGeometry::newCell( const GlobalPoint& f1 ,
00456                              const GlobalPoint& f2 ,
00457                              const GlobalPoint& f3 ,
00458                              const CCGFloat*    parm ,
00459                              const DetId&       detId   ) 
00460 {
00461    const unsigned int cellIndex ( EBDetId( detId ).denseIndex() ) ;
00462    m_cellVec[ cellIndex ] =
00463       TruncatedPyramid( cornersMgr(), f1, f2, f3, parm ) ;
00464    m_validIds.push_back( detId ) ;
00465 }
00466 
00467 CCGFloat 
00468 EcalBarrelGeometry::avgRadiusXYFrontFaceCenter() const 
00469 {
00470    if( 0 > m_radius )
00471    {
00472       CCGFloat sum ( 0 ) ;
00473       for( uint32_t i ( 0 ) ; i != m_cellVec.size() ; ++i )
00474       {
00475          const CaloCellGeometry* cell ( cellGeomPtr(i) ) ;
00476          if( 0 != cell )
00477          {
00478             const GlobalPoint& pos ( cell->getPosition() ) ;
00479             sum += pos.perp() ;
00480          }
00481       }
00482       m_radius = sum/m_cellVec.size() ;
00483    }
00484    return m_radius ;
00485 }
00486 
00487 const CaloCellGeometry* 
00488 EcalBarrelGeometry::cellGeomPtr( uint32_t index ) const
00489 {
00490    const CaloCellGeometry* cell ( &m_cellVec[ index ] ) ;
00491    return ( m_cellVec.size() < index ||
00492             0 == cell->param() ? 0 : cell ) ;
00493 }