/ElectroWeakAnalysis/Utilities/src/FSRWeightProducer.cc

https://github.com/aivanov-cern/cmssw · C++ · 167 lines · 119 code · 30 blank · 18 comment · 32 complexity · 142d2f597550c1fe15ebd1492e8ebb2d MD5 · raw file

  1. #include <memory>
  2. #include "FWCore/Framework/interface/Frameworkfwd.h"
  3. #include "FWCore/Framework/interface/EDProducer.h"
  4. #include "FWCore/Framework/interface/Event.h"
  5. #include "FWCore/Framework/interface/MakerMacros.h"
  6. #include "FWCore/ParameterSet/interface/ParameterSet.h"
  7. #include "DataFormats/HepMCCandidate/interface/GenParticle.h"
  8. #include "DataFormats/Candidate/interface/CompositeCandidate.h"
  9. #include "CommonTools/CandUtils/interface/AddFourMomenta.h"
  10. #include "CommonTools/CandUtils/interface/Booster.h"
  11. #include <Math/VectorUtil.h>
  12. //
  13. // class declaration
  14. //
  15. class FSRWeightProducer : public edm::EDProducer {
  16. public:
  17. explicit FSRWeightProducer(const edm::ParameterSet&);
  18. ~FSRWeightProducer();
  19. private:
  20. virtual void beginJob() override ;
  21. virtual void produce(edm::Event&, const edm::EventSetup&) override;
  22. virtual void endJob() override ;
  23. double alphaRatio(double) ;
  24. edm::InputTag genTag_;
  25. };
  26. #include "DataFormats/HepMCCandidate/interface/GenParticle.h"
  27. /////////////////////////////////////////////////////////////////////////////////////
  28. FSRWeightProducer::FSRWeightProducer(const edm::ParameterSet& pset) {
  29. genTag_ = pset.getUntrackedParameter<edm::InputTag> ("GenTag", edm::InputTag("genParticles"));
  30. produces<double>();
  31. }
  32. /////////////////////////////////////////////////////////////////////////////////////
  33. FSRWeightProducer::~FSRWeightProducer(){}
  34. /////////////////////////////////////////////////////////////////////////////////////
  35. void FSRWeightProducer::beginJob() {}
  36. /////////////////////////////////////////////////////////////////////////////////////
  37. void FSRWeightProducer::endJob(){}
  38. /////////////////////////////////////////////////////////////////////////////////////
  39. void FSRWeightProducer::produce(edm::Event& iEvent, const edm::EventSetup&) {
  40. if (iEvent.isRealData()) return;
  41. edm::Handle<reco::GenParticleCollection> genParticles;
  42. iEvent.getByLabel(genTag_, genParticles);
  43. std::auto_ptr<double> weight (new double);
  44. // Set a default weight to start with
  45. (*weight) = 1.;
  46. unsigned int gensize = genParticles->size();
  47. for (unsigned int i = 0; i<gensize; ++i) {
  48. const reco::GenParticle& lepton = (*genParticles)[i];
  49. if (lepton.status()!=3) continue;
  50. int leptonId = lepton.pdgId();
  51. if (abs(leptonId)!=11 && abs(leptonId)!=13 && abs(leptonId)!=15) continue;
  52. if (lepton.numberOfMothers()!=1) continue;
  53. const reco::Candidate * boson = lepton.mother();
  54. int bosonId = abs(boson->pdgId());
  55. if (bosonId!=23 && bosonId!=24) continue;
  56. double bosonMass = boson->mass();
  57. double leptonMass = lepton.mass();
  58. double leptonEnergy = lepton.energy();
  59. double cosLeptonTheta = cos(lepton.theta());
  60. double sinLeptonTheta = sin(lepton.theta());
  61. double leptonPhi = lepton.phi();
  62. int trueKey = i;
  63. if (lepton.numberOfDaughters()==0) {
  64. continue;
  65. } else if (lepton.numberOfDaughters()==1) {
  66. int otherleptonKey = lepton.daughterRef(0).key();
  67. const reco::GenParticle& otherlepton = (*genParticles)[otherleptonKey];
  68. if (otherlepton.pdgId()!=leptonId) continue;
  69. if (otherlepton.numberOfDaughters()<=1) continue;
  70. trueKey = otherleptonKey;
  71. }
  72. const reco::GenParticle& trueLepton = (*genParticles)[trueKey];
  73. unsigned int nDaughters = trueLepton.numberOfDaughters();
  74. for (unsigned int j = 0; j<nDaughters; ++j) {
  75. const reco::Candidate * photon = trueLepton.daughter(j);
  76. if (photon->pdgId()!=22) continue;
  77. double photonEnergy = photon->energy();
  78. double cosPhotonTheta = cos(photon->theta());
  79. double sinPhotonTheta = sin(photon->theta());
  80. double photonPhi = photon->phi();
  81. double costheta = sinLeptonTheta*sinPhotonTheta*cos(leptonPhi-photonPhi)
  82. + cosLeptonTheta*cosPhotonTheta;
  83. // Missing O(alpha) terms in soft-collinear approach
  84. // Only for W, from hep-ph/0303260
  85. if (bosonId==24) {
  86. double betaLepton = sqrt(1-pow(leptonMass/leptonEnergy,2));
  87. double delta = - 8*photonEnergy *(1-betaLepton*costheta)
  88. / pow(bosonMass,3)
  89. / (1-pow(leptonMass/bosonMass,2))
  90. / (4-pow(leptonMass/bosonMass,2))
  91. * leptonEnergy * (pow(leptonMass,2)/bosonMass+2*photonEnergy);
  92. (*weight) *= (1 + delta);
  93. }
  94. // Missing NLO QED orders in QED parton shower approach
  95. // Change coupling scale from 0 to kT to estimate this effect
  96. (*weight) *= alphaRatio(photonEnergy*sqrt(1-pow(costheta,2)));
  97. }
  98. }
  99. iEvent.put(weight);
  100. }
  101. double FSRWeightProducer::alphaRatio(double pt) {
  102. double pigaga = 0.;
  103. // Leptonic contribution (just one loop, precise at < 0.3% level)
  104. const double alphapi = 1/137.036/M_PI;
  105. const double mass_e = 0.0005;
  106. const double mass_mu = 0.106;
  107. const double mass_tau = 1.777;
  108. const double mass_Z = 91.2;
  109. if (pt>mass_e) pigaga += alphapi * (2*log(pt/mass_e)/3.-5./9.);
  110. if (pt>mass_mu) pigaga += alphapi * (2*log(pt/mass_mu)/3.-5./9.);
  111. if (pt>mass_tau) pigaga += alphapi * (2*log(pt/mass_tau)/3.-5./9.);
  112. // Hadronic vaccum contribution
  113. // Using simple effective parametrization from Physics Letters B 513 (2001) 46.
  114. // Top contribution neglected
  115. double A = 0.;
  116. double B = 0.;
  117. double C = 0.;
  118. if (pt<0.7) {
  119. A = 0.0; B = 0.0023092; C = 3.9925370;
  120. } else if (pt<2.0) {
  121. A = 0.0; B = 0.0022333; C = 4.2191779;
  122. } else if (pt<4.0) {
  123. A = 0.0; B = 0.0024402; C = 3.2496684;
  124. } else if (pt<10.0) {
  125. A = 0.0; B = 0.0027340; C = 2.0995092;
  126. } else if (pt<mass_Z) {
  127. A = 0.0010485; B = 0.0029431; C = 1.0;
  128. } else if (pt<10000.) {
  129. A = 0.0012234; B = 0.0029237; C = 1.0;
  130. } else {
  131. A = 0.0016894; B = 0.0028984; C = 1.0;
  132. }
  133. pigaga += A + B*log(1.+C*pt*pt);
  134. // Done
  135. return 1./(1.-pigaga);
  136. }
  137. DEFINE_FWK_MODULE(FSRWeightProducer);