CMS 3D CMS Logo

CMSSW_4_4_3_patch1/src/RecoEcal/EgammaClusterAlgos/src/Multi5x5ClusterAlgo.cc

Go to the documentation of this file.
00001 
00002 #include "RecoEcal/EgammaClusterAlgos/interface/Multi5x5ClusterAlgo.h"
00003 
00004 // Geometry
00005 #include "Geometry/Records/interface/IdealGeometryRecord.h"
00006 #include "Geometry/CaloGeometry/interface/CaloSubdetectorGeometry.h"
00007 #include "Geometry/CaloGeometry/interface/CaloCellGeometry.h"
00008 #include "Geometry/CaloTopology/interface/EcalEndcapTopology.h"
00009 #include "Geometry/CaloTopology/interface/EcalBarrelTopology.h"
00010 #include "RecoEcal/EgammaCoreTools/interface/ClusterEtLess.h"
00011 
00012 #include "DataFormats/CaloRecHit/interface/CaloID.h"
00013 #include "FWCore/MessageLogger/interface/MessageLogger.h"
00014 
00015 // Return a vector of clusters from a collection of EcalRecHits:
00016 //
00017 std::vector<reco::BasicCluster> Multi5x5ClusterAlgo::makeClusters(
00018                                   const EcalRecHitCollection* hits,
00019                                   const CaloSubdetectorGeometry *geometry_p,
00020                                   const CaloSubdetectorTopology *topology_p,
00021                                   const CaloSubdetectorGeometry *geometryES_p,
00022                                   reco::CaloID::Detectors detector,
00023                                   bool regional,
00024                                   const std::vector<EcalEtaPhiRegion>& regions
00025                                   )
00026 {
00027   seeds.clear();
00028   used_s.clear();
00029   canSeed_s.clear();
00030   clusters_v.clear();
00031 
00032   recHits_ = hits;
00033 
00034   double threshold = 0;
00035   std::string ecalPart_string;
00036   detector_ = reco::CaloID::DET_NONE;
00037   if (detector == reco::CaloID::DET_ECAL_ENDCAP) 
00038     {
00039       detector_ = reco::CaloID::DET_ECAL_ENDCAP;
00040       threshold = ecalEndcapSeedThreshold;
00041       ecalPart_string = "EndCap";
00042     }
00043   if (detector == reco::CaloID::DET_ECAL_BARREL) 
00044     {
00045       detector_ = reco::CaloID::DET_ECAL_BARREL;
00046       threshold = ecalBarrelSeedThreshold;
00047       ecalPart_string = "Barrel";
00048     }
00049 
00050   LogTrace("EcalClusters") << "-------------------------------------------------------------";
00051   LogTrace("EcalClusters") << "Island algorithm invoked for ECAL" << ecalPart_string ;
00052   LogTrace("EcalClusters") << "Looking for seeds, energy threshold used = " << threshold << " GeV";
00053 
00054 
00055   int nregions=0;
00056   if(regional) nregions=regions.size();
00057 
00058   if(!regional || nregions) {
00059 
00060     EcalRecHitCollection::const_iterator it;
00061     for(it = hits->begin(); it != hits->end(); it++)
00062       {
00063         double energy = it->energy();
00064         if (energy < threshold) continue; // need to check to see if this line is useful!
00065 
00066         const CaloCellGeometry *thisCell = geometry_p->getGeometry(it->id());
00067         GlobalPoint position = thisCell->getPosition();
00068 
00069         // Require that RecHit is within clustering region in case
00070         // of regional reconstruction
00071         bool withinRegion = false;
00072         if (regional) {
00073           std::vector<EcalEtaPhiRegion>::const_iterator region;
00074           for (region=regions.begin(); region!=regions.end(); region++) {
00075             if (region->inRegion(position)) {
00076               withinRegion =  true;
00077               break;
00078             }
00079           }
00080         }
00081 
00082         if (!regional || withinRegion) {
00083           float ET = it->energy() * sin(position.theta());
00084           if (ET > threshold) seeds.push_back(*it);
00085         }
00086       }
00087     
00088   }
00089   
00090    sort(seeds.begin(), seeds.end(), EcalRecHitLess());
00091 
00092    LogTrace("EcalClusters") << "Total number of seeds found in event = " << seeds.size();
00093 
00094 
00095    mainSearch(hits, geometry_p, topology_p, geometryES_p);
00096    sort(clusters_v.rbegin(), clusters_v.rend(), ClusterEtLess());
00097 
00098    LogTrace("EcalClusters") << "---------- end of main search. clusters have been sorted ----";
00099 
00100   
00101    return clusters_v;
00102  
00103 }
00104 
00105 // Search for clusters
00106 //
00107 void Multi5x5ClusterAlgo::mainSearch(const EcalRecHitCollection* hits,
00108                                      const CaloSubdetectorGeometry *geometry_p,
00109                                      const CaloSubdetectorTopology *topology_p,
00110                                      const CaloSubdetectorGeometry *geometryES_p
00111                                      )
00112 {
00113 
00114   LogTrace("EcalClusters") << "Building clusters............";
00115 
00116    // Loop over seeds:
00117    std::vector<EcalRecHit>::iterator it;
00118    for (it = seeds.begin(); it != seeds.end(); it++)
00119    {
00120 
00121       // check if this crystal is able to seed
00122       // (event though it is already used)
00123       bool usedButCanSeed = false;
00124       if (canSeed_s.find(it->id()) != canSeed_s.end()) usedButCanSeed = true;
00125 
00126       // avoid seeding for anomalous channels (recoFlag based)
00127       uint32_t rhFlag = (*it).recoFlag();
00128       std::vector<int>::const_iterator vit = std::find( v_chstatus_.begin(), v_chstatus_.end(), rhFlag );
00129       if ( vit != v_chstatus_.end() ) continue; // the recHit has to be excluded from seeding
00130 
00131       // make sure the current seed does not belong to a cluster already.
00132       if ((used_s.find(it->id()) != used_s.end()) && (usedButCanSeed == false))
00133       {
00134          if (it == seeds.begin())
00135          {
00136            LogTrace("EcalClusters") << "##############################################################" ;
00137            LogTrace("EcalClusters") << "DEBUG ALERT: Highest energy seed already belongs to a cluster!";
00138            LogTrace("EcalClusters") << "##############################################################";
00139 
00140          }
00141 
00142           // seed crystal is used or is used and cannot seed a cluster
00143           // so continue to the next seed crystal...
00144           continue;
00145       }
00146 
00147       // clear the vector of hits in current cluster
00148       current_v.clear();
00149 
00150       // Create a navigator at the seed and get seed
00151       // energy
00152       CaloNavigator<DetId> navigator(it->id(), topology_p);
00153       DetId seedId = navigator.pos();
00154       EcalRecHitCollection::const_iterator seedIt = hits->find(seedId);
00155       navigator.setHome(seedId);
00156 
00157       // Is the seed a local maximum?
00158       bool localMaxima = checkMaxima(navigator, hits);
00159 
00160       if (localMaxima)
00161       {
00162          // build the 5x5 taking care over which crystals
00163          // can seed new clusters and which can't
00164          prepareCluster(navigator, hits, geometry_p);
00165       }
00166 
00167       // If some crystals in the current vector then 
00168       // make them into a cluster 
00169       if (current_v.size() > 0) 
00170       {
00171          makeCluster(hits, geometry_p, geometryES_p, seedIt);
00172       }
00173 
00174    }  // End loop on seed crystals
00175 
00176 }
00177 
00178 void Multi5x5ClusterAlgo::makeCluster(const EcalRecHitCollection* hits,
00179                                     const CaloSubdetectorGeometry *geometry,
00180                                     const CaloSubdetectorGeometry *geometryES,
00181                                     const EcalRecHitCollection::const_iterator &seedIt)
00182 {
00183 
00184    double energy = 0;
00185    //double chi2   = 0;
00186    reco::CaloID caloID;
00187    Point position;
00188    position = posCalculator_.Calculate_Location(current_v, hits,geometry, geometryES);
00189   
00190    std::vector<std::pair<DetId, float> >::iterator it;
00191    for (it = current_v.begin(); it != current_v.end(); it++)
00192    {
00193       EcalRecHitCollection::const_iterator itt = hits->find( (*it).first );
00194       EcalRecHit hit_p = *itt;
00195       energy += hit_p.energy();
00196       //chi2 += 0;
00197       if ( (*it).first.subdetId() == EcalBarrel ) {
00198               caloID = reco::CaloID::DET_ECAL_BARREL;
00199       } else {
00200               caloID = reco::CaloID::DET_ECAL_ENDCAP;
00201       }
00202 
00203    }
00204    //chi2 /= energy;
00205 
00206    LogTrace("EcalClusters") << "******** NEW CLUSTER ********";
00207    LogTrace("EcalClusters") << "No. of crystals = " << current_v.size();
00208    LogTrace("EcalClusters") << "     Energy     = " << energy ;
00209    LogTrace("EcalClusters") << "     Phi        = " << position.phi();
00210    LogTrace("EcalClusters") << "     Eta " << position.eta();
00211    LogTrace("EcalClusters") << "*****************************";  
00212 
00213 
00214    // to be a valid cluster the cluster energy
00215    // must be at least the seed energy
00216    double seedEnergy = seedIt->energy();
00217    if (energy >= seedEnergy)
00218    {
00219       //clusters_v.push_back(reco::BasicCluster(energy, position, chi2, current_v, reco::CaloCluster::island));
00220       clusters_v.push_back(reco::BasicCluster(energy, position, reco::CaloID(detector_), current_v, reco::CaloCluster::multi5x5, seedIt->id()));
00221    }
00222 
00223 }
00224 
00225 bool Multi5x5ClusterAlgo::checkMaxima(CaloNavigator<DetId> &navigator,
00226                                       const EcalRecHitCollection *hits)
00227 {
00228 
00229    bool maxima = true;
00230    EcalRecHitCollection::const_iterator thisHit;
00231    EcalRecHitCollection::const_iterator seedHit = hits->find(navigator.pos());
00232    double seedEnergy = seedHit->energy();
00233 
00234    std::vector<DetId> swissCrossVec;
00235    swissCrossVec.clear();
00236 
00237    swissCrossVec.push_back(navigator.west());
00238    navigator.home();
00239    swissCrossVec.push_back(navigator.east());
00240    navigator.home();
00241    swissCrossVec.push_back(navigator.north());
00242    navigator.home();
00243    swissCrossVec.push_back(navigator.south());
00244    navigator.home();
00245 
00246    std::vector<DetId>::const_iterator detItr;
00247    for (unsigned int i = 0; i < swissCrossVec.size(); ++i)
00248    {
00249 
00250       // look for this hit
00251       thisHit = recHits_->find(swissCrossVec[i]);
00252 
00253       // continue if this hit was not found
00254       if  ((swissCrossVec[i] == DetId(0)) || thisHit == recHits_->end()) continue; 
00255 
00256       // the recHit has to be skipped in the local maximum search if it was found
00257       // in the map of channels to be excluded 
00258       uint32_t rhFlag = thisHit->recoFlag();
00259       std::vector<int>::const_iterator vit = std::find(v_chstatus_.begin(), v_chstatus_.end(), rhFlag);
00260       if (vit != v_chstatus_.end()) continue;
00261 
00262       // if this crystal has more energy than the seed then we do 
00263       // not have a local maxima
00264       if (thisHit->energy() > seedEnergy)
00265       {
00266          maxima = false;
00267          break;
00268       }
00269    }
00270 
00271    return maxima;
00272 
00273 }
00274 
00275 void Multi5x5ClusterAlgo::prepareCluster(CaloNavigator<DetId> &navigator, 
00276                 const EcalRecHitCollection *hits, 
00277                 const CaloSubdetectorGeometry *geometry)
00278 {
00279 
00280    DetId thisDet;
00281    std::set<DetId>::iterator setItr;
00282 
00283    // now add the 5x5 taking care to mark the edges
00284    // as able to seed and where overlapping in the central
00285    // region with crystals that were previously able to seed
00286    // change their status so they are not able to seed
00287    //std::cout << std::endl;
00288    for (int dx = -2; dx < 3; ++dx)
00289    {
00290       for (int dy = -2; dy < 3; ++ dy)
00291       {
00292 
00293           // navigate in free steps forming
00294           // a full 5x5
00295           thisDet = navigator.offsetBy(dx, dy);
00296           navigator.home();
00297 
00298           // add the current crystal
00299           //std::cout << "adding " << dx << ", " << dy << std::endl;
00300           addCrystal(thisDet);
00301 
00302           // now consider if we are in an edge (outer 16)
00303           // or central (inner 9) region
00304           if ((abs(dx) > 1) || (abs(dy) > 1))
00305           {    
00306              // this is an "edge" so should be allowed to seed
00307              // provided it is not already used
00308              //std::cout << "   setting can seed" << std::endl;
00309              canSeed_s.insert(thisDet);
00310           }  // end if "edge"
00311           else 
00312           {
00313              // or else we are in the central 3x3
00314              // and must remove any of these crystals from the canSeed set
00315              setItr = canSeed_s.find(thisDet);
00316              if (setItr != canSeed_s.end())
00317              {
00318                 //std::cout << "   unsetting can seed" << std::endl;
00319                 canSeed_s.erase(setItr);
00320              }
00321           }  // end if "centre"
00322 
00323 
00324       } // end loop on dy
00325 
00326    } // end loop on dx
00327 
00328    //std::cout << "*** " << std::endl;
00329    //std::cout << " current_v contains " << current_v.size() << std::endl;
00330    //std::cout << "*** " << std::endl;
00331 }
00332 
00333 
00334 void Multi5x5ClusterAlgo::addCrystal(const DetId &det)
00335 {   
00336 
00337    EcalRecHitCollection::const_iterator thisIt =  recHits_->find(det);
00338    if ((thisIt != recHits_->end()) && (thisIt->id() != DetId(0)))
00339    { 
00340       if ((used_s.find(thisIt->id()) == used_s.end())) 
00341       {
00342          //std::cout << "   ... this is a good crystal and will be added" << std::endl;
00343          current_v.push_back( std::pair<DetId, float>(det, 1.) ); // by default hit energy fractions are set at 1.
00344          used_s.insert(det);
00345       }
00346    } 
00347   
00348 }
00349