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[0], &neba[3] ) ;
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& )
00061 {
00062 return (unsigned int)DetId::Ecal - 1 ;
00063 }
00064
00065 DetId
00066 EcalBarrelGeometry::getClosestCell(const GlobalPoint& r) const
00067 {
00068
00069
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
00078 CCGFloat pointeta = r.eta();
00079
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))->getPosition().eta();
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
00112 const CCGFloat twopi = M_PI+M_PI;
00113
00114
00115 const CCGFloat tilt=twopi/36.;
00116 CCGFloat pointphi = r.phi()+tilt;
00117
00118
00119 if(pointphi > twopi)
00120 pointphi -= twopi;
00121 if(pointphi < 0)
00122 pointphi += twopi;
00123
00124
00125 int phibin = static_cast<int>(pointphi / (twopi/_nnxtalPhi)) + 1;
00126
00127
00128
00129
00130
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
00145
00146
00147
00148
00149 std::vector<CCGFloat> history;
00150 history.resize(4,0.);
00151
00152
00153 int start = 1;
00154 int counter = 0;
00155
00156 while (leverx==1 || levery == 1)
00157 {
00158 leverx = 0;
00159 levery = 0;
00160 const CaloCellGeometry::CornersVec& corners
00161 ( getGeometry(myCell)->getCorners() ) ;
00162 std::vector<CCGFloat> SS;
00163
00164
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.push_back(distance);
00176 }
00177
00178
00179
00180
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
00272
00273 history =SS;
00274
00275 counter++;
00276 if (counter == 10)
00277 {
00278 leverx=0;
00279 levery=0;
00280 }
00281 }
00282
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 static const int maxphi ( EBDetId::MAX_IPHI ) ;
00297 static const int maxeta ( EBDetId::MAX_IETA ) ;
00298 CaloSubdetectorGeometry::DetIdSet dis;
00299
00300 if( 0.000001 < dR )
00301 {
00302 if( dR > M_PI/2. )
00303 {
00304 dis = CaloSubdetectorGeometry::getCells( r, dR ) ;
00305 }
00306 else
00307 {
00308 const double dR2 ( dR*dR ) ;
00309 const double reta ( r.eta() ) ;
00310 const double rz ( r.z() ) ;
00311 const double rphi ( r.phi() ) ;
00312 const double lowEta ( reta - dR ) ;
00313 const double highEta ( reta + dR ) ;
00314
00315 if( highEta > -1.5 &&
00316 lowEta < 1.5 )
00317 {
00318 const double scale ( maxphi/(2*M_PI) ) ;
00319 const int ieta_center ( int( reta*scale + ((rz<0)?(-1):(1))) ) ;
00320 const double phi ( rphi<0 ? rphi + 2*M_PI : rphi ) ;
00321 const int iphi_center ( int( phi*scale + 11. ) ) ;
00322
00323 const double fr ( dR*scale ) ;
00324 const double frp ( 1.08*fr + 1. ) ;
00325 const double frm ( 0.92*fr - 1. ) ;
00326 const int idr ( (int)frp ) ;
00327 const int idr2p ( (int)(frp*frp) ) ;
00328 const int idr2m ( frm > 0 ? int(frm*frm) : 0 ) ;
00329
00330 for( int de ( -idr ) ; de <= idr ; ++de )
00331 {
00332 int ieta ( de + ieta_center ) ;
00333
00334 if( std::abs(ieta) <= maxeta &&
00335 ieta != 0 )
00336 {
00337 const int de2 ( de*de ) ;
00338 for( int dp ( -idr ) ; dp <= idr ; ++dp )
00339 {
00340 const int irange2 ( dp*dp + de2 ) ;
00341
00342 if( irange2 <= idr2p )
00343 {
00344 const int iphi ( ( iphi_center + dp + maxphi - 1 )%maxphi + 1 ) ;
00345
00346 if( iphi != 0 )
00347 {
00348 const EBDetId id ( ieta, iphi ) ;
00349
00350 bool ok ( irange2 < idr2m ) ;
00351
00352 if( !ok )
00353 {
00354 const CaloCellGeometry* cell ( getGeometry( id ) );
00355 if( 0 != cell )
00356 {
00357 const GlobalPoint& p ( cell->getPosition() ) ;
00358 const double eta ( p.eta() ) ;
00359 const double phi ( p.phi() ) ;
00360 ok = ( reco::deltaR2( eta, phi, reta, rphi ) < dR2 ) ;
00361 }
00362 }
00363 if( ok ) dis.insert( id ) ;
00364 }
00365 }
00366 }
00367 }
00368 }
00369 }
00370 }
00371 }
00372 return dis;
00373 }
00374
00375 const EcalBarrelGeometry::OrderedListOfEEDetId*
00376 EcalBarrelGeometry::getClosestEndcapCells( EBDetId id ) const
00377 {
00378 OrderedListOfEEDetId* ptr ( 0 ) ;
00379 if( 0 != id.rawId() )
00380 {
00381 const int iPhi ( id.iphi() ) ;
00382
00383 const int iz ( id.ieta()>0 ? 1 : -1 ) ;
00384 const EEDetId eeid ( EEDetId::idOuterRing( iPhi, iz ) ) ;
00385
00386
00387
00388
00389 const int iq ( eeid.iquadrant() ) ;
00390 const int xout ( 1==iq || 4==iq ? 1 : -1 ) ;
00391 const int yout ( 1==iq || 2==iq ? 1 : -1 ) ;
00392 if( 0 == m_borderMgr )
00393 {
00394 m_borderMgr = new EZMgrFL<EEDetId>( 720*9, 9 ) ;
00395 }
00396 if( 0 == m_borderPtrVec )
00397 {
00398 m_borderPtrVec = new VecOrdListEEDetIdPtr() ;
00399 m_borderPtrVec->reserve( 720 ) ;
00400 for( unsigned int i ( 0 ) ; i != 720 ; ++i )
00401 {
00402 const int kz ( 360>i ? -1 : 1 ) ;
00403 const EEDetId eeid ( EEDetId::idOuterRing( i%360+1, kz ) ) ;
00404
00405 const int jx ( eeid.ix() ) ;
00406 const int jy ( eeid.iy() ) ;
00407
00408 OrderedListOfEEDetId& olist ( *new OrderedListOfEEDetId( m_borderMgr ) );
00409 int il ( 0 ) ;
00410
00411 for( unsigned int k ( 1 ) ; k <= 25 ; ++k )
00412 {
00413 const int kx ( 1==k || 2==k || 3==k || 12==k || 13==k ? 0 :
00414 ( 4==k || 6==k || 8==k || 15==k || 20==k ? 1 :
00415 ( 5==k || 7==k || 9==k || 16==k || 19==k ? -1 :
00416 ( 10==k || 14==k || 21==k || 22==k || 25==k ? 2 : -2 )))) ;
00417 const int ky ( 1==k || 4==k || 5==k || 10==k || 11==k ? 0 :
00418 ( 2==k || 6==k || 7==k || 14==k || 17==k ? 1 :
00419 ( 3==k || 8==k || 9==k || 18==k || 21==k ? -1 :
00420 ( 12==k || 15==k || 16==k || 22==k || 23==k ? 2 : -2 )))) ;
00421
00422 if( 8>=il && EEDetId::validDetId( jx + kx*xout ,
00423 jy + ky*yout , kz ) )
00424 {
00425 olist[il++]=EEDetId( jx + kx*xout ,
00426 jy + ky*yout , kz ) ;
00427 }
00428 }
00429 m_borderPtrVec->push_back( &olist ) ;
00430 }
00431 }
00432 ptr = (*m_borderPtrVec)[ iPhi - 1 + ( 0>iz ? 0 : 360 ) ] ;
00433 }
00434 return ptr ;
00435 }
00436
00437 void
00438 EcalBarrelGeometry::localCorners( Pt3DVec& lc ,
00439 const CCGFloat* pv ,
00440 unsigned int i ,
00441 Pt3D& ref )
00442 {
00443 const bool negz ( EBDetId::kSizeForDenseIndexing/2 > i ) ;
00444 const bool odd ( 1 == i%2 ) ;
00445
00446 if( ( ( negz && !odd ) ||
00447 ( !negz && odd ) ) )
00448 {
00449 TruncatedPyramid::localCornersReflection( lc, pv, ref ) ;
00450 }
00451 else
00452 {
00453 TruncatedPyramid::localCornersSwap( lc, pv, ref ) ;
00454 }
00455 }
00456
00457 void
00458 EcalBarrelGeometry::newCell( const GlobalPoint& f1 ,
00459 const GlobalPoint& f2 ,
00460 const GlobalPoint& f3 ,
00461 const CCGFloat* parm ,
00462 const DetId& detId )
00463 {
00464 const unsigned int cellIndex ( EBDetId( detId ).denseIndex() ) ;
00465 m_cellVec[ cellIndex ] =
00466 TruncatedPyramid( cornersMgr(), f1, f2, f3, parm ) ;
00467 m_validIds.push_back( detId ) ;
00468 }
00469
00470 CCGFloat
00471 EcalBarrelGeometry::avgRadiusXYFrontFaceCenter() const
00472 {
00473 if( 0 > m_radius )
00474 {
00475 CCGFloat sum ( 0 ) ;
00476 for( uint32_t i ( 0 ) ; i != m_cellVec.size() ; ++i )
00477 {
00478 const CaloCellGeometry* cell ( cellGeomPtr(i) ) ;
00479 if( 0 != cell )
00480 {
00481 const GlobalPoint& pos ( cell->getPosition() ) ;
00482 sum += pos.perp() ;
00483 }
00484 }
00485 m_radius = sum/m_cellVec.size() ;
00486 }
00487 return m_radius ;
00488 }
00489
00490 const CaloCellGeometry*
00491 EcalBarrelGeometry::cellGeomPtr( uint32_t index ) const
00492 {
00493 const CaloCellGeometry* cell ( &m_cellVec[ index ] ) ;
00494 return ( m_cellVec.size() < index ||
00495 0 == cell->param() ? 0 : cell ) ;
00496 }