/ElectroWeakAnalysis/Utilities/src/DistortedPFCandProducer.cc

https://github.com/aivanov-cern/cmssw · C++ · 293 lines · 192 code · 70 blank · 31 comment · 53 complexity · 476ada0cd2423ed3b967b5d18d8a7b58 MD5 · raw file

  1. #include <memory>
  2. #include "FWCore/Framework/interface/Frameworkfwd.h"
  3. #include "FWCore/Framework/interface/MakerMacros.h"
  4. #include "FWCore/Framework/interface/EDProducer.h"
  5. #include "MuonAnalysis/MomentumScaleCalibration/interface/MomentumScaleCorrector.h"
  6. #include "MuonAnalysis/MomentumScaleCalibration/interface/ResolutionFunction.h"
  7. //
  8. // class declaration
  9. //
  10. class DistortedPFCandProducer : public edm::EDProducer {
  11. public:
  12. explicit DistortedPFCandProducer(const edm::ParameterSet&);
  13. ~DistortedPFCandProducer();
  14. private:
  15. virtual void beginJob() override ;
  16. virtual void produce(edm::Event&, const edm::EventSetup&) override;
  17. virtual void endJob() override ;
  18. edm::InputTag muonTag_;
  19. edm::InputTag pfTag_;
  20. edm::InputTag genMatchMapTag_;
  21. std::vector<double> etaBinEdges_;
  22. std::vector<double> shiftOnOneOverPt_; // in [1/GeV]
  23. std::vector<double> relativeShiftOnPt_;
  24. std::vector<double> uncertaintyOnOneOverPt_; // in [1/GeV]
  25. std::vector<double> relativeUncertaintyOnPt_;
  26. std::vector<double> efficiencyRatioOverMC_;
  27. };
  28. #include "FWCore/MessageLogger/interface/MessageLogger.h"
  29. #include "FWCore/Framework/interface/Event.h"
  30. #include "DataFormats/Common/interface/Handle.h"
  31. #include "DataFormats/Common/interface/View.h"
  32. #include "DataFormats/MuonReco/interface/Muon.h"
  33. #include "DataFormats/MuonReco/interface/MuonFwd.h"
  34. #include "DataFormats/TrackReco/interface/Track.h"
  35. #include "DataFormats/HepMCCandidate/interface/GenParticle.h"
  36. #include "DataFormats/ParticleFlowCandidate/interface/PFCandidate.h"
  37. #include "DataFormats/ParticleFlowCandidate/interface/PFCandidateFwd.h"
  38. #include <CLHEP/Random/RandFlat.h>
  39. #include <CLHEP/Random/RandGauss.h>
  40. /////////////////////////////////////////////////////////////////////////////////////
  41. DistortedPFCandProducer::DistortedPFCandProducer(const edm::ParameterSet& pset) {
  42. // What is being produced
  43. produces<std::vector<reco::PFCandidate> >();
  44. // Input products
  45. muonTag_ = pset.getUntrackedParameter<edm::InputTag> ("MuonTag", edm::InputTag("muons"));
  46. pfTag_ = pset.getUntrackedParameter<edm::InputTag> ("PFTag", edm::InputTag("particleFlow"));
  47. genMatchMapTag_ = pset.getUntrackedParameter<edm::InputTag> ("GenMatchMapTag", edm::InputTag("genMatchMap"));
  48. // Eta edges
  49. std::vector<double> defEtaEdges;
  50. defEtaEdges.push_back(-999999.);
  51. defEtaEdges.push_back(999999.);
  52. etaBinEdges_ = pset.getUntrackedParameter<std::vector<double> > ("EtaBinEdges",defEtaEdges);
  53. unsigned int ninputs_expected = etaBinEdges_.size()-1;
  54. // Distortions in muon momentum
  55. std::vector<double> defDistortion;
  56. defDistortion.push_back(0.);
  57. shiftOnOneOverPt_ = pset.getUntrackedParameter<std::vector<double> > ("ShiftOnOneOverPt",defDistortion); // in [1/GeV]
  58. if (shiftOnOneOverPt_.size()==1 && ninputs_expected>1) {
  59. for (unsigned int i=1; i<ninputs_expected; i++){ shiftOnOneOverPt_.push_back(shiftOnOneOverPt_[0]);}
  60. }
  61. relativeShiftOnPt_ = pset.getUntrackedParameter<std::vector<double> > ("RelativeShiftOnPt",defDistortion);
  62. if (relativeShiftOnPt_.size()==1 && ninputs_expected>1) {
  63. for (unsigned int i=1; i<ninputs_expected; i++){ relativeShiftOnPt_.push_back(relativeShiftOnPt_[0]);}
  64. }
  65. uncertaintyOnOneOverPt_ = pset.getUntrackedParameter<std::vector<double> > ("UncertaintyOnOneOverPt",defDistortion); // in [1/GeV]
  66. if (uncertaintyOnOneOverPt_.size()==1 && ninputs_expected>1) {
  67. for (unsigned int i=1; i<ninputs_expected; i++){ uncertaintyOnOneOverPt_.push_back(uncertaintyOnOneOverPt_[0]);}
  68. }
  69. relativeUncertaintyOnPt_ = pset.getUntrackedParameter<std::vector<double> > ("RelativeUncertaintyOnPt",defDistortion);
  70. if (relativeUncertaintyOnPt_.size()==1 && ninputs_expected>1) {
  71. for (unsigned int i=1; i<ninputs_expected; i++){ relativeUncertaintyOnPt_.push_back(relativeUncertaintyOnPt_[0]);}
  72. }
  73. // Data/MC efficiency ratios
  74. std::vector<double> defEfficiencyRatio;
  75. defEfficiencyRatio.push_back(1.);
  76. efficiencyRatioOverMC_ = pset.getUntrackedParameter<std::vector<double> > ("EfficiencyRatioOverMC",defEfficiencyRatio);
  77. if (efficiencyRatioOverMC_.size()==1 && ninputs_expected>1) {
  78. for (unsigned int i=1; i<ninputs_expected; i++){ efficiencyRatioOverMC_.push_back(efficiencyRatioOverMC_[0]);}
  79. }
  80. // Send a warning if there are inconsistencies in vector sizes !!
  81. bool effWrong = efficiencyRatioOverMC_.size()!=ninputs_expected;
  82. bool momWrong = shiftOnOneOverPt_.size()!=ninputs_expected
  83. || relativeShiftOnPt_.size()!=ninputs_expected
  84. || uncertaintyOnOneOverPt_.size()!=ninputs_expected
  85. || relativeUncertaintyOnPt_.size()!=ninputs_expected;
  86. if ( effWrong and momWrong) {
  87. edm::LogError("") << "WARNING: DistortedPFCandProducer : Size of some parameters do not match the EtaBinEdges vector!!";
  88. }
  89. }
  90. /////////////////////////////////////////////////////////////////////////////////////
  91. DistortedPFCandProducer::~DistortedPFCandProducer(){
  92. }
  93. /////////////////////////////////////////////////////////////////////////////////////
  94. void DistortedPFCandProducer::beginJob() {
  95. }
  96. /////////////////////////////////////////////////////////////////////////////////////
  97. void DistortedPFCandProducer::endJob(){
  98. }
  99. /////////////////////////////////////////////////////////////////////////////////////
  100. void DistortedPFCandProducer::produce(edm::Event& ev, const edm::EventSetup& iSetup) {
  101. if (ev.isRealData()) return;
  102. // Muon collection
  103. edm::Handle<edm::View<reco::Muon> > muonCollection;
  104. if (!ev.getByLabel(muonTag_, muonCollection)) {
  105. edm::LogError("") << ">>> Muon collection does not exist !!!";
  106. return;
  107. }
  108. edm::Handle<reco::GenParticleMatch> genMatchMap;
  109. if (!ev.getByLabel(genMatchMapTag_, genMatchMap)) {
  110. edm::LogError("") << ">>> Muon-GenParticle match map does not exist !!!";
  111. return;
  112. }
  113. // Get PFCandidate collection
  114. edm::Handle<edm::View<reco::PFCandidate> > pfCollection;
  115. if (!ev.getByLabel(pfTag_, pfCollection)) {
  116. edm::LogError("") << ">>> PFCandidate collection does not exist !!!";
  117. return;
  118. }
  119. unsigned int muonCollectionSize = muonCollection->size();
  120. unsigned int pfCollectionSize = pfCollection->size();
  121. if (pfCollectionSize<1) return;
  122. // Ask for PfMuon consistency
  123. bool pfMuonFound = false;
  124. std::auto_ptr<reco::PFCandidateCollection> newmuons (new reco::PFCandidateCollection);
  125. // Loop on all PF candidates
  126. for (unsigned int j=0; j<pfCollectionSize; j++) {
  127. edm::RefToBase<reco::PFCandidate> pf = pfCollection->refAt(j);
  128. // New PF muon
  129. double ptmu = pf->pt();
  130. for (unsigned int i=0; i<muonCollectionSize; i++) {
  131. edm::RefToBase<reco::Muon> mu = muonCollection->refAt(i);
  132. // Check the muon is in the PF collection
  133. if (pf->particleId()==reco::PFCandidate::mu) {
  134. reco::MuonRef muref = pf->muonRef();
  135. if (muref.isNonnull()) {
  136. if (muref.key()==mu.key()) {
  137. if ( mu->isStandAloneMuon() && ptmu == muref->standAloneMuon()->pt() && (
  138. ( !mu->isGlobalMuon() || ( mu->isGlobalMuon() && ptmu != muref->combinedMuon()->pt() ) ) &&
  139. ( !mu->isTrackerMuon() || ( mu->isTrackerMuon() && ptmu != mu->track()->pt() ) ) )
  140. ) {
  141. pfMuonFound = false;
  142. }
  143. else if ( !mu->isTrackerMuon() ){
  144. pfMuonFound = false;
  145. }
  146. else{
  147. pfMuonFound = true;}
  148. }
  149. else {pfMuonFound = false; }
  150. }
  151. }
  152. // do nothing if StandAlone muon
  153. //const reco::Track& track = *trackRef;
  154. if ( !pfMuonFound) continue;
  155. double ptgen = pf->pt();
  156. double etagen = pf->eta();
  157. reco::GenParticleRef gen = (*genMatchMap)[mu];
  158. if( !gen.isNull()) {
  159. ptgen = gen->pt();
  160. etagen = gen->eta();
  161. LogTrace("") << ">>> Muon-GenParticle match found; ptmu= " << pf->pt() << ", ptgen= " << ptgen;
  162. } else {
  163. LogTrace("") << ">>> MUON-GENPARTICLE MATCH NOT FOUND!!!";
  164. }
  165. // Initialize parameters
  166. double effRatio = 0.;
  167. double shift1 = 0.;
  168. double shift2 = 0.;
  169. double sigma1 = 0.;
  170. double sigma2 = 0.;
  171. // Find out which eta bin should be used
  172. unsigned int nbins = etaBinEdges_.size()-1;
  173. unsigned int etaBin = nbins;
  174. if (etagen>etaBinEdges_[0] && etagen<etaBinEdges_[nbins]) {
  175. for (unsigned int j=1; j<=nbins; ++j) {
  176. if (etagen>etaBinEdges_[j]) continue;
  177. etaBin = j-1;
  178. break;
  179. }
  180. }
  181. if (etaBin<nbins) {
  182. LogTrace("") << ">>> etaBin: " << etaBin << ", for etagen =" << etagen;
  183. } else {
  184. // Muon is rejected if outside the considered eta range
  185. LogTrace("") << ">>> Muon outside eta range: reject it; etagen = " << etagen;
  186. pfMuonFound = false;
  187. continue;
  188. }
  189. if (!pfMuonFound) continue;
  190. // Set shifts
  191. shift1 = shiftOnOneOverPt_[etaBin];
  192. shift2 = relativeShiftOnPt_[etaBin];
  193. LogTrace("") << "\tshiftOnOneOverPt= " << shift1*100 << " [%]";
  194. LogTrace("") << "\trelativeShiftOnPt= " << shift2*100 << " [%]";
  195. // Set resolutions
  196. sigma1 = uncertaintyOnOneOverPt_[etaBin];
  197. sigma2 = relativeUncertaintyOnPt_[etaBin];
  198. LogTrace("") << "\tuncertaintyOnOneOverPt= " << sigma1 << " [1/GeV]";
  199. LogTrace("") << "\trelativeUncertaintyOnPt= " << sigma2*100 << " [%]";
  200. // Set efficiency ratio
  201. effRatio = efficiencyRatioOverMC_[etaBin];
  202. LogTrace("") << "\tefficiencyRatioOverMC= " << effRatio;
  203. // Reject muons according to efficiency ratio
  204. double rndf = CLHEP::RandFlat::shoot();
  205. if (rndf>effRatio) continue;
  206. // Gaussian Random numbers for smearing
  207. double rndg1 = CLHEP::RandGauss::shoot();
  208. double rndg2 = CLHEP::RandGauss::shoot();
  209. // change here the pt of the candidate, if it is a muon
  210. ptmu += ptgen * ( shift1*ptgen + shift2 + sigma1*rndg1*ptgen + sigma2*rndg2);
  211. pfMuonFound = false ;
  212. }
  213. reco::PFCandidate* newmu = pf->clone();
  214. newmu->setP4 (
  215. reco::Particle::PolarLorentzVector (
  216. ptmu, pf->eta(), pf->phi(), pf->mass()
  217. )
  218. );
  219. newmuons->push_back(*newmu);
  220. }
  221. ev.put(newmuons);
  222. }
  223. DEFINE_FWK_MODULE(DistortedPFCandProducer);