CMS 3D CMS Logo

/afs/cern.ch/work/a/aaltunda/public/www/CMSSW_5_3_14/src/ElectroWeakAnalysis/Utilities/src/DistortedPFCandProducer.cc

Go to the documentation of this file.
00001 #include <memory>
00002 #include "FWCore/Framework/interface/Frameworkfwd.h"
00003 #include "FWCore/Framework/interface/MakerMacros.h"
00004 #include "FWCore/Framework/interface/EDProducer.h"
00005 
00006 #include "MuonAnalysis/MomentumScaleCalibration/interface/MomentumScaleCorrector.h"
00007 #include "MuonAnalysis/MomentumScaleCalibration/interface/ResolutionFunction.h"
00008 
00009 //
00010 // class declaration
00011 //
00012 class DistortedPFCandProducer : public edm::EDProducer {
00013    public:
00014       explicit DistortedPFCandProducer(const edm::ParameterSet&);
00015       ~DistortedPFCandProducer();
00016 
00017    private:
00018       virtual void beginJob() ;
00019       virtual void produce(edm::Event&, const edm::EventSetup&);
00020       virtual void endJob() ;
00021 
00022       edm::InputTag muonTag_;
00023       edm::InputTag pfTag_;
00024       edm::InputTag genMatchMapTag_;
00025       std::vector<double> etaBinEdges_;
00026 
00027       std::vector<double> shiftOnOneOverPt_; // in [1/GeV]
00028       std::vector<double> relativeShiftOnPt_;
00029       std::vector<double> uncertaintyOnOneOverPt_; // in [1/GeV]
00030       std::vector<double> relativeUncertaintyOnPt_;
00031 
00032       std::vector<double> efficiencyRatioOverMC_;
00033 };
00034 
00035 #include "FWCore/MessageLogger/interface/MessageLogger.h"
00036 #include "FWCore/Framework/interface/Event.h"
00037 #include "DataFormats/Common/interface/Handle.h"
00038 #include "DataFormats/Common/interface/View.h"
00039 #include "DataFormats/MuonReco/interface/Muon.h"
00040 #include "DataFormats/MuonReco/interface/MuonFwd.h"
00041 #include "DataFormats/TrackReco/interface/Track.h"
00042 #include "DataFormats/HepMCCandidate/interface/GenParticle.h"
00043 #include "DataFormats/ParticleFlowCandidate/interface/PFCandidate.h"
00044 #include "DataFormats/ParticleFlowCandidate/interface/PFCandidateFwd.h"
00045 
00046 #include <CLHEP/Random/RandFlat.h>
00047 #include <CLHEP/Random/RandGauss.h>
00048 
00050 DistortedPFCandProducer::DistortedPFCandProducer(const edm::ParameterSet& pset) {
00051 
00052   // What is being produced
00053       produces<std::vector<reco::PFCandidate> >();
00054 
00055   // Input products
00056       muonTag_ = pset.getUntrackedParameter<edm::InputTag> ("MuonTag", edm::InputTag("muons"));
00057       pfTag_ = pset.getUntrackedParameter<edm::InputTag> ("PFTag", edm::InputTag("particleFlow"));
00058       genMatchMapTag_ = pset.getUntrackedParameter<edm::InputTag> ("GenMatchMapTag", edm::InputTag("genMatchMap"));
00059 
00060   // Eta edges
00061       std::vector<double> defEtaEdges;
00062       defEtaEdges.push_back(-999999.);
00063       defEtaEdges.push_back(999999.);
00064       etaBinEdges_ = pset.getUntrackedParameter<std::vector<double> > ("EtaBinEdges",defEtaEdges);
00065       unsigned int ninputs_expected = etaBinEdges_.size()-1;
00066 
00067   // Distortions in muon momentum
00068       std::vector<double> defDistortion;
00069       defDistortion.push_back(0.);
00070 
00071       shiftOnOneOverPt_ = pset.getUntrackedParameter<std::vector<double> > ("ShiftOnOneOverPt",defDistortion); // in [1/GeV]
00072       if (shiftOnOneOverPt_.size()==1 && ninputs_expected>1) {
00073             for (unsigned int i=1; i<ninputs_expected; i++){ shiftOnOneOverPt_.push_back(shiftOnOneOverPt_[0]);}
00074       }
00075 
00076       relativeShiftOnPt_ = pset.getUntrackedParameter<std::vector<double> > ("RelativeShiftOnPt",defDistortion);
00077       if (relativeShiftOnPt_.size()==1 && ninputs_expected>1) {
00078             for (unsigned int i=1; i<ninputs_expected; i++){ relativeShiftOnPt_.push_back(relativeShiftOnPt_[0]);}
00079       }
00080 
00081       uncertaintyOnOneOverPt_ = pset.getUntrackedParameter<std::vector<double> > ("UncertaintyOnOneOverPt",defDistortion); // in [1/GeV]
00082       if (uncertaintyOnOneOverPt_.size()==1 && ninputs_expected>1) {
00083             for (unsigned int i=1; i<ninputs_expected; i++){ uncertaintyOnOneOverPt_.push_back(uncertaintyOnOneOverPt_[0]);}
00084       }
00085 
00086       relativeUncertaintyOnPt_ = pset.getUntrackedParameter<std::vector<double> > ("RelativeUncertaintyOnPt",defDistortion);
00087       if (relativeUncertaintyOnPt_.size()==1 && ninputs_expected>1) {
00088             for (unsigned int i=1; i<ninputs_expected; i++){ relativeUncertaintyOnPt_.push_back(relativeUncertaintyOnPt_[0]);}
00089       }
00090 
00091   // Data/MC efficiency ratios
00092       std::vector<double> defEfficiencyRatio;
00093       defEfficiencyRatio.push_back(1.);
00094       efficiencyRatioOverMC_ = pset.getUntrackedParameter<std::vector<double> > ("EfficiencyRatioOverMC",defEfficiencyRatio);
00095       if (efficiencyRatioOverMC_.size()==1 && ninputs_expected>1) {
00096             for (unsigned int i=1; i<ninputs_expected; i++){ efficiencyRatioOverMC_.push_back(efficiencyRatioOverMC_[0]);}
00097       }
00098 
00099   // Send a warning if there are inconsistencies in vector sizes !!
00100       bool effWrong = efficiencyRatioOverMC_.size()!=ninputs_expected;
00101       bool momWrong =    shiftOnOneOverPt_.size()!=ninputs_expected 
00102                       || relativeShiftOnPt_.size()!=ninputs_expected 
00103                       || uncertaintyOnOneOverPt_.size()!=ninputs_expected 
00104                       || relativeUncertaintyOnPt_.size()!=ninputs_expected;
00105       if ( effWrong and momWrong) {
00106            edm::LogError("") << "WARNING: DistortedPFCandProducer : Size of some parameters do not match the EtaBinEdges vector!!";
00107       }
00108 
00109 } 
00110 
00112 DistortedPFCandProducer::~DistortedPFCandProducer(){
00113 }
00114 
00116 void DistortedPFCandProducer::beginJob() {
00117 }
00118 
00120 void DistortedPFCandProducer::endJob(){
00121 }
00122 
00124 void DistortedPFCandProducer::produce(edm::Event& ev, const edm::EventSetup& iSetup) {
00125 
00126       if (ev.isRealData()) return;
00127 
00128       // Muon collection
00129       edm::Handle<edm::View<reco::Muon> > muonCollection;
00130       if (!ev.getByLabel(muonTag_, muonCollection)) {
00131             edm::LogError("") << ">>> Muon collection does not exist !!!";
00132             return;
00133       }
00134 
00135       edm::Handle<reco::GenParticleMatch> genMatchMap;
00136       if (!ev.getByLabel(genMatchMapTag_, genMatchMap)) {
00137             edm::LogError("") << ">>> Muon-GenParticle match map does not exist !!!";
00138             return;
00139       }
00140   
00141 
00142       // Get PFCandidate collection
00143       edm::Handle<edm::View<reco::PFCandidate> > pfCollection;
00144       if (!ev.getByLabel(pfTag_, pfCollection)) {
00145             edm::LogError("") << ">>> PFCandidate collection does not exist !!!";
00146             return;
00147       }
00148 
00149       unsigned int muonCollectionSize = muonCollection->size();
00150       unsigned int pfCollectionSize = pfCollection->size();
00151       
00152       if (pfCollectionSize<1) return;
00153 
00154 
00155       // Ask for PfMuon consistency
00156       bool pfMuonFound = false;
00157 
00158 
00159 
00160       std::auto_ptr<reco::PFCandidateCollection> newmuons (new reco::PFCandidateCollection);
00161 
00162 
00163       // Loop on all PF candidates
00164       for (unsigned int j=0; j<pfCollectionSize; j++) {
00165         edm::RefToBase<reco::PFCandidate> pf = pfCollection->refAt(j);
00166 
00167 
00168         // New PF muon
00169         double ptmu = pf->pt();
00170 
00171 
00172         for (unsigned int i=0; i<muonCollectionSize; i++) {
00173           edm::RefToBase<reco::Muon> mu = muonCollection->refAt(i);
00174 
00175 
00176           // Check the muon is in the PF collection
00177           if (pf->particleId()==reco::PFCandidate::mu) {
00178             reco::MuonRef muref = pf->muonRef();
00179             if (muref.isNonnull()) {
00180               if (muref.key()==mu.key()) {
00181                    if ( mu->isStandAloneMuon() && ptmu == muref->standAloneMuon()->pt()  && (
00182                          ( !mu->isGlobalMuon()  || ( mu->isGlobalMuon() &&  ptmu != muref->combinedMuon()->pt() ) ) &&
00183                          ( !mu->isTrackerMuon() || ( mu->isTrackerMuon() && ptmu != mu->track()->pt() ) ) )
00184                        ) {
00185                         pfMuonFound = false; 
00186                     }
00187                     else if ( !mu->isTrackerMuon() ){
00188                         pfMuonFound = false;
00189                     }
00190                     else{
00191                         pfMuonFound = true;}
00192               }
00193               else {pfMuonFound = false; }
00194 
00195             }
00196           }
00197 
00198           // do nothing if StandAlone muon
00199           //const reco::Track& track = *trackRef;
00200           
00201           if ( !pfMuonFound) continue;
00202 
00203           double ptgen = pf->pt();
00204           double etagen = pf->eta();
00205 
00206 
00207           reco::GenParticleRef gen = (*genMatchMap)[mu];
00208           if( !gen.isNull()) {
00209             ptgen = gen->pt();
00210             etagen = gen->eta();
00211             LogTrace("") << ">>> Muon-GenParticle match found; ptmu= " << pf->pt() << ", ptgen= " << ptgen;
00212           } else {
00213             LogTrace("") << ">>> MUON-GENPARTICLE MATCH NOT FOUND!!!";
00214           }
00215      
00216 
00217           // Initialize parameters
00218           double effRatio = 0.;
00219           double shift1 = 0.;
00220           double shift2 = 0.;
00221           double sigma1 = 0.;
00222           double sigma2 = 0.;
00223 
00224           // Find out which eta bin should be used
00225           unsigned int nbins = etaBinEdges_.size()-1;
00226           unsigned int etaBin = nbins;
00227           if (etagen>etaBinEdges_[0] && etagen<etaBinEdges_[nbins]) {
00228             for (unsigned int j=1; j<=nbins; ++j) {
00229               if (etagen>etaBinEdges_[j]) continue;
00230               etaBin = j-1;
00231               break;
00232             }
00233           }
00234           if (etaBin<nbins) {
00235             LogTrace("") << ">>> etaBin: " << etaBin << ", for etagen =" << etagen;
00236           } else {
00237             // Muon is rejected if outside the considered eta range
00238             LogTrace("") << ">>> Muon outside eta range: reject it; etagen = " << etagen;
00239             pfMuonFound = false;
00240             continue;
00241           }
00242           
00243           if (!pfMuonFound) continue;
00244 
00245           // Set shifts
00246           shift1 = shiftOnOneOverPt_[etaBin];
00247           shift2 = relativeShiftOnPt_[etaBin];
00248           LogTrace("") << "\tshiftOnOneOverPt= " << shift1*100 << " [%]"; 
00249           LogTrace("") << "\trelativeShiftOnPt= " << shift2*100 << " [%]"; 
00250           
00251           // Set resolutions
00252           sigma1 = uncertaintyOnOneOverPt_[etaBin];
00253           sigma2 = relativeUncertaintyOnPt_[etaBin];
00254           LogTrace("") << "\tuncertaintyOnOneOverPt= " << sigma1 << " [1/GeV]"; 
00255           LogTrace("") << "\trelativeUncertaintyOnPt= " << sigma2*100 << " [%]"; 
00256           
00257           // Set efficiency ratio
00258           effRatio = efficiencyRatioOverMC_[etaBin];
00259           LogTrace("") << "\tefficiencyRatioOverMC= " << effRatio;
00260           
00261           // Reject muons according to efficiency ratio
00262           double rndf = CLHEP::RandFlat::shoot();
00263           if (rndf>effRatio) continue;
00264 
00265           // Gaussian Random numbers for smearing
00266           double rndg1 = CLHEP::RandGauss::shoot();
00267           double rndg2 = CLHEP::RandGauss::shoot();
00268             
00269             
00270           // change here the pt of the candidate, if it is a muon 
00271 
00272           ptmu += ptgen * ( shift1*ptgen + shift2 + sigma1*rndg1*ptgen + sigma2*rndg2);
00273           pfMuonFound = false ;
00274 
00275         }
00276 
00277         reco::PFCandidate* newmu = pf->clone();
00278         newmu->setP4 (
00279                       reco::Particle::PolarLorentzVector (
00280                                                           ptmu, pf->eta(), pf->phi(), pf->mass()
00281                                                           )
00282                       );
00283         
00284         newmuons->push_back(*newmu);
00285       }
00286 
00287  
00288         ev.put(newmuons);
00289 
00290 
00291 }
00292 
00293 DEFINE_FWK_MODULE(DistortedPFCandProducer);