CMS 3D CMS Logo

/data/refman/pasoursint/CMSSW_6_1_2_SLHC4_patch1/src/RecoEcal/EgammaClusterAlgos/src/CosmicClusterAlgo.cc

Go to the documentation of this file.
00001 
00002 #include "RecoEcal/EgammaClusterAlgos/interface/CosmicClusterAlgo.h"
00003 
00004 #include <vector> //TEMP JHAUPT 4-27
00005 
00006 // Geometry
00007 #include "Geometry/Records/interface/CaloGeometryRecord.h"
00008 #include "Geometry/CaloGeometry/interface/CaloSubdetectorGeometry.h"
00009 #include "Geometry/CaloGeometry/interface/CaloCellGeometry.h"
00010 #include "Geometry/CaloTopology/interface/EcalEndcapTopology.h"
00011 #include "Geometry/CaloTopology/interface/EcalBarrelTopology.h"
00012 
00013 #include "RecoEcal/EgammaCoreTools/interface/ClusterEtLess.h"
00014 
00015 
00016 // Return a vector of clusters from a collection of EcalRecHits:
00017 //
00018 std::vector<reco::BasicCluster> CosmicClusterAlgo::makeClusters(
00019                                   const EcalRecHitCollection* hits,
00020                                   const EcalUncalibratedRecHitCollection *uncalibhits,                            
00021                                   const CaloSubdetectorGeometry *geometry_p,
00022                                   const CaloSubdetectorTopology *topology_p,
00023                                   const CaloSubdetectorGeometry *geometryES_p,
00024                                   EcalPart ecalPart,
00025                                   bool regional,
00026                                   const std::vector<EcalEtaPhiRegion>& regions)
00027 {
00028   seeds.clear();
00029   used_s.clear();
00030   canSeed_s.clear();
00031   clusters_v.clear();
00032 
00033   recHits_ = hits;
00034   uncalibRecHits_ = uncalibhits;
00035   
00036   inEB = true;
00037   double threshold = 0;
00038   std::string ecalPart_string;
00039   if (ecalPart == endcap) 
00040     {
00041       threshold = ecalEndcapSeedThreshold;
00042       ecalPart_string = "EndCap";
00043           inEB = false;
00044     }
00045   if (ecalPart == barrel) 
00046     {
00047       threshold = ecalBarrelSeedThreshold;
00048       ecalPart_string = "Barrel";
00049           inEB = true;
00050     }
00051 
00052   if (verbosity < pINFO)
00053     {
00054       std::cout << "-------------------------------------------------------------" << std::endl;
00055       std::cout << "Island algorithm invoked for ECAL" << ecalPart_string << std::endl;
00056       std::cout << "Looking for seeds, threshold used = " << threshold << " ADC" <<std::endl;
00057     }
00058 
00059   int nregions=0;
00060   if(regional) nregions=regions.size();
00061 
00062   if(!regional || nregions) {
00063 
00064     EcalRecHitCollection::const_iterator it;
00065     for(it = recHits_->begin(); it != recHits_->end(); it++)
00066       {   
00067           
00068           if (!uncalibRecHits_){  
00069              if (verbosity < pINFO)
00070          {
00071             std::cout << "-------------------------------------------------------------" << std::endl;
00072             std::cout << "No Uncalibrated RecHits no Uncalibrated rec hit collection available" << std::endl;
00073          }
00074          continue;
00075           }
00076   
00077           // if rechit affected by features other than these, do not allow if seeding
00078           // features are hard coded, for now; add severity?
00079           uint32_t rhFlag = (*it).recoFlag();
00080           if (!(
00081                 rhFlag == EcalRecHit::kGood      ||
00082                 rhFlag == EcalRecHit::kOutOfTime ||
00083                 rhFlag == EcalRecHit::kPoorCalib
00084                 )
00085               ) continue;
00086 
00087           EcalUncalibratedRecHitCollection::const_iterator itt =  uncalibRecHits_->find(it->id());
00088           
00089           if (itt == uncalibRecHits_->end()){  
00090              if (verbosity < pINFO)
00091          {
00092             std::cout << "-------------------------------------------------------------" << std::endl;
00093             std::cout << "No Uncalibrated RecHit associated with the RecHit Probably no Uncalibrated rec hit collection available" << std::endl;
00094                  }
00095              continue;
00096           }
00097           
00098       EcalUncalibratedRecHit uhit_p = *itt;
00099 
00100       // looking for cluster seeds        
00101           if (uhit_p.amplitude() <  (inEB ? ecalBarrelSeedThreshold : ecalEndcapSeedThreshold) ) continue; // 
00102           
00103           const CaloCellGeometry *thisCell = geometry_p->getGeometry(it->id());
00104           GlobalPoint position = thisCell->getPosition();
00105 
00106         // Require that RecHit is within clustering region in case
00107         // of regional reconstruction
00108         bool withinRegion = false;
00109         if (regional) {
00110           std::vector<EcalEtaPhiRegion>::const_iterator region;
00111           for (region=regions.begin(); region!=regions.end(); region++) {
00112             if (region->inRegion(position)) {
00113               withinRegion =  true;
00114               break;
00115             }
00116           }
00117         }
00118 
00119         if (!regional || withinRegion) {
00120           //float ET = it->energy() * sin(position.theta()); JHaupt Out 4-27-08 Et not needed for Cosmic Events...
00121          // if (energy >= threshold) 
00122           seeds.push_back(*it); // JHaupt 4-27-2008 Et -> energy, most likely not needed as there is already a threshold requirement.
00123         }
00124       }
00125     
00126   }
00127   
00128    sort(seeds.begin(), seeds.end(), EcalRecHitLess());
00129 
00130    if (verbosity < pINFO)
00131    {
00132       std::cout << "JH Total number of seeds found in event = " << seeds.size() << std::endl;
00133           for (EcalRecHitCollection::const_iterator ji = seeds.begin(); ji != seeds.end(); ++ji)
00134           {
00135               //std::cout << "JH Seed Energy " << ji->energy() << " hashed " << ((EBDetId)ji->id()).hashedIndex()  << std::endl;
00136 
00137           }
00138    }
00139 
00140    mainSearch(geometry_p,topology_p,geometryES_p,ecalPart );
00141    sort(clusters_v.rbegin(), clusters_v.rend(),ClusterEtLess());
00142          
00143    if (verbosity < pINFO)
00144    {
00145       std::cout << "---------- end of main search. clusters have been sorted ----" << std::endl;
00146    }
00147   
00148    return clusters_v;
00149  
00150 }
00151 
00152 // Search for clusters
00153 //
00154 void CosmicClusterAlgo::mainSearch(      const CaloSubdetectorGeometry *geometry_p,
00155                    const CaloSubdetectorTopology *topology_p,
00156                    const CaloSubdetectorGeometry *geometryES_p,
00157                    EcalPart ecalPart )
00158 {
00159 
00160    if (verbosity < pINFO)
00161    {
00162       std::cout << "Building clusters............" << std::endl;
00163    }
00164      
00165   // Loop over seeds:
00166    std::vector<EcalRecHit>::iterator it;
00167    for (it = seeds.begin(); it != seeds.end(); it++)
00168    {
00169 
00170       // check if this crystal is able to seed
00171       // (event though it is already used)
00172       bool usedButCanSeed = false;
00173       if (canSeed_s.find(it->id()) != canSeed_s.end()) usedButCanSeed = true;
00174 
00175       // make sure the current seed does not belong to a cluster already.
00176       if ((used_s.find(it->id()) != used_s.end()) && (usedButCanSeed == false))
00177       {
00178          if (it == seeds.begin())
00179          {
00180             if (verbosity < pINFO)
00181             {
00182            std::cout << "##############################################################" << std::endl;
00183                std::cout << "DEBUG ALERT: Highest energy seed already belongs to a cluster!" << std::endl;
00184                std::cout << "##############################################################" << std::endl;
00185             }
00186          }
00187 
00188           // seed crystal is used or is used and cannot seed a cluster
00189           // so continue to the next seed crystal...
00190           continue;
00191       }
00192 
00193       // clear the vector of hits in current clusterconst EcalRecHitCollection* hits,
00194       current_v9.clear();
00195       current_v25.clear();
00196       current_v25Sup.clear();
00197 
00198       // Create a navigator at the seed
00199       CaloNavigator<DetId> navigator(it->id(), topology_p);
00200       DetId seedId = navigator.pos();
00201       navigator.setHome(seedId);
00202 
00203       // Is the seed a local maximum?
00204       bool localMaxima = checkMaxima(navigator);
00205 
00206       if (localMaxima)
00207       {
00208          // build the 5x5 taking care over which crystals //JHaupt 4-27-08 3x3 is a good option...
00209          // can seed new clusters and which can't
00210          prepareCluster(navigator, geometry_p);
00211       }
00212 
00213       // If some crystals in the current vector then 
00214       // make them into a cluster 
00215       if (current_v25.size() > 0) 
00216       {
00217         makeCluster(geometry_p, geometryES_p, seedId);
00218       }
00219 
00220    }  // End loop on seed crystals
00221 
00222 }
00223 
00224 void CosmicClusterAlgo::makeCluster(
00225                                     const CaloSubdetectorGeometry *geometry,
00226                                     const CaloSubdetectorGeometry *geometryES,
00227                                         DetId seedId)
00228 {
00229 
00230    double energy = 0;
00231    double energySecond = 0.;//JHaupt 4-27-08 Added for the second crystal stream
00232    double energyMax = 0.;//JHaupt 4-27-08 Added for the max crystal stream
00233    double chi2   = 0;
00234    DetId detFir;
00235    DetId detSec;
00236    //bool goodCluster = false; //JHaupt 4-27-08 Added so that some can be earased.. used another day Might not be needed as seeds are energy ordered... 
00237    
00238    
00239    std::vector<DetId>::iterator it;
00240    for (it = current_v9.begin(); it != current_v9.end(); it++)
00241    {
00242      // Martina - check recoFlag for crystals sorrounding the good one 
00243      EcalRecHitCollection::const_iterator itt = recHits_->find(*it);
00244      // double-check that iterator can be dereferenced   
00245      if(itt==recHits_->end()) continue; 
00246      // if rechit affected by features other than these, do not allow 2 crystal seeding either
00247      // features are hard coded, for now; add severity?
00248      uint32_t rhFlag = (*itt).recoFlag();
00249      if (!(
00250            rhFlag == EcalRecHit::kGood      ||
00251            rhFlag == EcalRecHit::kOutOfTime ||
00252            rhFlag == EcalRecHit::kPoorCalib
00253            )
00254          ) continue;
00255      
00257 
00258       EcalUncalibratedRecHitCollection::const_iterator ittu = uncalibRecHits_->find(*it);
00259       EcalUncalibratedRecHit uhit_p = *ittu;
00260           
00261           if (uhit_p.amplitude() > energySecond ) {energySecond = uhit_p.amplitude(); detSec = uhit_p.id();}
00262           if (energySecond > energyMax ) {std::swap(energySecond,energyMax); std::swap(detFir,detSec);}
00263    }
00264    
00265    //if ((detFir.det() == DetId::Ecal) && (detFir.subdetId() == EcalEndcap)) inEB = false;
00266    //We ignore the possiblity that the cluster may span into the EE    
00267 
00268    if ((energyMax < (inEB ? ecalBarrelSingleThreshold : ecalEndcapSingleThreshold)) && (energySecond < (inEB ? ecalBarrelSecondThreshold : ecalEndcapSecondThreshold) )) return;
00269    
00270    for (it = current_v25.begin(); it != current_v25.end(); it++)
00271    {
00272       EcalRecHitCollection::const_iterator itt = recHits_->find(*it);
00273       EcalRecHit hit_p = *itt;
00274           
00275           EcalUncalibratedRecHitCollection::const_iterator ittu = uncalibRecHits_->find(*it);
00276       EcalUncalibratedRecHit uhit_p = *ittu;
00277           
00278       if ( uhit_p.amplitude() > ( inEB ? ecalBarrelSupThreshold : ecalEndcapSupThreshold)) 
00279       {  
00280          // energy fraction = 1
00281          current_v25Sup.push_back( std::pair<DetId, float>( hit_p.id(), 1.) );
00282          energy += hit_p.energy(); //Keep the fully corrected energy 
00283          chi2 += 0;
00284       }     
00285    }
00286    
00287    Point position;
00288    position = posCalculator_.Calculate_Location(current_v25Sup,recHits_, geometry, geometryES);
00289    
00290    //don't write empty clusters
00291    if (energy == 0 && position == Point(0,0,0)) return;
00292 
00293    chi2 /= energy;
00294    if (verbosity < pINFO)
00295    { 
00296       std::cout << "JH******** NEW CLUSTER ********" << std::endl;
00297       std::cout << "JHNo. of crystals = " << current_v25Sup.size() << std::endl;
00298       std::cout << "JH     Energy     = " << energy << std::endl;
00299       std::cout << "JH     Phi        = " << position.phi() << std::endl;
00300       std::cout << "JH     Eta        = " << position.eta() << std::endl;
00301       std::cout << "JH*****************************" << std::endl;
00302       // specialize this
00303 //       std::cout << "JH****Emax****  "<<energyMax << " ieta " <<detFir.ieta() <<" iphi "<<detFir.ieta()  << std::endl;
00304 //       std::cout << "JH****Esec****  "<<energySecond << " ieta " <<detSec.ieta() <<" iphi "<<detSec.ieta() << std::endl;
00305     }
00306    clusters_v.push_back(reco::BasicCluster(energy, position, reco::CaloID(), current_v25Sup, reco::CaloCluster::multi5x5, seedId));
00307 }
00308 
00309 bool CosmicClusterAlgo::checkMaxima(CaloNavigator<DetId> &navigator)
00310 {
00311 
00312    bool maxima = true;
00313    EcalRecHitCollection::const_iterator thisHit;
00314    EcalRecHitCollection::const_iterator seedHit = recHits_->find(navigator.pos());
00315    double thisEnergy = 0.;
00316    double seedEnergy = seedHit->energy();
00317 
00318    std::vector<DetId> swissCrossVec;
00319    swissCrossVec.clear();
00320 
00321    swissCrossVec.push_back(navigator.west());
00322    navigator.home();
00323    swissCrossVec.push_back(navigator.east());
00324    navigator.home();
00325    swissCrossVec.push_back(navigator.north());
00326    navigator.home();
00327    swissCrossVec.push_back(navigator.south());
00328    navigator.home();
00329 
00330    std::vector<DetId>::const_iterator detItr;
00331    for (unsigned int i = 0; i < swissCrossVec.size(); ++i)
00332    {
00333       thisHit = recHits_->find(swissCrossVec[i]);
00334       if  ((swissCrossVec[i] == DetId(0)) || thisHit == recHits_->end()) thisEnergy = 0.0;
00335       else thisEnergy = thisHit->energy();
00336       if (thisEnergy > seedEnergy)
00337       {
00338          maxima = false;
00339          break;
00340       }
00341    }
00342 
00343    return maxima;
00344 
00345 }
00346 
00347 void CosmicClusterAlgo::prepareCluster(CaloNavigator<DetId> &navigator,  
00348                 const CaloSubdetectorGeometry *geometry)
00349 {
00350 
00351    DetId thisDet;
00352    std::set<DetId>::iterator setItr;
00353 
00354    // now add the 5x5 taking care to mark the edges
00355    // as able to seed and where overlapping in the central
00356    // region with crystals that were previously able to seed
00357    // change their status so they are not able to seed
00358    //std::cout << std::endl;
00359    for (int dx = -2; dx < 3; ++dx) //for (int dx = -2; dx < 3; ++dx)
00360    {
00361       for (int dy = -2; dy < 3; ++ dy) //for (int dy = -2; dy < 3; ++ dy)
00362       {
00363 
00364           // navigate in free steps forming
00365           // a full 5x5
00366           thisDet = navigator.offsetBy(dx, dy);
00367           navigator.home();
00368 
00369           // add the current crystal
00370           //std::cout << "adding " << dx << ", " << dy << std::endl;
00371          
00372 
00373 
00374           // now consider if we are in an edge (outer 16)
00375           // or central (inner 9) region
00376           if ((abs(dx) > 1) || (abs(dy) > 1))
00377           {    
00378              // this is an "edge" so should be allowed to seed
00379              // provided it is not already used
00380              //std::cout << "   setting can seed" << std::endl;
00381                          addCrystal(thisDet,false); //These are in the V25
00382              canSeed_s.insert(thisDet);
00383           }  // end if "edge"
00384           else 
00385           {
00386              // or else we are in the central 3x3
00387              // and must remove any of these crystals from the canSeed set
00388              setItr = canSeed_s.find(thisDet);
00389                          addCrystal(thisDet,true); //These are in the V9
00390              if (setItr != canSeed_s.end())
00391              {
00392                 //std::cout << "   unsetting can seed" << std::endl;
00393                 canSeed_s.erase(setItr);
00394              }
00395           }  // end if "centre"
00396 
00397 
00398       } // end loop on dy
00399 
00400    } // end loop on dx
00401 
00402    //std::cout << "*** " << std::endl;
00403    //std::cout << " current_v contains " << current_v.size() << std::endl;
00404    //std::cout << "*** " << std::endl;
00405 }
00406 
00407 
00408 void CosmicClusterAlgo::addCrystal(const DetId &det, const bool in9)
00409 {   
00410     
00411     EcalRecHitCollection::const_iterator thisIt =  recHits_->find(det);
00412     if ((thisIt != recHits_->end()) && (thisIt->id() != DetId(0)))
00413     { 
00414         if ((used_s.find(thisIt->id()) == used_s.end())) 
00415         {
00416                     EcalUncalibratedRecHitCollection::const_iterator thisItu =  uncalibRecHits_->find(det);
00417             used_s.insert(det);
00418             if ((thisIt->energy() >= -1.) && !(thisItu->chi2() < -1.))
00419             {           
00420                if (in9)  current_v9.push_back(det);
00421                    current_v25.push_back(det);
00422             }
00423             
00424         }
00425     } 
00426    
00427 }