00001 #include "RecoEcal/EgammaCoreTools/interface/EcalClusterTools.h"
00002
00003 #include "DataFormats/DetId/interface/DetId.h"
00004 #include "DataFormats/EcalDetId/interface/EBDetId.h"
00005 #include "DataFormats/EcalDetId/interface/EEDetId.h"
00006 #include "RecoCaloTools/Navigation/interface/CaloNavigator.h"
00007
00008 #include "FWCore/MessageLogger/interface/MessageLogger.h"
00009
00010
00011 #include "CLHEP/Geometry/Transform3D.h"
00012
00013 #include "Geometry/CaloGeometry/interface/CaloGeometry.h"
00014 #include "Geometry/CaloTopology/interface/CaloTopology.h"
00015 #include "Geometry/CaloGeometry/interface/CaloCellGeometry.h"
00016 #include "Geometry/EcalAlgo/interface/EcalBarrelGeometry.h"
00017
00018 std::pair<DetId, float> EcalClusterTools::getMaximum( const std::vector<DetId> &v_id, const EcalRecHitCollection *recHits)
00019 {
00020 float max = 0;
00021 DetId id(0);
00022 for ( size_t i = 0; i < v_id.size(); ++i ) {
00023 float energy = recHitEnergy( v_id[i], recHits );
00024 if ( energy > max ) {
00025 max = energy;
00026 id = v_id[i];
00027 }
00028 }
00029 return std::pair<DetId, float>(id, max);
00030 }
00031
00032
00033
00034 std::pair<DetId, float> EcalClusterTools::getMaximum( const reco::BasicCluster &cluster, const EcalRecHitCollection *recHits)
00035 {
00036 return getMaximum( cluster.getHitsByDetId(), recHits );
00037 }
00038
00039
00040
00041 float EcalClusterTools::recHitEnergy(DetId id, const EcalRecHitCollection *recHits)
00042 {
00043 if ( id == DetId(0) ) {
00044 return 0;
00045 } else {
00046 EcalRecHitCollection::const_iterator it = recHits->find( id );
00047 if ( it != recHits->end() ) {
00048 return (*it).energy();
00049 } else {
00050
00051
00052 return 0;
00053 }
00054 }
00055 return 0;
00056 }
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071 float EcalClusterTools::matrixEnergy( const reco::BasicCluster &cluster, const EcalRecHitCollection *recHits, const CaloTopology* topology, DetId id, int ixMin, int ixMax, int iyMin, int iyMax )
00072 {
00073
00074 CaloNavigator<DetId> cursor = CaloNavigator<DetId>( id, topology->getSubdetectorTopology( id ) );
00075 float energy = 0;
00076 for ( int i = ixMin; i <= ixMax; ++i ) {
00077 for ( int j = iyMin; j <= iyMax; ++j ) {
00078 cursor.home();
00079 cursor.offsetBy( i, j );
00080 energy += recHitEnergy( *cursor, recHits );
00081 }
00082 }
00083
00084
00085
00086
00087
00088
00089 return energy;
00090 }
00091
00092
00093
00094 std::vector<DetId> EcalClusterTools::matrixDetId( const CaloTopology* topology, DetId id, int ixMin, int ixMax, int iyMin, int iyMax )
00095 {
00096 CaloNavigator<DetId> cursor = CaloNavigator<DetId>( id, topology->getSubdetectorTopology( id ) );
00097 std::vector<DetId> v;
00098 for ( int i = ixMin; i <= ixMax; ++i ) {
00099 for ( int j = iyMin; j <= iyMax; ++j ) {
00100 cursor.home();
00101 cursor.offsetBy( i, j );
00102 if ( *cursor != DetId(0) ) v.push_back( *cursor );
00103 }
00104 }
00105 return v;
00106 }
00107
00108
00109
00110 float EcalClusterTools::e2x2( const reco::BasicCluster &cluster, const EcalRecHitCollection *recHits, const CaloTopology* topology )
00111 {
00112 DetId id = getMaximum( cluster.getHitsByDetId(), recHits ).first;
00113 std::list<float> energies;
00114 energies.push_back( matrixEnergy( cluster, recHits, topology, id, -1, 0, -1, 0 ) );
00115 energies.push_back( matrixEnergy( cluster, recHits, topology, id, -1, 0, 0, 1 ) );
00116 energies.push_back( matrixEnergy( cluster, recHits, topology, id, 0, 1, 0, 1 ) );
00117 energies.push_back( matrixEnergy( cluster, recHits, topology, id, 0, 1, -1, 0 ) );
00118 energies.sort();
00119 return *--energies.end();
00120 }
00121
00122
00123
00124 float EcalClusterTools::e3x2( const reco::BasicCluster &cluster, const EcalRecHitCollection *recHits, const CaloTopology* topology )
00125 {
00126 DetId id = getMaximum( cluster.getHitsByDetId(), recHits ).first;
00127 std::list<float> energies;
00128 energies.push_back( matrixEnergy( cluster, recHits, topology, id, -1, 1, -1, 0 ) );
00129 energies.push_back( matrixEnergy( cluster, recHits, topology, id, 0, 1, -1, 1 ) );
00130 energies.push_back( matrixEnergy( cluster, recHits, topology, id, -1, 1, 0, 1 ) );
00131 energies.push_back( matrixEnergy( cluster, recHits, topology, id, -1, 0, -1, 1 ) );
00132 energies.sort();
00133 return *--energies.end();
00134 }
00135
00136
00137
00138 float EcalClusterTools::e3x3( const reco::BasicCluster &cluster, const EcalRecHitCollection *recHits, const CaloTopology* topology )
00139 {
00140 DetId id = getMaximum( cluster.getHitsByDetId(), recHits ).first;
00141 return matrixEnergy( cluster, recHits, topology, id, -1, 1, -1, 1 );
00142 }
00143
00144
00145
00146 float EcalClusterTools::e4x4( const reco::BasicCluster &cluster, const EcalRecHitCollection *recHits, const CaloTopology* topology )
00147 {
00148 DetId id = getMaximum( cluster.getHitsByDetId(), recHits ).first;
00149 std::list<float> energies;
00150 energies.push_back( matrixEnergy( cluster, recHits, topology, id, -1, 2, -2, 1 ) );
00151 energies.push_back( matrixEnergy( cluster, recHits, topology, id, -2, 1, -2, 1 ) );
00152 energies.push_back( matrixEnergy( cluster, recHits, topology, id, -2, 1, -1, 2 ) );
00153 energies.push_back( matrixEnergy( cluster, recHits, topology, id, -1, 2, -1, 2 ) );
00154 energies.sort();
00155 return *--energies.end();
00156 }
00157
00158
00159
00160 float EcalClusterTools::e5x5( const reco::BasicCluster &cluster, const EcalRecHitCollection *recHits, const CaloTopology* topology )
00161 {
00162 DetId id = getMaximum( cluster.getHitsByDetId(), recHits ).first;
00163 return matrixEnergy( cluster, recHits, topology, id, -2, 2, -2, 2 );
00164 }
00165
00166
00167
00168 float EcalClusterTools::eMax( const reco::BasicCluster &cluster, const EcalRecHitCollection *recHits )
00169 {
00170 return getMaximum( cluster.getHitsByDetId(), recHits ).second;
00171 }
00172
00173
00174
00175 float EcalClusterTools::e2nd( const reco::BasicCluster &cluster, const EcalRecHitCollection *recHits )
00176 {
00177 std::list<float> energies;
00178 std::vector<DetId> v_id = cluster.getHitsByDetId();
00179 if ( v_id.size() < 2 ) return 0;
00180 for ( size_t i = 0; i < v_id.size(); ++i ) {
00181 energies.push_back( recHitEnergy( v_id[i], recHits ) );
00182 }
00183 energies.sort();
00184 return *--(--energies.end());
00185 }
00186
00187
00188
00189 float EcalClusterTools::e2x5Right( const reco::BasicCluster &cluster, const EcalRecHitCollection *recHits, const CaloTopology* topology )
00190 {
00191 DetId id = getMaximum( cluster.getHitsByDetId(), recHits ).first;
00192 return matrixEnergy( cluster, recHits, topology, id, 1, 2, -2, 2 );
00193 }
00194
00195
00196
00197 float EcalClusterTools::e2x5Left( const reco::BasicCluster &cluster, const EcalRecHitCollection *recHits, const CaloTopology* topology )
00198 {
00199 DetId id = getMaximum( cluster.getHitsByDetId(), recHits ).first;
00200 return matrixEnergy( cluster, recHits, topology, id, -2, -1, -2, 2 );
00201 }
00202
00203
00204
00205 float EcalClusterTools::e2x5Top( const reco::BasicCluster &cluster, const EcalRecHitCollection *recHits, const CaloTopology* topology )
00206 {
00207 DetId id = getMaximum( cluster.getHitsByDetId(), recHits ).first;
00208 return matrixEnergy( cluster, recHits, topology, id, -2, 2, 1, 2 );
00209 }
00210
00211
00212
00213 float EcalClusterTools::e2x5Bottom( const reco::BasicCluster &cluster, const EcalRecHitCollection *recHits, const CaloTopology* topology )
00214 {
00215 DetId id = getMaximum( cluster.getHitsByDetId(), recHits ).first;
00216 return matrixEnergy( cluster, recHits, topology, id, -2, 2, -2, -1 );
00217 }
00218
00219
00220
00221 float EcalClusterTools::e2x5Max( const reco::BasicCluster &cluster, const EcalRecHitCollection *recHits, const CaloTopology* topology )
00222 {
00223 DetId id = getMaximum( cluster.getHitsByDetId(), recHits ).first;
00224
00225
00226 float left = matrixEnergy( cluster, recHits, topology, id, -1, -1, -2, 2 );
00227
00228 float right = matrixEnergy( cluster, recHits, topology, id, 1, 1, -2, 2 );
00229
00230 float centre = matrixEnergy( cluster, recHits, topology, id, 0, 0, -2, 2 );
00231
00232
00233 return left > right ? left+centre : right+centre;
00234 }
00235
00236
00237 float EcalClusterTools::e1x5( const reco::BasicCluster &cluster, const EcalRecHitCollection *recHits, const CaloTopology* topology )
00238 {
00239 DetId id = getMaximum( cluster.getHitsByDetId(), recHits ).first;
00240 return matrixEnergy( cluster, recHits, topology, id, 0, 0, -2, 2 );
00241 }
00242
00243
00244
00245
00246
00247
00248
00249
00250
00251
00252
00253 float EcalClusterTools::e1x3( const reco::BasicCluster &cluster, const EcalRecHitCollection *recHits, const CaloTopology* topology )
00254 {
00255 DetId id = getMaximum( cluster.getHitsByDetId(), recHits ).first;
00256 return matrixEnergy( cluster, recHits, topology, id, 0, 0, -1, 1 );
00257 }
00258
00259
00260
00261 float EcalClusterTools::e3x1( const reco::BasicCluster &cluster, const EcalRecHitCollection *recHits, const CaloTopology* topology )
00262 {
00263 DetId id = getMaximum( cluster.getHitsByDetId(), recHits ).first;
00264 return matrixEnergy( cluster, recHits, topology, id, -1, 1, 0, 0 );
00265 }
00266
00267
00268
00269 float EcalClusterTools::eLeft( const reco::BasicCluster &cluster, const EcalRecHitCollection *recHits, const CaloTopology* topology )
00270 {
00271 DetId id = getMaximum( cluster.getHitsByDetId(), recHits ).first;
00272 return matrixEnergy( cluster, recHits, topology, id, -1, -1, 0, 0 );
00273 }
00274
00275
00276
00277 float EcalClusterTools::eRight( const reco::BasicCluster &cluster, const EcalRecHitCollection *recHits, const CaloTopology* topology )
00278 {
00279 DetId id = getMaximum( cluster.getHitsByDetId(), recHits ).first;
00280 return matrixEnergy( cluster, recHits, topology, id, 1, 1, 0, 0 );
00281 }
00282
00283
00284
00285 float EcalClusterTools::eTop( const reco::BasicCluster &cluster, const EcalRecHitCollection *recHits, const CaloTopology* topology )
00286 {
00287 DetId id = getMaximum( cluster.getHitsByDetId(), recHits ).first;
00288 return matrixEnergy( cluster, recHits, topology, id, 0, 0, 1, 1 );
00289 }
00290
00291
00292
00293 float EcalClusterTools::eBottom( const reco::BasicCluster &cluster, const EcalRecHitCollection *recHits, const CaloTopology* topology )
00294 {
00295 DetId id = getMaximum( cluster.getHitsByDetId(), recHits ).first;
00296 return matrixEnergy( cluster, recHits, topology, id, 0, 0, -1, -1 );
00297 }
00298
00299
00300
00301 std::vector<float> EcalClusterTools::energyBasketFractionEta( const reco::BasicCluster &cluster, const EcalRecHitCollection *recHits )
00302 {
00303 std::vector<float> basketFraction( 2 * EBDetId::kModulesPerSM );
00304 float clusterEnergy = cluster.energy();
00305 std::vector<DetId> v_id = cluster.getHitsByDetId();
00306 if ( v_id[0].subdetId() != EcalBarrel ) {
00307 edm::LogWarning("EcalClusterTools::energyBasketFractionEta") << "Trying to get basket fraction for endcap basic-clusters. Basket fractions can be obtained ONLY for barrel basic-clusters. Returning empty vector.";
00308 return basketFraction;
00309 }
00310 for ( size_t i = 0; i < v_id.size(); ++i ) {
00311 basketFraction[ EBDetId(v_id[i]).im()-1 + EBDetId(v_id[i]).positiveZ()*EBDetId::kModulesPerSM ] += recHitEnergy( v_id[i], recHits ) / clusterEnergy;
00312 }
00313 std::sort( basketFraction.rbegin(), basketFraction.rend() );
00314 return basketFraction;
00315 }
00316
00317
00318
00319 std::vector<float> EcalClusterTools::energyBasketFractionPhi( const reco::BasicCluster &cluster, const EcalRecHitCollection *recHits )
00320 {
00321 std::vector<float> basketFraction( 2 * (EBDetId::MAX_IPHI / EBDetId::kCrystalsInPhi) );
00322 float clusterEnergy = cluster.energy();
00323 std::vector<DetId> v_id = cluster.getHitsByDetId();
00324 if ( v_id[0].subdetId() != EcalBarrel ) {
00325 edm::LogWarning("EcalClusterTools::energyBasketFractionPhi") << "Trying to get basket fraction for endcap basic-clusters. Basket fractions can be obtained ONLY for barrel basic-clusters. Returning empty vector.";
00326 return basketFraction;
00327 }
00328 for ( size_t i = 0; i < v_id.size(); ++i ) {
00329 basketFraction[ (EBDetId(v_id[i]).iphi()-1)/EBDetId::kCrystalsInPhi + EBDetId(v_id[i]).positiveZ()*EBDetId::kTowersInPhi] += recHitEnergy( v_id[i], recHits ) / clusterEnergy;
00330 }
00331 std::sort( basketFraction.rbegin(), basketFraction.rend() );
00332 return basketFraction;
00333 }
00334
00335
00336
00337 std::vector<EcalClusterTools::EcalClusterEnergyDeposition> EcalClusterTools::getEnergyDepTopology( const reco::BasicCluster &cluster, const EcalRecHitCollection *recHits, const CaloGeometry *geometry, bool logW, float w0 )
00338 {
00339 std::vector<EcalClusterTools::EcalClusterEnergyDeposition> energyDistribution;
00340
00341
00342 CLHEP::Hep3Vector clVect(cluster.position().x(), cluster.position().y(), cluster.position().z());
00343 CLHEP::Hep3Vector clDir(clVect);
00344 clDir*=1.0/clDir.mag();
00345
00346 CLHEP::Hep3Vector theta_axis(clDir.y(),-clDir.x(),0.0);
00347 theta_axis *= 1.0/theta_axis.mag();
00348 Hep3Vector phi_axis = theta_axis.cross(clDir);
00349
00350 std::vector<DetId> clusterDetIds = cluster.getHitsByDetId();
00351
00352 EcalClusterEnergyDeposition clEdep;
00353 EcalRecHit testEcalRecHit;
00354 std::vector<DetId>::iterator posCurrent;
00355
00356 for(posCurrent=clusterDetIds.begin(); posCurrent!=clusterDetIds.end(); ++posCurrent) {
00357 EcalRecHitCollection::const_iterator itt = recHits->find(*posCurrent);
00358 testEcalRecHit=*itt;
00359
00360 if((*posCurrent != DetId(0)) && (recHits->find(*posCurrent) != recHits->end())) {
00361 clEdep.deposited_energy = testEcalRecHit.energy();
00362
00363 if(logW) {
00364
00365
00366 double weight = std::max(0.0, w0 + log(fabs(clEdep.deposited_energy)/cluster.energy()) );
00367 if(weight==0) {
00368 LogDebug("ClusterShapeAlgo") << "Crystal has insufficient energy: E = "
00369 << clEdep.deposited_energy << " GeV; skipping... ";
00370 continue;
00371 }
00372 else LogDebug("ClusterShapeAlgo") << "===> got crystal. Energy = " << clEdep.deposited_energy << " GeV. ";
00373 }
00374 DetId id_ = *posCurrent;
00375 const CaloCellGeometry *this_cell = geometry->getSubdetectorGeometry(id_)->getGeometry(id_);
00376 GlobalPoint cellPos = this_cell->getPosition();
00377 CLHEP::Hep3Vector gblPos (cellPos.x(),cellPos.y(),cellPos.z());
00378
00379 CLHEP::Hep3Vector diff = gblPos - clVect;
00380
00381
00382
00383 CLHEP::Hep3Vector DigiVect = diff - diff.dot(clDir)*clDir;
00384 clEdep.r = DigiVect.mag();
00385 LogDebug("ClusterShapeAlgo") << "E = " << clEdep.deposited_energy
00386 << "\tdiff = " << diff.mag()
00387 << "\tr = " << clEdep.r;
00388 clEdep.phi = DigiVect.angle(theta_axis);
00389 if(DigiVect.dot(phi_axis)<0) clEdep.phi = 2 * M_PI - clEdep.phi;
00390 energyDistribution.push_back(clEdep);
00391 }
00392 }
00393 return energyDistribution;
00394 }
00395
00396
00397
00398 std::vector<float> EcalClusterTools::lat( const reco::BasicCluster &cluster, const EcalRecHitCollection *recHits, const CaloGeometry *geometry, bool logW, float w0 )
00399 {
00400 std::vector<EcalClusterTools::EcalClusterEnergyDeposition> energyDistribution = getEnergyDepTopology( cluster, recHits, geometry, logW, w0 );
00401
00402 std::vector<float> lat;
00403 double r, redmoment=0;
00404 double phiRedmoment = 0 ;
00405 double etaRedmoment = 0 ;
00406 int n,n1,n2,tmp;
00407 int clusterSize=energyDistribution.size();
00408 float etaLat_, phiLat_, lat_;
00409 if (clusterSize<3) {
00410 etaLat_ = 0.0 ;
00411 lat_ = 0.0;
00412 lat.push_back(0.);
00413 lat.push_back(0.);
00414 lat.push_back(0.);
00415 return lat;
00416 }
00417
00418 n1=0; n2=1;
00419 if (energyDistribution[1].deposited_energy >
00420 energyDistribution[0].deposited_energy)
00421 {
00422 tmp=n2; n2=n1; n1=tmp;
00423 }
00424 for (int i=2; i<clusterSize; i++) {
00425 n=i;
00426 if (energyDistribution[i].deposited_energy >
00427 energyDistribution[n1].deposited_energy)
00428 {
00429 tmp = n2;
00430 n2 = n1; n1 = i; n=tmp;
00431 } else {
00432 if (energyDistribution[i].deposited_energy >
00433 energyDistribution[n2].deposited_energy)
00434 {
00435 tmp=n2; n2=i; n=tmp;
00436 }
00437 }
00438
00439 r = energyDistribution[n].r;
00440 redmoment += r*r* energyDistribution[n].deposited_energy;
00441 double rphi = r * cos (energyDistribution[n].phi) ;
00442 phiRedmoment += rphi * rphi * energyDistribution[n].deposited_energy;
00443 double reta = r * sin (energyDistribution[n].phi) ;
00444 etaRedmoment += reta * reta * energyDistribution[n].deposited_energy;
00445 }
00446 double e1 = energyDistribution[n1].deposited_energy;
00447 double e2 = energyDistribution[n2].deposited_energy;
00448
00449 lat_ = redmoment/(redmoment+2.19*2.19*(e1+e2));
00450 phiLat_ = phiRedmoment/(phiRedmoment+2.19*2.19*(e1+e2));
00451 etaLat_ = etaRedmoment/(etaRedmoment+2.19*2.19*(e1+e2));
00452
00453 lat.push_back(etaLat_);
00454 lat.push_back(phiLat_);
00455 lat.push_back(lat_);
00456 return lat;
00457 }
00458
00459
00460
00461 math::XYZVector EcalClusterTools::meanClusterPosition( const reco::BasicCluster &cluster, const EcalRecHitCollection *recHits, const CaloTopology *topology, const CaloGeometry *geometry )
00462 {
00463
00464 math::XYZVector meanPosition(0.0, 0.0, 0.0);
00465 std::vector<DetId> v_id = matrixDetId( topology, getMaximum( cluster, recHits ).first, -2, 2, -2, 2 );
00466 for ( std::vector<DetId>::const_iterator it = v_id.begin(); it != v_id.end(); ++it ) {
00467 GlobalPoint positionGP = geometry->getSubdetectorGeometry( *it )->getGeometry( *it )->getPosition();
00468 math::XYZVector position(positionGP.x(),positionGP.y(),positionGP.z());
00469 meanPosition = meanPosition + recHitEnergy( *it, recHits ) * position;
00470 }
00471 return meanPosition / e5x5( cluster, recHits, topology );
00472 }
00473
00474
00475
00476
00477 std::pair<float,float> EcalClusterTools::meanClusterPositionInCrysCoord(const reco::BasicCluster &cluster, const EcalRecHitCollection* recHits,const CaloTopology *topology)
00478 {
00479 float meanEta=0.;
00480 float meanPhi=0.;
00481
00482 std::vector<DetId> v_id = matrixDetId( topology, getMaximum( cluster, recHits ).first, -2, 2, -2, 2 );
00483 for ( std::vector<DetId>::const_iterator it = v_id.begin(); it != v_id.end(); ++it ) {
00484 float crysIEta =getIEta(*it);
00485 float crysIPhi =getIPhi(*it);
00486 meanEta = meanEta + recHitEnergy( *it, recHits ) * crysIEta;
00487 meanPhi = meanPhi + recHitEnergy( *it, recHits ) * crysIPhi;
00488 }
00489 float energy5x5 = e5x5( cluster, recHits, topology );
00490 meanEta /=energy5x5;
00491 meanPhi /=energy5x5;
00492 return std::make_pair<float,float>(meanEta,meanPhi);
00493 }
00494
00495
00496
00497 std::vector<float> EcalClusterTools::covariances(const reco::BasicCluster &cluster, const EcalRecHitCollection* recHits, const CaloTopology *topology, const CaloGeometry* geometry, float w0)
00498 {
00499 float e_5x5 = e5x5( cluster, recHits, topology );
00500 float covEtaEta, covEtaPhi, covPhiPhi;
00501 if (e_5x5 > 0.) {
00502
00503 std::vector<DetId> v_id = cluster.getHitsByDetId();
00504 math::XYZVector meanPosition = meanClusterPosition( cluster, recHits, topology, geometry );
00505
00506
00507 double numeratorEtaEta = 0;
00508 double numeratorEtaPhi = 0;
00509 double numeratorPhiPhi = 0;
00510 double denominator = 0;
00511
00512 DetId id = getMaximum( v_id, recHits ).first;
00513 CaloNavigator<DetId> cursor = CaloNavigator<DetId>( id, topology->getSubdetectorTopology( id ) );
00514 for ( int i = -2; i <= 2; ++i ) {
00515 for ( int j = -2; j <= 2; ++j ) {
00516 cursor.home();
00517 cursor.offsetBy( i, j );
00518 float energy = recHitEnergy( *cursor, recHits );
00519
00520 if ( energy <= 0 ) continue;
00521
00522 GlobalPoint position = geometry->getSubdetectorGeometry(*cursor)->getGeometry(*cursor)->getPosition();
00523
00524 double dPhi = position.phi() - meanPosition.phi();
00525 if (dPhi > + Geom::pi()) { dPhi = Geom::twoPi() - dPhi; }
00526 if (dPhi < - Geom::pi()) { dPhi = Geom::twoPi() + dPhi; }
00527
00528 double dEta = position.eta() - meanPosition.eta();
00529 double w = 0.;
00530 w = std::max(0.0, w0 + log( energy / e_5x5 ));
00531
00532 denominator += w;
00533 numeratorEtaEta += w * dEta * dEta;
00534 numeratorEtaPhi += w * dEta * dPhi;
00535 numeratorPhiPhi += w * dPhi * dPhi;
00536 }
00537 }
00538
00539 covEtaEta = numeratorEtaEta / denominator;
00540 covEtaPhi = numeratorEtaPhi / denominator;
00541 covPhiPhi = numeratorPhiPhi / denominator;
00542 } else {
00543
00544
00545 covEtaEta = 0;
00546 covEtaPhi = 0;
00547 covPhiPhi = 0;
00548 }
00549 std::vector<float> v;
00550 v.push_back( covEtaEta );
00551 v.push_back( covEtaPhi );
00552 v.push_back( covPhiPhi );
00553 return v;
00554 }
00555
00556
00557
00558
00559
00560
00561
00562
00563
00564
00565
00566 std::vector<float> EcalClusterTools::localCovariances(const reco::BasicCluster &cluster, const EcalRecHitCollection* recHits,const CaloTopology *topology,float w0)
00567 {
00568
00569
00570
00571 float e_5x5 = e5x5( cluster, recHits, topology );
00572 float covEtaEta, covEtaPhi, covPhiPhi;
00573
00574 if (e_5x5 > 0.) {
00575
00576 std::vector<DetId> v_id = cluster.getHitsByDetId();
00577 std::pair<float,float> meanEtaPhi = meanClusterPositionInCrysCoord( cluster, recHits, topology );
00578
00579
00580
00581
00582 double numeratorEtaEta = 0;
00583 double numeratorEtaPhi = 0;
00584 double numeratorPhiPhi = 0;
00585 double denominator = 0;
00586
00587
00588
00589 const double barrelCrysSize = 0.01745;
00590 const double endcapCrysSize = 0.0447;
00591
00592 DetId id = getMaximum( v_id, recHits ).first;
00593
00594 bool isBarrel=id.subdetId()==EcalBarrel;
00595
00596 const double crysSize = isBarrel ? barrelCrysSize : endcapCrysSize;
00597
00598
00599 CaloNavigator<DetId> cursor = CaloNavigator<DetId>( id, topology->getSubdetectorTopology( id ) );
00600 for ( int eastNr = -2; eastNr <= 2; ++eastNr ) {
00601 for ( int northNr = -2; northNr <= 2; ++northNr ) {
00602 cursor.home();
00603 cursor.offsetBy( eastNr, northNr);
00604 float energy = recHitEnergy( *cursor, recHits );
00605
00606
00607 if ( energy <= 0 ) continue;
00608
00609 float crysIEta = getIEta(*cursor);
00610 float crysIPhi = getIPhi(*cursor);
00611 double dEta = crysIEta - meanEtaPhi.first;
00612 double dPhi = crysIPhi - meanEtaPhi.second;
00613
00614
00615
00616 if(isBarrel){
00617 if(crysIEta*meanEtaPhi.first<0){
00618 if(crysIEta>0) dEta--;
00619 else dEta++;
00620 }
00621 }
00622 if(isBarrel){
00623 if (dPhi > + 180) { dPhi = 360 - dPhi; }
00624 if (dPhi < - 180) { dPhi = 360 + dPhi; }
00625 }
00626 double w = 0.;
00627 w = std::max(0.0, w0 + log( energy / e_5x5 ));
00628
00629 denominator += w;
00630 numeratorEtaEta += w * dEta * dEta;
00631 numeratorEtaPhi += w * dEta * dPhi;
00632 numeratorPhiPhi += w * dPhi * dPhi;
00633 }
00634 }
00635
00636 covEtaEta = crysSize*crysSize* numeratorEtaEta / denominator;
00637 covEtaPhi = crysSize*crysSize* numeratorEtaPhi / denominator;
00638 covPhiPhi = crysSize*crysSize* numeratorPhiPhi / denominator;
00639 } else {
00640
00641
00642 covEtaEta = 0;
00643 covEtaPhi = 0;
00644 covPhiPhi = 0;
00645 }
00646 std::vector<float> v;
00647 v.push_back( covEtaEta );
00648 v.push_back( covEtaPhi );
00649 v.push_back( covPhiPhi );
00650 return v;
00651 }
00652
00653 double EcalClusterTools::zernike20( const reco::BasicCluster &cluster, const EcalRecHitCollection *recHits, const CaloGeometry *geometry, double R0, bool logW, float w0 )
00654 {
00655 return absZernikeMoment( cluster, recHits, geometry, 2, 0, R0, logW, w0 );
00656 }
00657
00658
00659
00660 double EcalClusterTools::zernike42( const reco::BasicCluster &cluster, const EcalRecHitCollection *recHits, const CaloGeometry *geometry, double R0, bool logW, float w0 )
00661 {
00662 return absZernikeMoment( cluster, recHits, geometry, 4, 2, R0, logW, w0 );
00663 }
00664
00665
00666
00667 double EcalClusterTools::absZernikeMoment( const reco::BasicCluster &cluster, const EcalRecHitCollection *recHits, const CaloGeometry *geometry, int n, int m, double R0, bool logW, float w0 )
00668 {
00669
00670 if ((m>n) || ((n-m)%2 != 0) || (n<0) || (m<0)) return -1;
00671
00672
00673
00674 if ((n>20) || (R0<=2.19)) return -1;
00675 if (n<=5) return fast_AbsZernikeMoment(cluster, recHits, geometry, n, m, R0, logW, w0 );
00676 else return calc_AbsZernikeMoment(cluster, recHits, geometry, n, m, R0, logW, w0 );
00677 }
00678
00679
00680 double EcalClusterTools::fast_AbsZernikeMoment(const reco::BasicCluster &cluster, const EcalRecHitCollection *recHits, const CaloGeometry *geometry, int n, int m, double R0, bool logW, float w0 )
00681 {
00682 double r,ph,e,Re=0,Im=0;
00683 double TotalEnergy = cluster.energy();
00684 int index = (n/2)*(n/2)+(n/2)+m;
00685 std::vector<EcalClusterEnergyDeposition> energyDistribution = getEnergyDepTopology( cluster, recHits, geometry, logW, w0 );
00686 int clusterSize = energyDistribution.size();
00687 if(clusterSize < 3) return 0.0;
00688
00689 for (int i=0; i<clusterSize; i++)
00690 {
00691 r = energyDistribution[i].r / R0;
00692 if (r<1) {
00693 std::vector<double> pol;
00694 pol.push_back( f00(r) );
00695 pol.push_back( f11(r) );
00696 pol.push_back( f20(r) );
00697 pol.push_back( f22(r) );
00698 pol.push_back( f31(r) );
00699 pol.push_back( f33(r) );
00700 pol.push_back( f40(r) );
00701 pol.push_back( f42(r) );
00702 pol.push_back( f44(r) );
00703 pol.push_back( f51(r) );
00704 pol.push_back( f53(r) );
00705 pol.push_back( f55(r) );
00706 ph = (energyDistribution[i]).phi;
00707 e = energyDistribution[i].deposited_energy;
00708 Re = Re + e/TotalEnergy * pol[index] * cos( (double) m * ph);
00709 Im = Im - e/TotalEnergy * pol[index] * sin( (double) m * ph);
00710 }
00711 }
00712 return sqrt(Re*Re+Im*Im);
00713 }
00714
00715
00716
00717 double EcalClusterTools::calc_AbsZernikeMoment(const reco::BasicCluster &cluster, const EcalRecHitCollection *recHits, const CaloGeometry *geometry, int n, int m, double R0, bool logW, float w0 )
00718 {
00719 double r, ph, e, Re=0, Im=0, f_nm;
00720 double TotalEnergy = cluster.energy();
00721 std::vector<DetId> clusterDetIds = cluster.getHitsByDetId();
00722 std::vector<EcalClusterEnergyDeposition> energyDistribution = getEnergyDepTopology( cluster, recHits, geometry, logW, w0 );
00723 int clusterSize=energyDistribution.size();
00724 if(clusterSize<3) return 0.0;
00725
00726 for (int i = 0; i < clusterSize; ++i)
00727 {
00728 r = energyDistribution[i].r / R0;
00729 if (r < 1) {
00730 ph = energyDistribution[i].phi;
00731 e = energyDistribution[i].deposited_energy;
00732 f_nm = 0;
00733 for (int s=0; s<=(n-m)/2; s++) {
00734 if (s%2==0) {
00735 f_nm = f_nm + factorial(n-s)*pow(r,(double) (n-2*s))/(factorial(s)*factorial((n+m)/2-s)*factorial((n-m)/2-s));
00736 } else {
00737 f_nm = f_nm - factorial(n-s)*pow(r,(double) (n-2*s))/(factorial(s)*factorial((n+m)/2-s)*factorial((n-m)/2-s));
00738 }
00739 }
00740 Re = Re + e/TotalEnergy * f_nm * cos( (double) m*ph);
00741 Im = Im - e/TotalEnergy * f_nm * sin( (double) m*ph);
00742 }
00743 }
00744 return sqrt(Re*Re+Im*Im);
00745 }
00746
00747
00748
00749
00750
00751 float EcalClusterTools::getIEta(const DetId& id)
00752 {
00753 if(id.det()==DetId::Ecal){
00754 if(id.subdetId()==EcalBarrel){
00755 EBDetId ebId(id);
00756 return ebId.ieta();
00757 }else if(id.subdetId()==EcalEndcap){
00758 EEDetId eeId(id);
00759
00760 int iXNorm = eeId.ix()-50;
00761 if(iXNorm<=0) iXNorm--;
00762 int iYNorm = eeId.iy()-50;
00763 if(iYNorm<=0) iYNorm--;
00764
00765 return std::sqrt(iXNorm*iXNorm+iYNorm*iYNorm);
00766 }
00767 }
00768 return 0.;
00769 }
00770
00771
00772
00773
00774
00775 float EcalClusterTools::getIPhi(const DetId& id)
00776 {
00777 if(id.det()==DetId::Ecal){
00778 if(id.subdetId()==EcalBarrel){
00779 EBDetId ebId(id);
00780 return ebId.iphi();
00781 }
00782 }
00783 return 0.;
00784 }