CMS 3D CMS Logo

EcalClusterTools.cc

Go to the documentation of this file.
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                         //throw cms::Exception("EcalRecHitNotFound") << "The recHit corresponding to the DetId" << id.rawId() << " not found in the EcalRecHitCollection";
00051                         // the recHit is not in the collection (hopefully zero suppressed)
00052                         return 0;
00053                 }
00054         }
00055         return 0;
00056 }
00057 
00058 
00059 // Returns the energy in a rectangle of crystals
00060 // specified in eta by ixMin and ixMax
00061 //       and in phi by iyMin and iyMax
00062 //
00063 // Reference picture (X=seed crystal)
00064 //    iy ___________
00065 //     2 |_|_|_|_|_|
00066 //     1 |_|_|_|_|_|
00067 //     0 |_|_|X|_|_|
00068 //    -1 |_|_|_|_|_|
00069 //    -2 |_|_|_|_|_|
00070 //      -2 -1 0 1 2 ix
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         // fast version
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         // slow elegant version
00084         //float energy = 0;
00085         //std::vector<DetId> v_id = matrixDetId( topology, id, ixMin, ixMax, iyMin, iyMax );
00086         //for ( std::vector<DetId>::const_iterator it = v_id.begin(); it != v_id.end(); ++it ) {
00087         //        energy += recHitEnergy( *it, recHits );
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 // Energy in 2x5 strip containing the max crystal.
00220 // Adapted from code by Sam Harper
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   // 1x5 strip left of seed
00226   float left   = matrixEnergy( cluster, recHits, topology, id, -1, -1, -2, 2 );
00227   // 1x5 strip right of seed
00228   float right  = matrixEnergy( cluster, recHits, topology, id,  1,  1, -2, 2 );
00229   // 1x5 strip containing seed
00230   float centre = matrixEnergy( cluster, recHits, topology, id,  0,  0, -2, 2 );
00231 
00232   // Return the maximum of (left+center) or (right+center) strip
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 // float EcalClusterTools::e5x1( const reco::BasicCluster &cluster, const EcalRecHitCollection *recHits, const CaloTopology* topology )
00246 // {
00247 //         DetId id = getMaximum( cluster.getHitsByDetId(), recHits ).first;
00248 //         return matrixEnergy( cluster, recHits, topology, id, -2, 2, 0, 0 );
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         // init a map of the energy deposition centered on the
00341         // cluster centroid. This is for momenta calculation only.
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         // in the transverse plane, axis perpendicular to clusterDir
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         // loop over crystals
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                         // if logarithmic weight is requested, apply cut on minimum energy of the recHit
00363                         if(logW) {
00364                                 //double w0 = parameterMap_.find("W0")->second;
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()); //surface position?
00378                         // Evaluate the distance from the cluster centroid
00379                         CLHEP::Hep3Vector diff = gblPos - clVect;
00380                         // Important: for the moment calculation, only the "lateral distance" is important
00381                         // "lateral distance" r_i = distance of the digi position from the axis Origin-Cluster Center
00382                         // ---> subtract the projection on clDir
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         // find mean energy position of a 5x5 cluster around the maximum
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 //returns mean energy weighted eta/phi in crystal coordinates
00475 //iPhi is not defined for endcap and is returned as zero
00476 //return <eta,phi>
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                 //double w0_ = parameterMap_.find("W0")->second;
00503                 std::vector<DetId> v_id = cluster.getHitsByDetId();
00504                 math::XYZVector meanPosition = meanClusterPosition( cluster, recHits, topology, geometry );
00505 
00506                 // now we can calculate the covariances
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                 // Warn the user if there was no energy in the cells and return zeroes.
00544                 //       std::cout << "\ClusterShapeAlgo::Calculate_Covariances:  no energy in supplied cells.\n";
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 //for the barrel, covIEtaIEta,covIEtaIPhi and covIPhiIPhi are defined but only covIEtaIEta has been actively studied
00562 //for the endcap, only covIEtaIEta is defined, covIEtaIPhi and covIPhiIPhi are zeroed
00563 //instead of using absolute eta/phi it counts crystals normalised so that it gives identical results to normal covariances except near the cracks where of course its better 
00564 //it also does not require any eta correction function in the endcap
00565 //it is multipled by an approprate crystal size to ensure it gives similar values to covariances(...)
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                 //double w0_ = parameterMap_.find("W0")->second;
00576                 std::vector<DetId> v_id = cluster.getHitsByDetId();
00577                 std::pair<float,float> meanEtaPhi =  meanClusterPositionInCrysCoord( cluster, recHits, topology );
00578         
00579         
00580 
00581                 // now we can calculate the covariances
00582                 double numeratorEtaEta = 0;
00583                 double numeratorEtaPhi = 0;
00584                 double numeratorPhiPhi = 0;
00585                 double denominator     = 0;
00586 
00587                 //these allow us to scale the localCov by the crystal size 
00588                 //so that the localCovs have the same average value as the normal covs
00589                 const double barrelCrysSize = 0.01745; //approximate size of crystal in eta,phi in barrel
00590                 const double endcapCrysSize = 0.0447; //the approximate crystal size sigmaEtaEta was corrected to in the endcap
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 ) { //east is eta in barrel
00601                   for ( int northNr = -2; northNr <= 2; ++northNr ) { //north is phi in barrel
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                                 //no iEta=0 in barrel, so if go from positive to negative
00615                                 //need to reduce abs(detEta) by 1
00616                                 if(isBarrel){ 
00617                                   if(crysIEta*meanEtaPhi.first<0){ // -1 to 1 transition
00618                                     if(crysIEta>0) dEta--;
00619                                     else dEta++;
00620                                   }
00621                                 }
00622                                 if(isBarrel){ //if barrel, need to map into 0-180 
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                 //multiplying by crysSize to make the values compariable to normal covariances
00636                 covEtaEta =  crysSize*crysSize* numeratorEtaEta / denominator;
00637                 covEtaPhi =  crysSize*crysSize* numeratorEtaPhi / denominator;
00638                 covPhiPhi =  crysSize*crysSize* numeratorPhiPhi / denominator;
00639         } else {
00640                 // Warn the user if there was no energy in the cells and return zeroes.
00641                 //       std::cout << "\ClusterShapeAlgo::Calculate_Covariances:  no energy in supplied cells.\n";
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         // 1. Check if n,m are correctly
00670         if ((m>n) || ((n-m)%2 != 0) || (n<0) || (m<0)) return -1;
00671 
00672         // 2. Check if n,R0 are within validity Range :
00673         // n>20 or R0<2.19cm  just makes no sense !
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 //returns the crystal 'eta' from the det id
00748 //it is defined as the number of crystals from the centre in the eta direction
00749 //for the barrel with its eta/phi geometry it is always integer
00750 //for the endcap it is fractional due to the x/y geometry
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       //want to map 1=-50,50=-1,51=1 and 100 to 50 so sub off one if zero or neg
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 //returns the crystal 'phi' from the det id
00772 //it is defined as the number of crystals from the centre in the phi direction
00773 //for the barrel with its eta/phi geometry it is always integer
00774 //for the endcap it is not defined 
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 }

Generated on Tue Jun 9 17:43:16 2009 for CMSSW by  doxygen 1.5.4