CMS 3D CMS Logo

CMSSW_4_4_3_patch1/src/RecoLocalCalo/CaloTowersCreator/src/CaloTowersMerger.cc

Go to the documentation of this file.
00001 // -*- C++ -*-
00002 //
00003 // Package:    CaloTowersMerger
00004 // Class:      CaloTowersMerger
00005 // 
00013 //
00014 // Original Author:  Jean-Roch Vlimant,40 3-A28,+41227671209,
00015 //         Created:  Thu Nov  4 16:36:30 CET 2010
00016 // $Id: CaloTowersMerger.cc,v 1.2 2010/11/24 19:52:16 anastass Exp $
00017 //
00018 //
00019 
00020 // Anton Anastassov (Northwestern):
00021 // Add code for actual tower merging, define two distinct inputs of
00022 // "regular" and "extra" towers
00023 // This functionality is subject to some restrictions
00024 // (see notes below)
00025 
00026 
00027 
00028 // system include files
00029 #include <memory>
00030 
00031 // user include files
00032 #include "FWCore/Framework/interface/Frameworkfwd.h"
00033 #include "FWCore/Framework/interface/EDProducer.h"
00034 
00035 #include "FWCore/Framework/interface/Event.h"
00036 #include "FWCore/Framework/interface/MakerMacros.h"
00037 
00038 #include "FWCore/ParameterSet/interface/ParameterSet.h"
00039 
00040 #include "RecoLocalCalo/CaloTowersCreator/src/CaloTowersCreator.h"
00041 #include "DataFormats/CaloTowers/interface/CaloTower.h"
00042 
00043 //
00044 // class declaration
00045 //
00046 
00047 class CaloTowersMerger : public edm::EDProducer {
00048    public:
00049       explicit CaloTowersMerger(const edm::ParameterSet&);
00050       ~CaloTowersMerger();
00051 
00052   CaloTower mergedTower(CaloTower t1, CaloTower t2);
00053 
00054    private:
00055       virtual void beginJob() ;
00056       virtual void produce(edm::Event&, const edm::EventSetup&);
00057       virtual void endJob() ;
00058       
00059       // ----------member data ---------------------------
00060 
00061   edm::InputTag regularTowerTag,extraTowerTag;
00062 };
00063 
00064 //
00065 // constants, enums and typedefs
00066 //
00067 
00068 
00069 //
00070 // static data member definitions
00071 //
00072 
00073 //
00074 // constructors and destructor
00075 //
00076 CaloTowersMerger::CaloTowersMerger(const edm::ParameterSet& iConfig)
00077 {
00078   regularTowerTag=iConfig.getParameter<edm::InputTag>("regularTowerTag");
00079   extraTowerTag=iConfig.getParameter<edm::InputTag>("extraTowerTag");
00080 
00081    //register your products
00082    produces<CaloTowerCollection>();
00083 }
00084 
00085 
00086 CaloTowersMerger::~CaloTowersMerger()
00087 {
00088  
00089    // do anything here that needs to be done at desctruction time
00090    // (e.g. close files, deallocate resources etc.)
00091 
00092 }
00093 
00094 
00095 //
00096 // member functions
00097 //
00098 
00099 // ------------ method called to produce the data  ------------
00100 void
00101 CaloTowersMerger::produce(edm::Event& iEvent, const edm::EventSetup& iSetup)
00102 {
00103   edm::Handle<CaloTowerCollection> regTower,extraTower;
00104 
00105   iEvent.getByLabel(regularTowerTag,regTower);
00106   iEvent.getByLabel(extraTowerTag,extraTower);
00107 
00108   std::auto_ptr<CaloTowerCollection> output;
00109 
00110   if (!regTower.isValid() && !extraTower.isValid()){
00111     edm::LogError("CaloTowersMerger")<<"both input tag:"<<regularTowerTag<<" and "<<extraTowerTag<<" are invalid. empty merged collection";
00112     output.reset(new CaloTowerCollection());
00113     iEvent.put(output);
00114     return;
00115   }else if (!regTower.isValid()  || !extraTower.isValid()){
00116     if (!regTower.isValid() && extraTower.isValid())
00117       regTower=extraTower;
00118     output.reset(new CaloTowerCollection(*regTower));
00119     iEvent.put(output);
00120     return;
00121   }
00122   else{
00123     //both valid input collections: merging
00124     output.reset(new CaloTowerCollection());
00125     output->reserve(regTower->size()+extraTower->size());
00126   
00127     CaloTowerCollection::const_iterator rt_begin = regTower->begin();
00128     CaloTowerCollection::const_iterator rt_end = regTower->end();
00129     CaloTowerCollection::const_iterator rt_it = rt_begin;
00130 
00131     //vector of overlapping towers
00132     std::vector<CaloTowerCollection::const_iterator> overlappingTowers;
00133     overlappingTowers.reserve(extraTower->size());
00134 
00135     for (;rt_it!=rt_end;++rt_it){
00136       CaloTowerCollection::const_iterator et_it = extraTower->find(rt_it->id());
00137       if (et_it != extraTower->end()){
00138         //need to merge the components
00139         //FIXME
00140 
00142         //one needs to merge t1 and t2 into mergedTower
00143         //end FIXME
00144         CaloTower mt = mergedTower(*rt_it, *et_it);
00145 
00146         output->push_back(mt);
00147         overlappingTowers.push_back(et_it);
00148 
00149       }else{
00150         //just copy the regular tower over
00151         output->push_back(*rt_it);
00152       }
00153     }
00154     CaloTowerCollection::const_iterator et_begin = extraTower->begin();
00155     CaloTowerCollection::const_iterator et_end = extraTower->end();
00156     CaloTowerCollection::const_iterator et_it=et_begin;
00157     for (;et_it!=et_end;++et_it){
00158       if (std::find(overlappingTowers.begin(),overlappingTowers.end(),et_it)==overlappingTowers.end())
00159         //non overlapping tower
00160         //copy the extra tower over
00161         output->push_back(*et_it);
00162     }
00163     iEvent.put(output);
00164   }
00165   
00166 }
00167 
00168 // ------------ method called once each job just before starting event loop  ------------
00169 void 
00170 CaloTowersMerger::beginJob()
00171 {
00172 }
00173 
00174 // ------------ method called once each job just after ending the event loop  ------------
00175 void 
00176 CaloTowersMerger::endJob() {
00177 }
00178 
00179 
00180 
00181 
00182 
00183 // Make a new tower by merging two towers containing exclusive hits
00184 // This cannot be done fully consistently and independent of the
00185 // creation mechnaism...
00186 // This functionlaity it to be used only for testing the effects 
00187 // of rejected bad hits.
00188 
00189 CaloTower CaloTowersMerger::mergedTower(const CaloTower rt, const CaloTower et) {
00190 
00191   double newOuterE = 0;
00192 
00193   // HO energies are always saved (even if useHO=false)
00194   // make sure there is no double counting
00195   // crude test if one has HO energy and the other not (possibly due to bad hit cleanup)
00196   // However: for |iEta|>15 E_outer has different meening:
00197   // it holds either the energy in the outer depths in HCAL, etc
00198   
00199   if (rt.ietaAbs()<16 && (fabs(rt.outerEnergy()-et.outerEnergy())<0.00001 ) ) {
00200     // there is no differnce in the store HO energies
00201     newOuterE = rt.outerEnergy();
00202   }
00203   else {
00204     newOuterE = rt.outerEnergy()+et.outerEnergy();
00205   }
00206 
00207 
00208   bool rt_hasEcalConstit = false;
00209   bool et_hasEcalConstit = false;
00210   
00211   bool rt_hasHcalConstit = false;
00212   bool et_hasHcalConstit = false;
00213 
00214 
00215   // check if there are HCAL/ECAL constituents in the towers
00216 
00217   std::vector<DetId>::const_iterator rc_begin=rt.constituents().begin();
00218   std::vector<DetId>::const_iterator rc_end=rt.constituents().end();
00219   std::vector<DetId>::const_iterator rc_it;
00220 
00221 
00222    for (rc_it=rc_begin; rc_it!=rc_end; ++rc_it) {
00223      if (rc_it->det()==DetId::Hcal) rt_hasHcalConstit=true;
00224      break;
00225    }
00226    for (rc_it=rc_begin; rc_it!=rc_end; ++rc_it) {
00227      if (rc_it->det()==DetId::Ecal) rt_hasEcalConstit=true;
00228      break;
00229    }
00230 
00231   std::vector<DetId>::const_iterator ec_begin=et.constituents().begin();
00232   std::vector<DetId>::const_iterator ec_end=et.constituents().end();
00233   std::vector<DetId>::const_iterator ec_it;
00234 
00235    for (ec_it=ec_begin; ec_it!=ec_end; ++ec_it) {
00236      if (ec_it->det()==DetId::Hcal) et_hasHcalConstit=true;
00237      break;
00238    }
00239    for (ec_it=ec_begin; ec_it!=ec_end; ++ec_it) {
00240      if (ec_it->det()==DetId::Ecal) et_hasEcalConstit=true;
00241      break;
00242    }
00243 
00244 
00245    std::vector<DetId> combinedConstituents = rt.constituents();
00246    for (ec_it=ec_begin; ec_it!=ec_end; ++ec_it) {
00247      // if properly resconstructed, the only possible overlap should be for HO hits that
00248      // are always listed as constituents if above thereshold (old JetMET request)
00249      if (std::find(combinedConstituents.begin(),combinedConstituents.end(), *ec_it)==combinedConstituents.end())
00250        combinedConstituents.push_back(*ec_it);
00251    }
00252 
00253 
00254 
00255    GlobalPoint newEmPosition(0.0, 0.0, 0.0);
00256 
00257    // The following assumes the current default
00258    // momentum reconstruction method (1) and 
00259    // accepted rechits with some threshod >0
00260 
00261 
00262    if (rt_hasEcalConstit && et_hasEcalConstit) {
00263     
00264      if (rt.emEnergy()>0 && et.emEnergy()>0) {
00265        double sumEmE = rt.emEnergy()+ et.emEnergy();
00266        
00267        double x =   rt.emEnergy()*rt.emPosition().x() + et.emEnergy()*et.emPosition().x();
00268        double y =   rt.emEnergy()*rt.emPosition().y() + et.emEnergy()*et.emPosition().y();   
00269        double z =   rt.emEnergy()*rt.emPosition().z() + et.emEnergy()*et.emPosition().z();
00270       
00271        GlobalPoint weightedEmdPosition(x/sumEmE,y/sumEmE,z/sumEmE);
00272        newEmPosition = weightedEmdPosition;
00273      }
00274      
00275 
00276    }
00277    else if (rt_hasEcalConstit && !et_hasEcalConstit) {
00278      newEmPosition = rt.emPosition();
00279    }
00280    else if (!rt_hasEcalConstit && et_hasEcalConstit) {
00281      newEmPosition = et.emPosition();
00282    }
00283    
00284    
00285    GlobalPoint newHadPosition(0.0, 0.0, 0.0);
00286    // had positions are the same if there is at least one constituent
00287    if (rt_hasHcalConstit) {
00288      newHadPosition = rt.hadPosition();
00289    }
00290    else if (et_hasHcalConstit) {
00291      newHadPosition = et.hadPosition();
00292    }
00293    
00294 
00295    // MAke the new tower and set all values  
00296     
00297    CaloTower mergedTower(rt.id(), rt.emEnergy()+et.emEnergy(), rt.hadEnergy()+et.hadEnergy(), newOuterE, -1, -1, 
00298                          rt.p4()+et.p4(), newEmPosition, newHadPosition);
00299    
00300    mergedTower.addConstituents(combinedConstituents);
00301 
00302    (rt.hottestCellE() > et.hottestCellE())?
00303      mergedTower.setHottestCellE(rt.hottestCellE()) : 
00304      mergedTower.setHottestCellE(et.hottestCellE());
00305 
00306   unsigned int numBadHcalChan = rt.numBadHcalCells() - et.numProblematicHcalCells() - rt.numRecoveredHcalCells();
00307    unsigned int numBadEcalChan = rt.numBadEcalCells() - et.numProblematicEcalCells() - rt.numRecoveredEcalCells();
00308 
00309    unsigned int numProbHcalChan = rt.numProblematicHcalCells() + et.numProblematicHcalCells();
00310    unsigned int numProbEcalChan = rt.numProblematicEcalCells() + et.numProblematicEcalCells();
00311 
00312    unsigned int numRecHcalChan = rt.numRecoveredHcalCells() + et.numRecoveredHcalCells();
00313    unsigned int numRecEcalChan = rt.numRecoveredEcalCells() + et.numRecoveredEcalCells();
00314 
00315    mergedTower.setCaloTowerStatus(numBadHcalChan, numBadEcalChan,    
00316                                   numRecHcalChan, numRecEcalChan,    
00317                                   numProbHcalChan, numProbEcalChan);
00318 
00319    // use timing from the good tower only (for now, in default reco we use information from good hits only)
00320    // time is saved as integer but returned as float in (ns)
00321    mergedTower.setEcalTime( int(rt.ecalTime()*100.0 + 0.5) );
00322    mergedTower.setHcalTime( int(rt.hcalTime()*100.0 + 0.5) );
00323 
00324 
00325   return mergedTower;
00326 
00327 }
00328 
00329 
00330 
00331 //define this as a plug-in
00332 DEFINE_FWK_MODULE(CaloTowersMerger);