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& )
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
00159
00160
00161
00162
00163
00164
00165
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 ) ;
00206 }
00207 else
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() ;
00225 }
00226
00227
00228
00229 DetId
00230 EcalEndcapGeometry::getClosestCell( const GlobalPoint& r ) const
00231 {
00232 try
00233 {
00234 EEDetId mycellID ( gId( r.x(), r.y(), r.z() ) ) ;
00235
00236 if( EEDetId::validDetId( mycellID.ix(),
00237 mycellID.iy(),
00238 mycellID.zside() ) )
00239 {
00240
00241
00242 Pt3D A;
00243 Pt3D B;
00244 Pt3D C;
00245 Pt3D point(r.x(),r.y(),r.z());
00246
00247
00248
00249
00250 CCGFloat x,y,z;
00251 unsigned offset=0;
00252 int zsign=1;
00253
00254 std::vector<CCGFloat> SS;
00255
00256
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
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
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 ;
00349 if( 0.000001 < dR )
00350 {
00351 if( dR > M_PI/2. )
00352 {
00353 dis = CaloSubdetectorGeometry::getCells( r, dR ) ;
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 ) ;
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 &&
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 ) )
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 ,
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 }