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& )
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))->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
00112 constexpr CCGFloat twopi = M_PI+M_PI;
00113
00114 constexpr CCGFloat tilt=twopi/36.;
00115
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 CCGFloat history[4]{0.f};
00150
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 CCGFloat SS[4];
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[i] = 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 std::copy(SS,SS+4,history);
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 constexpr int maxphi ( EBDetId::MAX_IPHI ) ;
00297 constexpr int maxeta ( EBDetId::MAX_IETA ) ;
00298 constexpr float scale( maxphi/(2*M_PI) ) ;
00299
00300 CaloSubdetectorGeometry::DetIdSet dis;
00301
00302 if( 0.000001 < dR )
00303 {
00304 if( dR > M_PI/2. )
00305 {
00306 dis = CaloSubdetectorGeometry::getCells( r, dR ) ;
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 )
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 ) ) ;
00323
00324 const float fr ( dR*scale ) ;
00325 const float frp ( 1.08f*fr + 1.f ) ;
00326 const float frm ( 0.92f*fr - 1.f ) ;
00327 const int idr ( (int)frp ) ;
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 )
00332 {
00333 int ieta ( de + ieta_center ) ;
00334
00335 if( std::abs(ieta) <= maxeta &&
00336 ieta != 0 )
00337 {
00338 const int de2 ( de*de ) ;
00339 for( int dp ( -idr ) ; dp <= idr ; ++dp )
00340 {
00341 const int irange2 ( dp*dp + de2 ) ;
00342
00343 if( irange2 <= idr2p )
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 ) ;
00352
00353 if( !ok )
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
00384
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 }