CMS 3D CMS Logo

/afs/cern.ch/work/a/aaltunda/public/www/CMSSW_6_2_5/src/RecoHI/HiJetAlgos/plugins/ParticleTowerProducer.cc

Go to the documentation of this file.
00001 // -*- C++ -*-
00002 //
00003 // Package:    ParticleTowerProducer
00004 // Class:      ParticleTowerProducer
00005 // 
00013 //
00014 // Original Author:  Yetkin Yilmaz,32 4-A08,+41227673039,
00015 //         Created:  Thu Jan 20 19:53:58 CET 2011
00016 // $Id: ParticleTowerProducer.cc,v 1.11 2013/05/02 12:29:18 mnguyen Exp $
00017 //
00018 //
00019 
00020 
00021 // system include files
00022 #include <memory>
00023 
00024 
00025 // user include files
00026 #include "FWCore/Framework/interface/Frameworkfwd.h"
00027 #include "FWCore/Framework/interface/EDProducer.h"
00028 
00029 #include "FWCore/Framework/interface/Event.h"
00030 #include "FWCore/Framework/interface/MakerMacros.h"
00031 
00032 #include "FWCore/Framework/interface/ESHandle.h"
00033 
00034 #include "FWCore/ParameterSet/interface/ParameterSet.h"
00035 
00036 #include "RecoHI/HiJetAlgos/plugins/ParticleTowerProducer.h"
00037 
00038 #include "DataFormats/HcalDetId/interface/HcalDetId.h"
00039 #include "DataFormats/ParticleFlowCandidate/interface/PFCandidate.h"
00040 #include "DataFormats/CaloTowers/interface/CaloTowerCollection.h"
00041 #include "DataFormats/Math/interface/deltaR.h"
00042 
00043 #include "Geometry/CaloGeometry/interface/CaloGeometry.h"
00044 #include "Geometry/Records/interface/CaloGeometryRecord.h"
00045 #include "Geometry/CaloGeometry/interface/CaloSubdetectorGeometry.h"
00046 #include "Geometry/CaloTopology/interface/CaloTopology.h"
00047 
00048 #include "TMath.h"
00049 #include "TRandom.h"
00050 
00051 
00052 
00053 
00054 //
00055 // constants, enums and typedefs
00056 //
00057 
00058 
00059 //
00060 // static data member definitions
00061 //
00062 
00063 //
00064 // constructors and destructor
00065 //
00066 ParticleTowerProducer::ParticleTowerProducer(const edm::ParameterSet& iConfig):
00067    geo_(0)
00068 {
00069    //register your products  
00070   src_ = iConfig.getParameter<edm::InputTag>("src");
00071   useHF_ = iConfig.getUntrackedParameter<bool>("useHF");
00072   
00073   produces<CaloTowerCollection>();
00074   
00075   //now do what ever other initialization is needed
00076   random_ = new TRandom();
00077   PI = TMath::Pi();
00078   
00079 
00080 
00081 }
00082 
00083 
00084 ParticleTowerProducer::~ParticleTowerProducer()
00085 {
00086  
00087    // do anything here that needs to be done at desctruction time
00088    // (e.g. close files, deallocate resources etc.)
00089 
00090 }
00091 
00092 
00093 //
00094 // member functions
00095 //
00096 
00097 // ------------ method called to produce the data  ------------
00098 void
00099 ParticleTowerProducer::produce(edm::Event& iEvent, const edm::EventSetup& iSetup)
00100 {
00101    using namespace edm;
00102 
00103    if(!geo_){
00104       edm::ESHandle<CaloGeometry> pG;
00105       iSetup.get<CaloGeometryRecord>().get(pG);
00106       geo_ = pG.product();
00107    }
00108 
00109 
00110    resetTowers(iEvent, iSetup);
00111 
00112 
00113    edm::Handle<reco::PFCandidateCollection> inputsHandle;
00114    iEvent.getByLabel(src_, inputsHandle);
00115    
00116    for(reco::PFCandidateCollection::const_iterator ci  = inputsHandle->begin(); ci!=inputsHandle->end(); ++ci)  {
00117 
00118     const reco::PFCandidate& particle = *ci;
00119     
00120     // put a cutoff if you want
00121     //if(particle.et() < 0.3) continue;      
00122     
00123     double eta = particle.eta();
00124 
00125     if(!useHF_ && fabs(eta) > 3. ) continue;
00126 
00127     int ieta = eta2ieta(eta);
00128     if(eta<0) ieta  *= -1;
00129 
00130     int iphi = phi2iphi(particle.phi(),ieta);
00131        
00132     HcalSubdetector sd;
00133     if(abs(ieta)<=16) sd = HcalBarrel;
00134     else if(fabs(eta)< 3.) sd = HcalEndcap;  // Use the endcap until eta =3
00135     else sd = HcalForward;
00136     
00137     HcalDetId hid = HcalDetId(sd,ieta,iphi,1); // assume depth=1
00138 
00139     // check against the old method (boundaries slightly shifted in the endcaps
00140     /*
00141     HcalDetId hid_orig = getNearestTower(particle);
00142     
00143     if(hid != hid_orig)
00144       { 
00145         if(abs((hid).ieta()-(hid_orig).ieta())>1 || abs((hid).iphi()-(hid_orig).iphi()) >1 ){
00146 
00147           int phi_diff = 1;
00148           if(abs((hid).ieta())>39 || abs((hid_orig).ieta())>39) phi_diff = 4;
00149           else if(abs((hid).ieta())>20 || abs((hid_orig).ieta())>20) phi_diff = 2;
00150 
00151           if(abs((hid).ieta()-(hid_orig).ieta()) > 1 || abs((hid).iphi()-(hid_orig).iphi()) > phi_diff ){
00152               std::cout<<" eta "<<eta<<std::endl;
00153               std::cout<<" hid "<<hid<<std::endl;
00154               std::cout<<" old method "<<hid_orig<<std::endl;
00155           }
00156         }
00157       }
00158     */
00159     towers_[hid] += particle.et();      
00160    }
00161    
00162    
00163    std::auto_ptr<CaloTowerCollection> prod(new CaloTowerCollection());
00164 
00165    for ( std::map< DetId, double >::const_iterator iter = towers_.begin();
00166          iter != towers_.end(); ++iter ){
00167      
00168      CaloTowerDetId newTowerId(iter->first.rawId());
00169      double et = iter->second;
00170 
00171      if(et>0){
00172 
00173        GlobalPoint pos =geo_->getGeometry(newTowerId)->getPosition();
00174        
00175        if(!useHF_ && fabs(pos.eta()) > 3. ) continue;
00176 
00177        // currently sets et =  pt, mass to zero
00178        // pt, eta , phi, mass
00179        reco::Particle::PolarLorentzVector p4(et,pos.eta(),pos.phi(),0.);
00180        
00181        CaloTower newTower(newTowerId,et,0,0,0,0,p4,pos,pos);
00182        prod->push_back(newTower);     
00183      }
00184    }
00185 
00186    
00187    //For reference, Calo Tower Constructors
00188 
00189    /*
00190    CaloTower(const CaloTowerDetId& id, 
00191              double emE, double hadE, double outerE,
00192              int ecal_tp, int hcal_tp,
00193              const PolarLorentzVector p4,
00194        GlobalPoint emPosition, GlobalPoint hadPosition);
00195  
00196    CaloTower(const CaloTowerDetId& id, 
00197              double emE, double hadE, double outerE,
00198              int ecal_tp, int hcal_tp,
00199              const LorentzVector p4,
00200        GlobalPoint emPosition, GlobalPoint hadPosition);
00201    */
00202 
00203 
00204    iEvent.put(prod);
00205 
00206 
00207 }
00208 
00209 // ------------ method called once each job just before starting event loop  ------------
00210 void 
00211 ParticleTowerProducer::beginJob()
00212 {
00213   // tower edges from fast sim, used starting at index 30 for the HF
00214   const double etatow[42] = {0.000, 0.087, 0.174, 0.261, 0.348, 0.435, 0.522, 0.609, 0.696, 0.783, 0.870, 0.957, 1.044, 1.131, 1.218, 1.305, 1.392, 1.479, 1.566, 1.653, 1.740, 1.830, 1.930, 2.043, 2.172, 2.322, 2.500, 2.650, 2.853, 3.000, 3.139, 3.314, 3.489, 3.664, 3.839, 4.013, 4.191, 4.363, 4.538, 4.716, 4.889, 5.191};
00215   
00216   // tower centers derived directly from by looping over HCAL towers and printing out the values, used up until eta = 3 where the HF/Endcap interface becomes problematic
00217   const double etacent[40] = {
00218     0.0435, // 1
00219     0.1305, // 2
00220     0.2175, // 3
00221     0.3045, // 4
00222     0.3915, // 5
00223     0.4785, // 6
00224     0.5655, // 7
00225     0.6525, // 8
00226     0.7395, // 9
00227     0.8265, // 10
00228     0.9135, // 11
00229     1.0005, // 12
00230     1.0875, // 13
00231     1.1745, // 14
00232     1.2615, // 15
00233     1.3485, // 16
00234     1.4355, // 17
00235     1.5225, // 18
00236     1.6095, // 19
00237     1.6965, // 20
00238     1.785 , // 21
00239     1.88  , // 22
00240     1.9865, // 23
00241     2.1075, // 24
00242     2.247 , // 25
00243     2.411 , // 26
00244     2.575 , // 27
00245     2.759 , // 28
00246     2.934 , // 29
00247     2.90138,// 29
00248     3.04448,// 30 
00249     3.21932,// 31
00250     3.39462,// 32
00251     3.56966,// 33 
00252     3.74485,// 34 
00253     3.91956,// 35 
00254     4.09497,// 36 
00255     4.27007,// 37 
00256     4.44417,// 38 
00257     4.62046 // 39 
00258       };
00259 
00260   // Use the real towers centrers for the barrel and endcap up to eta=3
00261   etaedge[0] = 0.;
00262   for(int i=1;i<30;i++){
00263     etaedge[i] = (etacent[i-1]-etaedge[i-1])*2.0 + etaedge[i-1];
00264     //std::cout<<" i "<<i<<" etaedge "<<etaedge[i]<<std::endl;  
00265   }
00266   // beyond eta = 3 just use the fast sim values
00267   if(useHF_){
00268     for(int i=30;i<42;i++){
00269       etaedge[i]=etatow[i];
00270       //std::cout<<" i "<<i<<" etaedge "<<etaedge[i]<<std::endl;  
00271     }
00272   }
00273 }
00274 
00275 // ------------ method called once each job just after ending the event loop  ------------
00276 void 
00277 ParticleTowerProducer::endJob() {
00278 }
00279 
00280 
00281 void ParticleTowerProducer::resetTowers(edm::Event& iEvent,const edm::EventSetup& iSetup)
00282 {
00283   
00284   std::vector<DetId> alldid =  geo_->getValidDetIds();
00285 
00286   for(std::vector<DetId>::const_iterator did=alldid.begin(); did != alldid.end(); did++){
00287     if( (*did).det() == DetId::Hcal ){
00288        HcalDetId hid = HcalDetId(*did);
00289        if( hid.depth() == 1 ) {
00290          
00291          if(!useHF_){
00292            GlobalPoint pos =geo_->getGeometry(hid)->getPosition();       
00293            //if((hid).iphi()==1)std::cout<<" ieta "<<(hid).ieta()<<" eta "<<pos.eta()<<" iphi "<<(hid).iphi()<<" phi "<<pos.phi()<<std::endl;
00294            if(fabs(pos.eta())>3.) continue;
00295          }
00296           towers_[(*did)] = 0.;
00297        }
00298        
00299     }
00300   }
00301 
00302 
00303 
00304 
00305   //print out tower eta boundaries
00306   /*
00307   int current_ieta=0;
00308   float testphi =0.;
00309   for(double testeta=1.7; testeta<=5.4;testeta+=0.00001){
00310     HcalDetId hid = getNearestTower(testeta,testphi);
00311     if((hid).ieta()!=current_ieta) {
00312       std::cout<<" new ieta "<<current_ieta<<" testeta "<<testeta<<std::endl;
00313       current_ieta = (hid).ieta();
00314     }
00315   }
00316   */
00317 
00318 }
00319 
00320 
00321 
00322 
00323 DetId ParticleTowerProducer::getNearestTower(const reco::PFCandidate & in) const {
00324 
00325   double eta = in.eta();
00326   double phi  = in.phi();
00327 
00328   double minDeltaR = 9999;
00329 
00330   std::vector<DetId> alldid =  geo_->getValidDetIds();
00331 
00332   DetId returnId;
00333   
00334   //int nclosetowers=0;
00335 
00336   for(std::vector<DetId>::const_iterator did=alldid.begin(); did != alldid.end(); did++){
00337     if( (*did).det() == DetId::Hcal ){
00338 
00339       HcalDetId hid(*did);
00340       
00341       // which layer is irrelevant for an eta-phi map, no?
00342 
00343       if( hid.depth() != 1 ) continue;
00344 
00345       GlobalPoint pos =geo_->getGeometry(hid)->getPosition();
00346       
00347       double hcalEta = pos.eta();
00348       double hcalPhi = pos.phi();
00349 
00350       //std::cout<<" transverse distance = "<<sqrt(pos.x()*pos.x()+pos.y()*pos.y())<<std::endl;
00351 
00352       //std::cout<<" ieta "<<(hid).ieta()<<" iphi "<<(hid).iphi()<<" hcalEta "<<hcalEta<<" hcalPhi "<<hcalPhi<<std::endl;
00353 
00354       double deltaR = reco::deltaR(eta,phi,hcalEta,hcalPhi);
00355       
00356       // need to factor in the size of the tower
00357       double towersize = 0.087;
00358      
00359       int ieta  = (hid).ieta();
00360       
00361       if(abs(ieta)>21){
00362         if(abs(ieta)>29) towersize=0.175;
00363         else{
00364           if(abs(ieta)==22) towersize=0.1;
00365           else if(abs(ieta)==23) towersize=0.113;
00366           else if(abs(ieta)==24) towersize=0.129;
00367           else if(abs(ieta)==25) towersize=0.16;
00368           else if(abs(ieta)==26) towersize=0.168;
00369           else if(abs(ieta)==27) towersize=0.15;
00370           else if(abs(ieta)==28) towersize=0.218;
00371           else if(abs(ieta)==29) towersize=0.132;
00372         }
00373       }
00374 
00375       deltaR /= towersize;
00376       //if(deltaR<1/3.) nclosetowers++;
00377 
00378       if(deltaR<minDeltaR){
00379          returnId = DetId(*did);
00380          minDeltaR = deltaR;
00381       }
00382       
00383       //if(abs(eta-hcalEta)<towersize/2. && abs(phi-hcalPhi)<towersize/2.) break;
00384     }
00385   }
00386   //if(nclosetowers>1)std::cout<<"eta "<<eta<<" phi "<<phi<<" minDeltaR "<<minDeltaR<<" nclosetowers "<<nclosetowers<<std::endl;
00387   return returnId;
00388 
00389 
00390 }
00391 
00392 
00393 DetId ParticleTowerProducer::getNearestTower(double eta, double phi) const {
00394 
00395   // get closest tower by delta R matching
00396   // Now obsolute, instead use faster premade eta-phi grid
00397 
00398   double minDeltaR = 9999;
00399 
00400   std::vector<DetId> alldid =  geo_->getValidDetIds();
00401 
00402   DetId returnId;
00403   
00404   //int nclosetowers=0;
00405 
00406   for(std::vector<DetId>::const_iterator did=alldid.begin(); did != alldid.end(); did++){
00407     if( (*did).det() == DetId::Hcal ){
00408 
00409       HcalDetId hid(*did);
00410       
00411       // which layer is irrelevant for an eta-phi map, no?
00412 
00413       if( hid.depth() != 1 ) continue;
00414 
00415       GlobalPoint pos =geo_->getGeometry(hid)->getPosition();
00416       
00417       double hcalEta = pos.eta();
00418       double hcalPhi = pos.phi();
00419 
00420       //std::cout<<" transverse distance = "<<sqrt(pos.x()*pos.x()+pos.y()*pos.y())<<std::endl;
00421 
00422       //std::cout<<" ieta "<<(hid).ieta()<<" iphi "<<(hid).iphi()<<" hcalEta "<<hcalEta<<" hcalPhi "<<hcalPhi<<std::endl;
00423 
00424       double deltaR = reco::deltaR(eta,phi,hcalEta,hcalPhi);
00425       
00426       // need to factor in the size of the tower
00427       double towersize = 0.087;
00428      
00429       int ieta  = (hid).ieta();
00430       
00431       if(abs(ieta)>21){
00432         if(abs(ieta)>29) towersize=0.175;
00433         else{
00434           if(abs(ieta)==22) towersize=0.1;
00435           else if(abs(ieta)==23) towersize=0.113;
00436           else if(abs(ieta)==24) towersize=0.129;
00437           else if(abs(ieta)==25) towersize=0.16;
00438           else if(abs(ieta)==26) towersize=0.168;
00439           else if(abs(ieta)==27) towersize=0.15;
00440           else if(abs(ieta)==28) towersize=0.218;
00441           else if(abs(ieta)==29) towersize=0.132;
00442         }
00443       }
00444 
00445       deltaR /= towersize;
00446       //if(deltaR<1/3.) nclosetowers++;
00447 
00448       if(deltaR<minDeltaR){
00449          returnId = DetId(*did);
00450          minDeltaR = deltaR;
00451       }
00452       
00453       //if(abs(eta-hcalEta)<towersize/2. && abs(phi-hcalPhi)<towersize/2.) break;
00454     }
00455   }
00456   //if(nclosetowers>1)std::cout<<"eta "<<eta<<" phi "<<phi<<" minDeltaR "<<minDeltaR<<" nclosetowers "<<nclosetowers<<std::endl;
00457   return returnId;
00458 
00459 
00460 }
00461 
00462 
00463 
00464 
00465 // Taken from FastSimulation/CalorimeterProperties/src/HCALProperties.cc
00466 // Note this returns an abs(ieta)
00467 int ParticleTowerProducer::eta2ieta(double eta) const {
00468   // binary search in the array of towers eta edges
00469 
00470   if(fabs(eta)>etaedge[41]) return 41;
00471   int size = 42;
00472   if(!useHF_) size = 30;
00473 
00474   double x = fabs(eta);
00475   int curr = size / 2;
00476   int step = size / 4;
00477   int iter;
00478   int prevdir = 0; 
00479   int actudir = 0; 
00480 
00481   for (iter = 0; iter < size ; iter++) {
00482 
00483     if( curr >= size || curr < 1 )
00484       std::cout <<  " ParticleTowerProducer::eta2ieta - wrong current index = "
00485                 << curr << " !!!" << std::endl;
00486 
00487     if ((x <= etaedge[curr]) && (x > etaedge[curr-1])) break;
00488     prevdir = actudir;
00489     if(x > etaedge[curr]) {actudir =  1;}
00490     else {actudir = -1;}
00491     if(prevdir * actudir < 0) { if(step > 1) step /= 2;}
00492     curr += actudir * step;
00493     if(curr > size) curr = size;
00494     else { if(curr < 1) {curr = 1;}}
00495 
00496     /*
00497     std::cout << " HCALProperties::eta2ieta  end of iter." << iter 
00498           << " curr, etaedge[curr-1], etaedge[curr] = "
00499                 << curr << " " << etaedge[curr-1] << " " << etaedge[curr] << std::endl;
00500     */
00501     
00502   }
00503 
00504   /*
00505   std::cout << " HCALProperties::eta2ieta  for input x = " << x 
00506       << "  found index = " << curr-1
00507           << std::endl;
00508   */
00509   
00510   return curr;
00511 }
00512 
00513 int ParticleTowerProducer::phi2iphi(double phi, int ieta) const {
00514   
00515   if(phi<0) phi += 2.*PI;
00516   else if(phi> 2.*PI) phi -= 2.*PI;
00517   
00518   int iphi = (int) TMath::Ceil(phi/2.0/PI*72.);
00519   // take into account larger granularity in endcap (x2) and at the end of the HF (x4)
00520   if(abs(ieta)>20){
00521     if(abs(ieta)<40) iphi -= (iphi+1)%2;
00522     else {
00523       iphi -= (iphi+1)%4;
00524       if(iphi==-1) iphi=71;
00525       }
00526   }
00527   
00528   return iphi;
00529 
00530 }
00531 
00532     //define this as a plug-in
00533 DEFINE_FWK_MODULE(ParticleTowerProducer);