CMS 3D CMS Logo

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