CMS 3D CMS Logo

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