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
00142
00143
00144
00145
00146
00147
00148
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 ) ;
00189 }
00190 else
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() ;
00208 }
00209
00210
00211
00212 DetId
00213 EcalEndcapGeometry::getClosestCell( const GlobalPoint& r ) const
00214 {
00215 try
00216 {
00217 EEDetId mycellID ( gId( r.x(), r.y(), r.z() ) ) ;
00218
00219 if( EEDetId::validDetId( mycellID.ix(),
00220 mycellID.iy(),
00221 mycellID.zside() ) )
00222 {
00223
00224
00225 Pt3D A;
00226 Pt3D B;
00227 Pt3D C;
00228 Pt3D point(r.x(),r.y(),r.z());
00229
00230
00231
00232
00233 CCGFloat x,y,z;
00234 unsigned offset=0;
00235 int zsign=1;
00236
00237 std::vector<CCGFloat> SS;
00238
00239
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
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
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 ;
00332 if( 0.000001 < dR )
00333 {
00334 if( dR > M_PI/2. )
00335 {
00336 dis = CaloSubdetectorGeometry::getCells( r, dR ) ;
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 ) ;
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 &&
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 ) )
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 }