CMS 3D CMS Logo

 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
List of all members | Classes | Public Member Functions | Private Member Functions | Private Attributes | Static Private Attributes
ParticleReplacerZtautau Class Reference

#include <ParticleReplacerZtautau.h>

Inheritance diagram for ParticleReplacerZtautau:
ParticleReplacerBase

Classes

struct  MinVisPtCut
 
struct  MinVisPtCutCombination
 

Public Member Functions

virtual void beginJob ()
 
virtual void beginRun (edm::Run &, const edm::EventSetup &)
 
virtual void declareExtraProducts (MCParticleReplacer *)
 
virtual void endJob ()
 
 ParticleReplacerZtautau (const edm::ParameterSet &)
 
virtual std::auto_ptr
< HepMC::GenEvent > 
produce (const std::vector< reco::Particle > &, const reco::Vertex *=0, const HepMC::GenEvent *=0, MCParticleReplacer *=0)
 
 ~ParticleReplacerZtautau ()
 
- Public Member Functions inherited from ParticleReplacerBase
virtual void endRun ()
 
 ParticleReplacerBase (const edm::ParameterSet &)
 
virtual ~ParticleReplacerBase ()
 

Private Member Functions

void cleanEvent (HepMC::GenEvent *, HepMC::GenVertex *)
 
HepMC::GenEvent * processEventWithPythia (HepMC::GenEvent *)
 
HepMC::GenEvent * processEventWithTauola (HepMC::GenEvent *)
 
bool testEvent (HepMC::GenEvent *)
 
void transformMuMu2LepLep (CLHEP::HepRandomEngine &randomEngine, reco::Particle *, reco::Particle *)
 
void transformMuMu2TauNu (reco::Particle *, reco::Particle *)
 

Private Attributes

bool applyMuonRadiationCorrection_
 
double beamEnergy_
 
std::string generatorMode_
 
int maxNumberOfAttempts_
 
std::vector
< MinVisPtCutCombination
minVisPtCuts_
 
int motherParticleID_
 
GenMuonRadiationAlgorithmmuonRadiationAlgo_
 
bool printEvent_
 
gen::Pythia6Service pythia_
 
double rfRotationAngle_
 
int targetParticle1AbsPdgID_
 
double targetParticle1Mass_
 
int targetParticle2AbsPdgID_
 
double targetParticle2Mass_
 
gen::TauolaInterfaceBasetauola_
 
unsigned int transformationMode_
 
bool useExternalGenerators_
 
bool useTauola_
 
bool useTauolaPolarization_
 

Static Private Attributes

static bool tauola_isInitialized_ = false
 

Additional Inherited Members

- Public Attributes inherited from ParticleReplacerBase
unsigned int passed_
 
unsigned int tried_
 
- Protected Attributes inherited from ParticleReplacerBase
const double tauMass_
 
int verbosity_
 

Detailed Description

Auxiliary class to replace muons reconstructed in selected Z –> mu+ mu- events by generator level particles, which will be passed to detector simulation & reconstruction modules to create "hybrid" events ("embedded" leptons from Monte Carlo simulation, rest of the event taken from data)

Per default, the reconstructed muons are replaced by generator level tau leptons, which are passed to TAUOLA in order to produce generator level tau decay products.

For systematic/background studies, it is possible also to:

Author
Manuel Zeise
Version
Revision:
1.6
Id:
ParticleReplacerZtautau.h,v 1.6 2013/01/31 09:07:18 veelken Exp

Definition at line 40 of file ParticleReplacerZtautau.h.

Constructor & Destructor Documentation

ParticleReplacerZtautau::ParticleReplacerZtautau ( const edm::ParameterSet cfg)
explicit

Definition at line 43 of file ParticleReplacerZtautau.cc.

References edm::ParameterSet::addParameter(), applyMuonRadiationCorrection_, beamEnergy_, gather_cfg::cout, GOODCOLL_filter_cfg::cut, ParticleReplacerZtautau::MinVisPtCutCombination::cut_string_, ParticleReplacerZtautau::MinVisPtCutCombination::cuts_, edm::hlt::Exception, edm::ParameterSet::exists(), generatorMode_, reco::get(), edm::ParameterSet::getParameter(), ParticleReplacerZtautau::MinVisPtCut::index_, ParticleReplacerZtautau::MinVisPtCut::kELEC, ParticleReplacerZtautau::MinVisPtCut::kHAD, ParticleReplacerZtautau::MinVisPtCut::kMU, ParticleReplacerZtautau::MinVisPtCut::kTAU, maxNumberOfAttempts_, minVisPtCuts_, motherParticleID_, muonRadiationAlgo_, NULL, Pi, rfRotationAngle_, cmsHarvester::sep, AlCaHLTBitMon_QueryRunRegistry::string, tauola_, ParticleReplacerZtautau::MinVisPtCut::threshold_, transformationMode_, ParticleReplacerZtautau::MinVisPtCut::type_, and ParticleReplacerBase::verbosity_.

44  : ParticleReplacerBase(cfg),
45  generatorMode_(cfg.getParameter<std::string>("generatorMode")),
46  beamEnergy_(cfg.getParameter<double>("beamEnergy")),
49  pythia_(cfg)
50 {
51  tauola_ = (gen::TauolaInterfaceBase*)(TauolaFactory::get()->create("Tauolapp113a",cfg.getParameter<edm::ParameterSet>("TauolaOptions")));
52  // settings?
53  // usesResource(edm::SharedResourceNames::kTauola);
54  maxNumberOfAttempts_ = ( cfg.exists("maxNumberOfAttempts") ) ?
55  cfg.getParameter<int>("maxNumberOfAttempts") : 10000;
56 
57  // transformationMode =
58  // 0 - no transformation
59  // 1 - mumu -> tautau
60  // 2 - mumu -> ee
61  // 3 - mumu -> taunu
62  // 4 - munu -> taunu
63  transformationMode_ = ( cfg.exists("transformationMode") ) ?
64  cfg.getParameter<int>("transformationMode") : 1;
65  if ( verbosity_ ) {
66  edm::LogInfo("Replacer") << "generatorMode = " << generatorMode_ << "\n";
67  edm::LogInfo("Replacer") << "transformationMode = " << transformationMode_ << "\n";
68  }
69 
70  motherParticleID_ = ( cfg.exists("motherParticleID") ) ?
71  cfg.getParameter<int>("motherParticleID") : 23;
72 
73  // require generator level visible tau decay products to exceed given transverse momentum.
74  // The purpose of this flag is make maximal use of the available Zmumu events statistics
75  // by not generating tau-paisr which will fail the visible Pt cuts applied on reconstruction level in physics analyses.
76  //
77  // NOTE: the thresholds specified by configuration parameter 'minVisibleTransverseMomentum' need to be a few GeV lower
78  // than the cuts applied on reconstruction level in physics analyses,
79  // to account for resolution effects
80  //
81  if ( cfg.exists("minVisibleTransverseMomentum") ) {
82  std::string minVisibleTransverseMomentumLine = cfg.getParameter<std::string>("minVisibleTransverseMomentum");
83  const char* startptr = minVisibleTransverseMomentumLine.c_str();
84  char* endptr;
85  double d = strtod(startptr, &endptr);
86  if ( *endptr == '\0' && endptr != startptr ) {
87  // fallback for backwards compatibility:
88  // if it's a single number then use this as a threshold for both particles
89  MinVisPtCut cutLeg1;
90  cutLeg1.type_ = MinVisPtCut::kTAU;
91  cutLeg1.threshold_ = d;
92  cutLeg1.index_ = 0;
93  MinVisPtCut cutLeg2;
94  cutLeg2.type_ = MinVisPtCut::kTAU;
95  cutLeg2.threshold_ = d;
96  cutLeg2.index_ = 1;
97  MinVisPtCutCombination minVisPtCut;
98  minVisPtCut.cut_string_ = minVisibleTransverseMomentumLine;
99  minVisPtCut.cuts_.push_back(cutLeg1);
100  minVisPtCut.cuts_.push_back(cutLeg2);
101  minVisPtCuts_.push_back(minVisPtCut);
102  } else {
103  // string has new format:
104  // parse the minVisibleTransverseMomentum string
105  for ( std::string::size_type prev = 0, pos = 0; prev < minVisibleTransverseMomentumLine.length(); prev = pos + 1) {
106  pos = minVisibleTransverseMomentumLine.find(';', prev);
107  if ( pos == std::string::npos ) pos = minVisibleTransverseMomentumLine.length();
108 
109  std::string sub = minVisibleTransverseMomentumLine.substr(prev, pos - prev);
110  MinVisPtCutCombination minVisPtCut;
111  minVisPtCut.cut_string_ = minVisibleTransverseMomentumLine;
112  const char* sub_c = sub.c_str();
113  while (*sub_c != '\0' ) {
114  const char* sep = std::strchr(sub_c, '_');
115  if ( sep == NULL ) throw cms::Exception("Configuration")
116  << "Minimum transverse parameter string must contain an underscore to separate type from Pt threshold !!\n";
117  std::string type(sub_c, sep);
118 
119  MinVisPtCut cut;
120  if ( type == "elec1" ) { cut.type_ = MinVisPtCut::kELEC; cut.index_ = 0; }
121  else if ( type == "mu1" ) { cut.type_ = MinVisPtCut::kMU; cut.index_ = 0; }
122  else if ( type == "had1" ) { cut.type_ = MinVisPtCut::kHAD; cut.index_ = 0; }
123  else if ( type == "tau1" ) { cut.type_ = MinVisPtCut::kTAU; cut.index_ = 0; }
124  else if ( type == "elec2" ) { cut.type_ = MinVisPtCut::kELEC; cut.index_ = 1; }
125  else if ( type == "mu2" ) { cut.type_ = MinVisPtCut::kMU; cut.index_ = 1; }
126  else if ( type == "had2" ) { cut.type_ = MinVisPtCut::kHAD; cut.index_ = 1; }
127  else if ( type == "tau2" ) { cut.type_ = MinVisPtCut::kTAU; cut.index_ = 1; }
128  else throw cms::Exception("Configuration")
129  << "'" << type << "' is not a valid type. Allowed values are { elec1, mu1, had1, tau1, elec2, mu2, had2, tau2 } !!\n";
130 
131  char* endptr;
132  cut.threshold_ = strtod(sep + 1, &endptr);
133  if ( endptr == sep + 1 ) throw cms::Exception("Configuration")
134  << "No Pt threshold given !!\n";
135 
136  std::cout << "Adding vis. Pt cut: index = " << cut.index_ << ", type = " << cut.type_ << ", threshold = " << cut.threshold_ << std::endl;
137  minVisPtCut.cuts_.push_back(cut);
138  sub_c = endptr;
139  }
140  minVisPtCuts_.push_back(minVisPtCut);
141  }
142  }
143  }
144 
145  rfRotationAngle_ = cfg.getParameter<double>("rfRotationAngle")*TMath::Pi()/180.;
146 
147  std::string applyMuonRadiationCorrection_string = cfg.getParameter<std::string>("applyMuonRadiationCorrection");
148  if ( applyMuonRadiationCorrection_string != "" ) {
149  edm::ParameterSet cfgMuonRadiationAlgo;
150  cfgMuonRadiationAlgo.addParameter<double>("beamEnergy", beamEnergy_);
151  cfgMuonRadiationAlgo.addParameter<std::string>("mode", applyMuonRadiationCorrection_string);
152  cfgMuonRadiationAlgo.addParameter<int>("verbosity", 0);
153  edm::ParameterSet cfgPhotosOptions;
154  cfgMuonRadiationAlgo.addParameter<edm::ParameterSet>("PhotosOptions", cfgPhotosOptions);
155  edm::ParameterSet cfgPythiaParameters = cfg.getParameter<edm::ParameterSet>("PythiaParameters");
156  cfgMuonRadiationAlgo.addParameter<edm::ParameterSet>("PythiaParameters", cfgPythiaParameters);
157  muonRadiationAlgo_ = new GenMuonRadiationAlgorithm(cfgMuonRadiationAlgo);
159  }
160 }
const double Pi
type
Definition: HCALResponse.h:21
T getParameter(std::string const &) const
std::vector< MinVisPtCutCombination > minVisPtCuts_
bool exists(std::string const &parameterName) const
checks if a parameter exists
#define NULL
Definition: scimark2.h:8
uint16_t size_type
ParticleReplacerBase(const edm::ParameterSet &)
gen::TauolaInterfaceBase * tauola_
void addParameter(std::string const &name, T const &value)
Definition: ParameterSet.h:142
tuple cout
Definition: gather_cfg.py:121
GenMuonRadiationAlgorithm * muonRadiationAlgo_
T get(const Candidate &c)
Definition: component.h:55
ParticleReplacerZtautau::~ParticleReplacerZtautau ( )

Definition at line 162 of file ParticleReplacerZtautau.cc.

References muonRadiationAlgo_.

163 {
164  delete muonRadiationAlgo_;
165 }
GenMuonRadiationAlgorithm * muonRadiationAlgo_

Member Function Documentation

void ParticleReplacerZtautau::beginJob ( void  )
virtual
void ParticleReplacerZtautau::beginRun ( edm::Run run,
const edm::EventSetup es 
)
virtual

Reimplemented from ParticleReplacerBase.

Definition at line 698 of file ParticleReplacerZtautau.cc.

References gather_cfg::cout, gen::TauolaInterfaceBase::init(), tauola_, and tauola_isInitialized_.

699 {
700  if ( !tauola_isInitialized_ ) {
701  std::cout << "<ParticleReplacerZtautau::beginRun>: Initializing TAUOLA interface." << std::endl;
702  tauola_->init(es);
703  tauola_isInitialized_ = true;
704  }
705 }
virtual void init(const edm::EventSetup &)
gen::TauolaInterfaceBase * tauola_
tuple cout
Definition: gather_cfg.py:121
void ParticleReplacerZtautau::cleanEvent ( HepMC::GenEvent *  genEvt,
HepMC::GenVertex *  genVtx 
)
private

Definition at line 825 of file ParticleReplacerZtautau.cc.

References repairBarcodes().

Referenced by produce().

826 {
827  std::stack<HepMC::GenParticle*> genParticles_to_delete;
828 
829  std::stack<HepMC::GenVertex*> genVertices_to_process;
830  std::stack<HepMC::GenVertex*> genVertices_to_delete;
831 
832  for ( HepMC::GenVertex::particles_out_const_iterator genParticle = genVtx->particles_out_const_begin();
833  genParticle != genVtx->particles_out_const_end(); ++genParticle ) {
834  genParticles_to_delete.push(*genParticle);
835  if ( (*genParticle)->end_vertex() ) genVertices_to_process.push((*genParticle)->end_vertex());
836  }
837 
838  while ( !genVertices_to_process.empty() ) {
839  HepMC::GenVertex* tempVtx = genVertices_to_process.top();
840  if ( tempVtx->particles_out_size() > 0 ) {
841  for ( HepMC::GenVertex::particles_out_const_iterator genParticle = tempVtx->particles_out_const_begin();
842  genParticle != tempVtx->particles_out_const_end(); ++genParticle ) {
843  if ( (*genParticle)->end_vertex() ) genVertices_to_process.push((*genParticle)->end_vertex());
844  }
845  delete tempVtx;
846  }
847  genVertices_to_delete.push(tempVtx);
848  genVertices_to_process.pop();
849  }
850 
851  while ( !genVertices_to_delete.empty() ) {
852  genEvt->remove_vertex(genVertices_to_delete.top());
853  genVertices_to_delete.pop();
854  }
855 
856  while ( !genParticles_to_delete.empty() ) {
857  delete genVtx->remove_particle(genParticles_to_delete.top());
858  genParticles_to_delete.pop();
859  }
860 
862 }
void repairBarcodes(HepMC::GenEvent *)
void ParticleReplacerZtautau::declareExtraProducts ( MCParticleReplacer producer)
virtual

Reimplemented from ParticleReplacerBase.

Definition at line 167 of file ParticleReplacerZtautau.cc.

References MCParticleReplacer::call_produces().

168 {
169  producer->call_produces<ParticleCollection>("muonsBeforeRad");
170  producer->call_produces<ParticleCollection>("muonsAfterRad");
171 }
void call_produces(const std::string &instanceName)
std::vector< reco::Particle > ParticleCollection
void ParticleReplacerZtautau::endJob ( void  )
virtual

Reimplemented from ParticleReplacerBase.

Definition at line 707 of file ParticleReplacerZtautau.cc.

References gen::TauolaInterfaceBase::statistics(), and tauola_.

708 {
709  tauola_->statistics();
710 }
gen::TauolaInterfaceBase * tauola_
HepMC::GenEvent* ParticleReplacerZtautau::processEventWithPythia ( HepMC::GenEvent *  )
private
HepMC::GenEvent* ParticleReplacerZtautau::processEventWithTauola ( HepMC::GenEvent *  )
private
std::auto_ptr< HepMC::GenEvent > ParticleReplacerZtautau::produce ( const std::vector< reco::Particle > &  muons,
const reco::Vertex evtVtx = 0,
const HepMC::GenEvent *  genEvt = 0,
MCParticleReplacer producer = 0 
)
virtual

Implements ParticleReplacerBase.

Definition at line 233 of file ParticleReplacerZtautau.cc.

References funct::abs(), applyMuonRadiationCorrection_, beamEnergy_, MCParticleReplacer::call_put(), call_pyexec(), reco::Particle::charge(), cleanEvent(), GenMuonRadiationAlgorithm::compFSR(), conv, gather_cfg::cout, gen::TauolaInterfaceBase::decay(), decayRandomEngine, deltaR(), alignCSCRings::e, electronMass, edm::hlt::Exception, generatorMode_, configurableAnalysis::GenParticle, edm::RandomNumberGenerator::getEngine(), MCParticleReplacer::getStreamID(), customizeTrackingMonitorSeedNumber::idx, edm::Service< T >::isAvailable(), maxNumberOfAttempts_, motherParticleID_, metsig::muon, muonMass, muonRadiationAlgo_, reco::Particle::p4(), ParticleReplacerBase::passed_, reco::Particle::pdgId(), protonMass, reco::Particle::px(), reco::Particle::py(), pythia_, reco::Particle::pz(), repairBarcodes(), gen::TauolaInterfaceBase::setRandomEngine(), reco::Particle::setStatus(), mathSSE::sqrt(), Clusterizer1DCommons::square(), targetParticle1AbsPdgID_, targetParticle1Mass_, targetParticle2AbsPdgID_, targetParticle2Mass_, tauMass, tauola_, testEvent(), transformationMode_, transformMuMu2LepLep(), transformMuMu2TauNu(), ParticleReplacerBase::tried_, ParticleReplacerBase::verbosity_, and reco::Particle::vertex().

234 {
236  if ( !rng.isAvailable() )
237  throw cms::Exception("Configuration")
238  << "The RandomNumberProducer module requires the RandomNumberGeneratorService\n"
239  << "which appears to be absent. Please add that service to your configuration\n"
240  << "or remove the modules that require it.\n";
241 
242  CLHEP::HepRandomEngine& decayRandomEngine = rng->getEngine(producer->getStreamID());
243  tauola_->setRandomEngine(&decayRandomEngine);
244 
245  if ( evtVtx != 0 ) throw cms::Exception("Configuration")
246  << "ParticleReplacerZtautau does NOT support using primary vertex as the origin for taus !!\n";
247 
248  std::auto_ptr<ParticleCollection> muonsBeforeRad(new ParticleCollection());
249  std::auto_ptr<ParticleCollection> muonsAfterRad(new ParticleCollection());
250 
251 //--- transform the muons to the desired gen. particles
252  std::vector<reco::Particle> embedParticles;
253  if ( transformationMode_ <= 2 ) { // mumu -> ll (Z -> Z boson, l = { e, mu, tau })
254 
255  if ( muons.size() != 2 ) {
256  edm::LogError ("Replacer")
257  << "The decay mode Z->ll requires exactly two muons --> returning empty HepMC event !!" << std::endl;
258  return std::auto_ptr<HepMC::GenEvent>(0);
259  }
260 
261  switch ( transformationMode_ ) {
262  case 0: // mumu -> mumu
265  break;
266  case 1: // mumu -> tautau
269  break;
270  case 2: // mumu -> ee
273  break;
274  default:
275  assert(0);
276  }
279 
280  const reco::Particle& muon1 = muons.at(0);
281  const reco::Particle& muon2 = muons.at(1);
282  reco::Particle embedLepton1(muon1.charge(), muon1.p4(), muon1.vertex(), muon1.pdgId(), 0, true);
283  reco::Particle embedLepton2(muon2.charge(), muon2.p4(), muon2.vertex(), muon2.pdgId(), 0, true);
284  // Also call this for the mumu->mumu case, to set the correct status values
285  // and to apply the rotation:
286  transformMuMu2LepLep(decayRandomEngine, &embedLepton1, &embedLepton2);
287  embedParticles.push_back(embedLepton1);
288  embedParticles.push_back(embedLepton2);
289  } else if ( transformationMode_ == 3 ) { // mumu -> taunu (Z -> W boson)
290 
291  if ( muons.size() != 2 ) {
292  edm::LogError ("Replacer")
293  << "The decay mode W->taunu requires exactly two muons --> returning empty HepMC event !!" << std::endl;
294  return std::auto_ptr<HepMC::GenEvent>(0);
295  }
296 
301 
302  const reco::Particle& muon1 = muons.at(0);
303  const reco::Particle& muon2 = muons.at(1);
304  reco::Particle embedTau(muon1.charge(), muon1.p4(), muon1.vertex(), muon1.pdgId(), 0, true);
305  reco::Particle embedNu(muon2.charge(), muon2.p4(), muon2.vertex(), muon2.pdgId(), 0, true);
306  transformMuMu2TauNu(&embedTau, &embedNu);
307  embedParticles.push_back(embedTau);
308  embedParticles.push_back(embedNu);
309  } else if ( transformationMode_ == 4 ) { // munu -> taunu (W -> W boson)
310 
311  if ( muons.size() != 2 ) {
312  edm::LogError ("Replacer")
313  << "The decay mode W->taunu requires exactly two gen. leptons --> returning empty HepMC event !!" << std::endl;
314  return std::auto_ptr<HepMC::GenEvent>(0);
315  }
316 
321 
322  const reco::Particle& muon = muons.at(0);
323  double embedLeptonEn = sqrt(square(muon.px()) + square(muon.py()) + square(muon.pz()) + square(targetParticle1Mass_));
324  reco::Candidate::LorentzVector embedTauP4(muon.px(), muon.py(), muon.pz(), embedLeptonEn);
325  reco::Particle embedTau(muon.charge(), embedTauP4, muon.vertex(), targetParticle1AbsPdgID_*muon.pdgId()/std::abs(muon.pdgId()), 0, true);
326  embedTau.setStatus(1);
327  embedParticles.push_back(embedTau);
328  const reco::Particle& nu = muons.at(1);
329  reco::Particle embedNu(0, nu.p4(), nu.vertex(), -targetParticle2AbsPdgID_*muon.pdgId()/std::abs(muon.pdgId()), 0, true);
330  embedNu.setStatus(1);
331  embedParticles.push_back(embedNu);
332  }
333 
334  if ( embedParticles.size() != 2 ){
335  edm::LogError ("Replacer")
336  << "The creation of gen. particles failed somehow --> returning empty HepMC event !!" << std::endl;
337  return std::auto_ptr<HepMC::GenEvent>(0);
338  }
339 
340  HepMC::GenEvent* genEvt_output = 0;
341 
342  HepMC::GenVertex* genVtx_output = new HepMC::GenVertex();
343 
344  HepMC::GenVertex* ppCollisionVtx = 0;
345 
346  std::vector<reco::Candidate::LorentzVector> auxPhotonP4s;
347 
348 //--- prepare the output HepMC event
349  if ( genEvt ) { // embed gen. leptons into existing HepMC event
350  genEvt_output = new HepMC::GenEvent(*genEvt);
351 
352  for ( HepMC::GenEvent::vertex_iterator genVtx = genEvt_output->vertices_begin();
353  genVtx != genEvt_output->vertices_end(); ++genVtx ) {
354 
355  if ( (*genVtx)->particles_out_size() <= 0 || (*genVtx)->particles_in_size() <= 0 ) continue;
356 
357  bool foundMuon1 = false;
358  bool foundMuon2 = false;
359  bool foundZ = false;
360  for ( HepMC::GenVertex::particles_out_const_iterator genParticle = (*genVtx)->particles_out_const_begin();
361  genParticle != (*genVtx)->particles_out_const_end(); ++genParticle ) {
362  if ( (*genParticle)->pdg_id() == 13 ) foundMuon1 = true;
363  if ( (*genParticle)->pdg_id() == -13 ) foundMuon2 = true;
364  if ( (*genParticle)->pdg_id() == 23 ) foundZ = true;
365  }
366 
367  int motherPdgId = (*(*genVtx)->particles_in_const_begin())->pdg_id();
368 
369  if ( ((*genVtx)->particles_out_size() == 2 &&
370  (*genVtx)->particles_in_size() > 0 &&
371  motherPdgId == 23 &&
372  foundMuon1 &&
373  foundMuon2 ) ||
374  ((*genVtx)->particles_out_size() > 2 &&
375  (*genVtx)->particles_in_size() > 0 &&
376  motherPdgId == 23 &&
377  foundMuon1 &&
378  foundMuon2 &&
379  foundZ ) ) {
380  genVtx_output = (*genVtx);
381  }
382  }
383 
384  cleanEvent(genEvt_output, genVtx_output);
385 
386  // prevent a decay of existing particles
387  // (the decay of existing particles is a bug in the PythiaInterface which should be fixed in newer versions) <-- to be CHECKed (*)
388  for ( HepMC::GenEvent::particle_iterator genParticle = genEvt_output->particles_begin();
389  genParticle != genEvt_output->particles_end(); ++genParticle ) {
390  (*genParticle)->set_status(0);
391  }
392 
393  for ( std::vector<reco::Particle>::const_iterator embedParticle = embedParticles.begin();
394  embedParticle != embedParticles.end(); ++embedParticle ) {
396  reco::Candidate::LorentzVector sumOtherParticlesP4(0.,0.,0.,0.);
397  for ( std::vector<reco::Particle>::const_iterator otherParticle = embedParticles.begin();
398  otherParticle != embedParticles.end(); ++otherParticle ) {
399  if ( deltaR(otherParticle->p4(), embedParticle->p4()) > 1.e-3 ) sumOtherParticlesP4 += otherParticle->p4();
400  }
401  int errorFlag = 0;
402  reco::Candidate::LorentzVector muonFSR = muonRadiationAlgo_->compFSR(producer->getStreamID(), embedParticle->p4(), embedParticle->charge(), sumOtherParticlesP4, errorFlag);
403  double embedParticlePx_corrected = embedParticle->px() + muonFSR.px();
404  double embedParticlePy_corrected = embedParticle->py() + muonFSR.py();
405  double embedParticlePz_corrected = embedParticle->pz() + muonFSR.pz();
406  double embedParticleEn_corrected = sqrt(square(embedParticlePx_corrected) + square(embedParticlePy_corrected) + square(embedParticlePz_corrected) + square(embedParticle->mass()));
407  reco::Candidate::LorentzVector embedParticleP4_corrected(embedParticlePx_corrected, embedParticlePy_corrected, embedParticlePz_corrected, embedParticleEn_corrected);
408  genVtx_output->add_particle_out(new HepMC::GenParticle((HepMC::FourVector)embedParticleP4_corrected, embedParticle->pdgId(), 1, HepMC::Flow(), HepMC::Polarization(0,0)));
409  // CV: add photon of energy matching muon FSR correction
410  // in opposite eta, phi direction to preserve transverse momentum balance
411  auxPhotonP4s.push_back(reco::Candidate::LorentzVector(-muonFSR.px(), -muonFSR.py(), -muonFSR.pz(), sqrt(square(muonFSR.px()) + square(muonFSR.py()) + square(muonFSR.pz()))));
412  // CV: assume pp collision vertex to be simply the first vertex;
413  // should not really matter as long as pointer is not null...
414  ppCollisionVtx = (*genEvt_output->vertices_begin());
415  assert(ppCollisionVtx);
416 
417  muonsBeforeRad->push_back(reco::Particle(embedParticle->charge(), embedParticle->p4(), embedParticle->vertex(), embedParticle->pdgId()));
418  muonsAfterRad->push_back(reco::Particle(embedParticle->charge(), embedParticleP4_corrected, embedParticle->vertex(), embedParticle->pdgId()));
419  } else {
420  genVtx_output->add_particle_out(new HepMC::GenParticle((HepMC::FourVector)embedParticle->p4(), embedParticle->pdgId(), 1, HepMC::Flow(), HepMC::Polarization(0,0)));
421  }
422  }
423  } else { // embed gen. leptons into new (empty) HepMC event
424  reco::Particle::LorentzVector genMotherP4;
425  double ppCollisionPosX = 0.;
426  double ppCollisionPosY = 0.;
427  double ppCollisionPosZ = 0.;
428  int idx = 0;
429  for ( std::vector<reco::Particle>::const_iterator embedParticle = embedParticles.begin();
430  embedParticle != embedParticles.end(); ++embedParticle ) {
431  //std::cout << "embedParticle #" << idx << ": Pt = " << embedParticle->pt() << ","
432  // << " eta = " << embedParticle->eta() << ", phi = " << embedParticle->phi() << ", mass = " << embedParticle->mass() << std::endl;
433  //std::cout << "(production vertex: x = " << embedParticle->vertex().x() << ", y = " << embedParticle->vertex().y() << ", z = " << embedParticle->vertex().z() << ")" << std::endl;
434  genMotherP4 += embedParticle->p4();
435  const reco::Particle::Point& embedParticleVertex = embedParticle->vertex();
436  ppCollisionPosX += embedParticleVertex.x();
437  ppCollisionPosY += embedParticleVertex.y();
438  ppCollisionPosZ += embedParticleVertex.z();
439  ++idx;
440  }
441 
442  int numEmbedParticles = embedParticles.size();
443  if ( numEmbedParticles > 0 ) {
444  ppCollisionPosX /= numEmbedParticles;
445  ppCollisionPosY /= numEmbedParticles;
446  ppCollisionPosZ /= numEmbedParticles;
447  }
448 
449  ppCollisionVtx = new HepMC::GenVertex(HepMC::FourVector(ppCollisionPosX*10., ppCollisionPosY*10., ppCollisionPosZ*10., 0.)); // convert from cm to mm
450  double protonEn = beamEnergy_;
451  double protonPz = sqrt(square(protonEn) - square(protonMass));
452  ppCollisionVtx->add_particle_in(new HepMC::GenParticle(HepMC::FourVector(0., 0., +protonPz, protonEn), 2212, 3));
453  ppCollisionVtx->add_particle_in(new HepMC::GenParticle(HepMC::FourVector(0., 0., -protonPz, protonEn), 2212, 3));
454 
455  HepMC::GenVertex* genMotherDecayVtx = new HepMC::GenVertex(HepMC::FourVector(ppCollisionPosX*10., ppCollisionPosY*10., ppCollisionPosZ*10., 0.)); // Z decays immediately
456  HepMC::GenParticle* genMother = new HepMC::GenParticle((HepMC::FourVector)genMotherP4, motherParticleID_, (generatorMode_ == "Pythia" ? 3 : 2), HepMC::Flow(), HepMC::Polarization(0,0));
457  if ( transformationMode_ == 3 ) {
458  int chargedLepPdgId = embedParticles.begin()->pdgId(); // first daughter particle is charged lepton always
459  int motherPdgId = -24*chargedLepPdgId/std::abs(chargedLepPdgId);
460  genMother->set_pdg_id(motherPdgId);
461  }
462 
463  ppCollisionVtx->add_particle_out(genMother);
464 
465  genMotherDecayVtx->add_particle_in(genMother);
466  for ( std::vector<reco::Particle>::const_iterator embedParticle = embedParticles.begin();
467  embedParticle != embedParticles.end(); ++embedParticle ) {
469  reco::Candidate::LorentzVector sumOtherParticlesP4(0.,0.,0.,0.);
470  for ( std::vector<reco::Particle>::const_iterator otherParticle = embedParticles.begin();
471  otherParticle != embedParticles.end(); ++otherParticle ) {
472  if ( deltaR(otherParticle->p4(), embedParticle->p4()) > 1.e-3 ) sumOtherParticlesP4 += otherParticle->p4();
473  }
474  //std::cout << "embedParticle:"
475  // << " En = " << embedParticle->energy() << ","
476  // << " Px = " << embedParticle->px() << ","
477  // << " Py = " << embedParticle->py() << ","
478  // << " Pz = " << embedParticle->pz() << std::endl;
479  int errorFlag = 0;
480  reco::Candidate::LorentzVector muonFSR = muonRadiationAlgo_->compFSR(producer->getStreamID(), embedParticle->p4(), embedParticle->charge(), sumOtherParticlesP4, errorFlag);
481  //std::cout << "muonFSR:"
482  // << " En = " << muonFSR.E() << ","
483  // << " Px = " << muonFSR.px() << ","
484  // << " Py = " << muonFSR.py() << ","
485  // << " Pz = " << muonFSR.pz() << std::endl;
486  double embedParticlePx_corrected = embedParticle->px() + muonFSR.px();
487  double embedParticlePy_corrected = embedParticle->py() + muonFSR.py();
488  double embedParticlePz_corrected = embedParticle->pz() + muonFSR.pz();
489  double embedParticleEn_corrected = sqrt(square(embedParticlePx_corrected) + square(embedParticlePy_corrected) + square(embedParticlePz_corrected) + square(embedParticle->mass()));
490  reco::Candidate::LorentzVector embedParticleP4_corrected(embedParticlePx_corrected, embedParticlePy_corrected, embedParticlePz_corrected, embedParticleEn_corrected);
491  //std::cout << "embedParticle (corrected):"
492  // << " En = " << embedParticleP4_corrected.E() << ","
493  // << " Px = " << embedParticleP4_corrected.px() << ","
494  // << " Py = " << embedParticleP4_corrected.py() << ","
495  // << " Pz = " << embedParticleP4_corrected.pz() << std::endl;
496  genMotherDecayVtx->add_particle_out(new HepMC::GenParticle((HepMC::FourVector)embedParticleP4_corrected, embedParticle->pdgId(), 1, HepMC::Flow(), HepMC::Polarization(0,0)));
497  // CV: add photon of energy matching muon FSR correction
498  // in opposite eta, phi direction to preserve transverse momentum balance
499  auxPhotonP4s.push_back(reco::Candidate::LorentzVector(-muonFSR.px(), -muonFSR.py(), -muonFSR.pz(), sqrt(square(muonFSR.px()) + square(muonFSR.py()) + square(muonFSR.pz()))));
500 
501  muonsBeforeRad->push_back(reco::Particle(embedParticle->charge(), embedParticleP4_corrected, embedParticle->vertex(), embedParticle->pdgId()));
502  muonsAfterRad->push_back(reco::Particle(embedParticle->charge(), embedParticle->p4(), embedParticle->vertex(), embedParticle->pdgId()));
503  } else {
504  genMotherDecayVtx->add_particle_out(new HepMC::GenParticle((HepMC::FourVector)embedParticle->p4(), embedParticle->pdgId(), 1, HepMC::Flow(), HepMC::Polarization(0,0)));
505  }
506  }
507 
508  genEvt_output = new HepMC::GenEvent();
509  genEvt_output->add_vertex(ppCollisionVtx);
510  genEvt_output->add_vertex(genMotherDecayVtx);
511 
512  repairBarcodes(genEvt_output);
513  }
514 
515 //--- compute probability to pass visible Pt cuts
516  HepMC::GenEvent* passedEvt_output = 0;
517 
518  unsigned int numEvents_tried = 0;
519  unsigned int numEvents_passed = 0;
520 
521  int verbosity_backup = verbosity_;
522 
523  HepMC::IO_HEPEVT conv;
524  for ( int iTrial = 0; iTrial < maxNumberOfAttempts_; ++iTrial ) {
525  HepMC::GenEvent* tempEvt = new HepMC::GenEvent(*genEvt_output);
526  ++numEvents_tried;
527  if ( generatorMode_ == "Pythia" ) { // Pythia
528  throw cms::Exception("Configuration")
529  << "Pythia is currently not supported !!\n";
530  } else if ( generatorMode_ == "Tauola" ) { // TAUOLA
531  conv.write_event(tempEvt);
532  HepMC::GenEvent* decayEvt = tauola_->decay(tempEvt);
533  // This code only works if decay() modifies the event inplace. This seems
534  // to have changed between CMSSW_5_3_X and CMSSW_7_0_0
535  // (possible with the introduction of tauola++?), so make sure this
536  // assumption is correct:
537  assert(decayEvt == tempEvt);
538  }
539 
540  bool passesVisPtCuts = testEvent(tempEvt);
541  if ( passesVisPtCuts ) {
542  if ( !passedEvt_output ) passedEvt_output = tempEvt; // store first HepMC event passing visible Pt cuts in output file
543  else delete tempEvt;
544  ++numEvents_passed;
545  verbosity_ = 0;
546  } else {
547  delete tempEvt;
548  }
549  }
550 
551  tried_ = numEvents_tried;
552  passed_ = numEvents_passed;
553  verbosity_ = verbosity_backup;
554 
555  if ( !passedEvt_output ) {
556  edm::LogError ("Replacer")
557  << "Failed to create an event which satisfies the visible Pt cuts !!" << std::endl;
558  int idx = 0;
559  for ( std::vector<reco::Particle>::const_iterator muon = muons.begin();
560  muon != muons.end(); ++muon ) {
561  std::cout << " muon #" << idx << " (charge = " << muon->charge() << "): Pt = " << muon->pt() << ", eta = " << muon->eta() << ", phi = " << muon->phi() << std::endl;
562  ++idx;
563  }
564  return std::auto_ptr<HepMC::GenEvent>(0);
565  }
566 
567  // use PYTHIA to decay unstable hadrons (e.g. pi0 -> gamma gamma)
568  //std::cout << "before pi0 -> gamma gamma decays:" << std::endl;
569  //passedEvt_output->print(std::cout);
570 
571  conv.write_event(passedEvt_output);
572 
573  gen::Pythia6Service::InstanceWrapper pythia6InstanceGuard(&pythia_);
574 
575  // convert hepevt -> pythia
576  call_pyhepc(2);
577 
578  // call PYTHIA
579  call_pyexec();
580 
581  // convert pythia -> hepevt
582  call_pyhepc(1);
583 
584  HepMC::GenEvent* passedEvt_pythia = conv.read_next_event();
585  //std::cout << "PYTHIA output:" << std::endl;
586  //passedEvt_pythia->print(std::cout);
587 
588  // CV: back and forth conversion between HepMC and PYTHIA causes
589  // pp -> Z vertex to get corrupted for some reason;
590  // do **not** take HepMC::GenEvent from PYTHIA,
591  // but add decays of unstable particles to original HepMC::GenEvent
592  for ( HepMC::GenEvent::vertex_const_iterator genVertex_pythia = passedEvt_pythia->vertices_begin();
593  genVertex_pythia != passedEvt_pythia->vertices_end(); ++genVertex_pythia ) {
594  bool isDecayVertex = ((*genVertex_pythia)->particles_in_size() >= 1 && (*genVertex_pythia)->particles_out_size() >= 2);
595  for ( HepMC::GenEvent::vertex_const_iterator genVertex_output = passedEvt_output->vertices_begin();
596  genVertex_output != passedEvt_output->vertices_end(); ++genVertex_output ) {
597  if ( matchesGenVertex(*genVertex_output, *genVertex_pythia, true, false) ) isDecayVertex = false;
598  }
599  if ( !isDecayVertex ) continue;
600 
601  // create new vertex
602  //std::cout << "creating decay vertex: barcode = " << (*genVertex_pythia)->barcode() << std::endl;
603  HepMC::GenVertex* genVertex_output = new HepMC::GenVertex((*genVertex_pythia)->position());
604 
605  // associate "incoming" particles to new vertex
606  for ( HepMC::GenVertex::particles_in_const_iterator genParticle_pythia = (*genVertex_pythia)->particles_in_const_begin();
607  genParticle_pythia != (*genVertex_pythia)->particles_in_const_end(); ++genParticle_pythia ) {
608  for ( HepMC::GenEvent::particle_iterator genParticle_output = passedEvt_output->particles_begin();
609  genParticle_output != passedEvt_output->particles_end(); ++genParticle_output ) {
610  if ( matchesGenParticle(*genParticle_output, *genParticle_pythia) ) {
611  //std::cout << " adding 'incoming' particle: barcode = " << (*genParticle_output)->barcode() << std::endl;
612  genVertex_output->add_particle_in(*genParticle_output);
613  // flag "incoming" particle to be unstable
614  (*genParticle_output)->set_status(2);
615  }
616  }
617  }
618 
619  // create "outgoing" particles and associate them to new vertex
620  for ( HepMC::GenVertex::particles_out_const_iterator genParticle_pythia = (*genVertex_pythia)->particles_out_const_begin();
621  genParticle_pythia != (*genVertex_pythia)->particles_out_const_end(); ++genParticle_pythia ) {
622  HepMC::GenParticle* genParticle_output = new HepMC::GenParticle(
623  (*genParticle_pythia)->momentum(),
624  (*genParticle_pythia)->pdg_id(),
625  (*genParticle_pythia)->status(),
626  (*genParticle_pythia)->flow(),
627  (*genParticle_pythia)->polarization());
628  genParticle_output->suggest_barcode((*genParticle_pythia)->barcode());
629  //std::cout << " adding 'outgoing' particle: barcode = " << genParticle_output->barcode() << std::endl;
630  genVertex_output->add_particle_out(genParticle_output);
631  }
632 
633  //std::cout << "adding decay vertex: barcode = " << genVertex_output->barcode() << std::endl;
634  passedEvt_output->add_vertex(genVertex_output);
635 
636  // CV: add auxiliary photons correcting transverse momentum balance
637  // in case corrections for muon --> muon + gamma radiation are applied
638  // after TAUOLA has run, in order not to confuse TAUOLA (polarization)
640  for ( std::vector<reco::Candidate::LorentzVector>::const_iterator auxPhotonP4 = auxPhotonP4s.begin();
641  auxPhotonP4 != auxPhotonP4s.end(); ++auxPhotonP4 ) {
642  ppCollisionVtx->add_particle_out(new HepMC::GenParticle((HepMC::FourVector)*auxPhotonP4, 22, 1, HepMC::Flow(), HepMC::Polarization(0,0)));
643  }
644  }
645  }
646  delete passedEvt_pythia;
647 
648  //std::cout << "after pi0 -> gamma gamma decays:" << std::endl;
649  //passedEvt_output->print(std::cout);
650 
651  // undo the "hack" (*):
652  // recover the particle status codes
653  if ( genEvt ) {
654  for ( HepMC::GenEvent::particle_iterator genParticle = passedEvt_output->particles_begin();
655  genParticle != passedEvt_output->particles_end(); ++genParticle ) {
656  if ( (*genParticle)->end_vertex() ) (*genParticle)->set_status(2);
657  else (*genParticle)->set_status(1);
658  }
659  }
660 
661  // check that transverse momentum of embedded Z -> tautau matches
662  // transverse momentum of replaced di-muon system
663  reco::Candidate::LorentzVector sumMuonP4_replaced(0.,0.,0.,0.);
664  for ( std::vector<reco::Particle>::const_iterator muon = muons.begin();
665  muon != muons.end(); ++muon ) {
666  sumMuonP4_replaced += muon->p4();
667  }
668  reco::Candidate::LorentzVector sumMuonP4_embedded(0.,0.,0.,0.);
669  if ( genEvt ) {
670  for ( HepMC::GenEvent::particle_iterator genParticle = passedEvt_output->particles_begin();
671  genParticle != passedEvt_output->particles_end(); ++genParticle ) {
672  if ( (*genParticle)->status() != 1 ) continue;
673  if ( abs((*genParticle)->pdg_id()) == 12 || abs((*genParticle)->pdg_id()) == 14 || abs((*genParticle)->pdg_id()) == 16 ) continue;
674  sumMuonP4_embedded += reco::Candidate::LorentzVector((*genParticle)->momentum().px(), (*genParticle)->momentum().py(), (*genParticle)->momentum().pz(), (*genParticle)->momentum().e());
675  }
676  }
677  if ( (sumMuonP4_embedded.pt() - sumMuonP4_replaced.pt()) > (1.e-3*sumMuonP4_replaced.pt()) ) {
678  edm::LogWarning ("<MCEmbeddingValidationAnalyzer::analyze>")
679  << "Transverse momentum of embedded tau leptons = " << sumMuonP4_embedded.pt()
680  << " differs from transverse momentum of replaced muons = " << sumMuonP4_replaced.pt() << " !!" << std::endl;
681  }
682 
683  std::auto_ptr<HepMC::GenEvent> passedEvt_output_ptr(passedEvt_output);
684  if ( verbosity_ ) {
685  passedEvt_output_ptr->print(std::cout);
686  std::cout << " numEvents: tried = " << numEvents_tried << ", passed = " << numEvents_passed << std::endl;
687  }
688 
689  delete genVtx_output;
690  delete genEvt_output;
691 
692  producer->call_put(muonsBeforeRad, "muonsBeforeRad");
693  producer->call_put(muonsAfterRad, "muonsAfterRad");
694 
695  return passedEvt_output_ptr;
696 }
double px() const
x coordinate of momentum vector
Definition: Particle.cc:140
CLHEP::HepRandomEngine * decayRandomEngine
static HepMC::IO_HEPEVT conv
const double protonMass
Definition: V0Fitter.cc:40
void call_pyexec()
Definition: extraPythia.cc:3
void transformMuMu2LepLep(CLHEP::HepRandomEngine &randomEngine, reco::Particle *, reco::Particle *)
const LorentzVector & p4() const
four-momentum Lorentz vector
Definition: Particle.cc:86
edm::StreamID getStreamID() const
const double muonMass
void cleanEvent(HepMC::GenEvent *, HepMC::GenVertex *)
double eta() const
momentum pseudorapidity
Definition: Particle.cc:168
void transformMuMu2TauNu(reco::Particle *, reco::Particle *)
double phi() const
momentum azimuthal angle
Definition: Particle.cc:159
const double tauMass
void call_put(T &product, const std::string &instanceName)
gen::TauolaInterfaceBase * tauola_
T sqrt(T t)
Definition: SSEVec.h:48
bool testEvent(HepMC::GenEvent *)
bool isAvailable() const
Definition: Service.h:46
math::XYZPoint Point
point in the space
Definition: Particle.h:31
Abs< T >::type abs(const T &t)
Definition: Abs.h:22
const Point & vertex() const
vertex position
Definition: Particle.cc:226
double pt() const
transverse momentum
Definition: Particle.cc:155
reco::Candidate::LorentzVector compFSR(const edm::StreamID &streamID, const reco::Candidate::LorentzVector &, int, const reco::Candidate::LorentzVector &, int &)
double deltaR(double eta1, double eta2, double phi1, double phi2)
Definition: TreeUtility.cc:17
tuple idx
DEBUGGING if hasattr(process,&quot;trackMonIterativeTracking2012&quot;): print &quot;trackMonIterativeTracking2012 D...
double pz() const
z coordinate of momentum vector
Definition: Particle.cc:150
int pdgId() const
PDG identifier.
Definition: Particle.cc:246
virtual HepMC::GenEvent * decay(HepMC::GenEvent *evt)
virtual CLHEP::HepRandomEngine & getEngine(StreamID const &) const =0
Use this engine in event methods.
const double electronMass
math::XYZTLorentzVector LorentzVector
Lorentz vector.
Definition: Candidate.h:41
void repairBarcodes(HepMC::GenEvent *)
tuple muons
Definition: patZpeak.py:38
double square(const double a)
tuple cout
Definition: gather_cfg.py:121
VertexRefVector::iterator vertex_iterator
iterator over a vector of references to Vertex objects in the same collection
Definition: VertexFwd.h:19
double py() const
y coordinate of momentum vector
Definition: Particle.cc:145
virtual void setRandomEngine(CLHEP::HepRandomEngine *v)=0
int charge() const
electric charge
Definition: Particle.cc:70
math::XYZTLorentzVector LorentzVector
Lorentz vector.
Definition: Particle.h:27
GenMuonRadiationAlgorithm * muonRadiationAlgo_
std::vector< reco::Particle > ParticleCollection
bool ParticleReplacerZtautau::testEvent ( HepMC::GenEvent *  genEvt)
private

Definition at line 712 of file ParticleReplacerZtautau.cc.

References funct::abs(), runEdmFileComparison::collection, gather_cfg::cout, GOODCOLL_filter_cfg::cut, configurableAnalysis::GenParticle, ParticleReplacerZtautau::MinVisPtCut::kELEC, ParticleReplacerZtautau::MinVisPtCut::kHAD, ParticleReplacerZtautau::MinVisPtCut::kMU, ParticleReplacerZtautau::MinVisPtCut::kTAU, minVisPtCuts_, python.multivaluedict::sort(), AlCaHLTBitMon_QueryRunRegistry::string, and ParticleReplacerBase::verbosity_.

Referenced by produce().

713 {
714  //if ( verbosity_ ) std::cout << "<ParticleReplacerZtautau::testEvent>:" << std::endl;
715 
716  if ( minVisPtCuts_.empty() ) return true; // no visible Pt cuts applied
717 
718  std::vector<double> muonPts;
719  std::vector<double> electronPts;
720  std::vector<double> tauJetPts;
721  std::vector<double> tauPts;
722 
723  int genParticleIdx = 0;
724  for ( HepMC::GenEvent::particle_iterator genParticle = genEvt->particles_begin();
725  genParticle != genEvt->particles_end(); ++genParticle ) {
726  if ( abs((*genParticle)->pdg_id()) == 15 && (*genParticle)->end_vertex() ) {
728  std::queue<const HepMC::GenParticle*> decayProducts;
729  decayProducts.push(*genParticle);
730  enum { kELEC, kMU, kHAD };
731  int type = kHAD;
732  int decayProductIdx = 0;
733  while ( !decayProducts.empty() && decayProductIdx < 100 ) { // CV: protection against entering infinite loop in case of corrupt particle relations
734  const HepMC::GenParticle* decayProduct = decayProducts.front();
735  if ( verbosity_ ) {
736  std::cout << "decayProduct #" << (decayProductIdx + 1) << " (pdgId = " << decayProduct->pdg_id() << "):"
737  << " Pt = " << decayProduct->momentum().perp() << ", eta = " << decayProduct->momentum().eta() << ", phi = " << decayProduct->momentum().phi()
738  << std::endl;
739  }
740  decayProducts.pop();
741  if ( !decayProduct->end_vertex() ) { // stable decay product
742  int absPdgId = abs(decayProduct->pdg_id());
743  if ( !(absPdgId == 12 || absPdgId == 14 || absPdgId == 16) ) visP4 += (reco::Candidate::LorentzVector)decayProduct->momentum();
744  if ( absPdgId == 11 ) type = kELEC;
745  if ( absPdgId == 13 ) type = kMU;
746  } else { // decay product decays further...
747  HepMC::GenVertex* decayVtx = decayProduct->end_vertex();
748  for ( HepMC::GenVertex::particles_out_const_iterator daughter = decayVtx->particles_out_const_begin();
749  daughter != decayVtx->particles_out_const_end(); ++daughter ) {
750  decayProducts.push(*daughter);
751  }
752  }
753  ++decayProductIdx;
754  }
755 
756  double visPt = visP4.pt();
757  tauPts.push_back(visPt);
758  if ( type == kMU ) muonPts.push_back(visPt);
759  else if ( type == kELEC ) electronPts.push_back(visPt);
760  else if ( type == kHAD ) tauJetPts.push_back(visPt);
761  if ( verbosity_ ) {
762  std::string type_string = "";
763  if ( type == kMU ) type_string = "mu";
764  else if ( type == kELEC ) type_string = "elec";
765  else if ( type == kHAD ) type_string = "had";
766  std::cout << "visLeg #" << (genParticleIdx + 1) << " (type = " << type_string << "):"
767  << " Pt = " << visP4.pt() << ", eta = " << visP4.eta() << ", phi = " << visP4.phi()
768  << " (X = " << (visP4.energy()/(*genParticle)->momentum().e()) << ")" << std::endl;
769  }
770  ++genParticleIdx;
771  }
772  }
773 
774  std::sort(tauPts.begin(), tauPts.end(), std::greater<double>());
775  std::sort(electronPts.begin(), electronPts.end(), std::greater<double>());
776  std::sort(muonPts.begin(), muonPts.end(), std::greater<double>());
777  std::sort(tauJetPts.begin(), tauJetPts.end(), std::greater<double>());
778 
779  // check if visible decay products pass Pt cuts
780  //
781  // NOTE: return value = True if leg1 > threshold[i] && leg2 > threshold[i] for **any** path i
782  // (e.g. (leg1Pt > 10 && leg2Pt > 20) || (leg1Pt > 20 && leg2Pt > 10), consistent with logic used by HLT)
783  //
784  for ( std::vector<MinVisPtCutCombination>::const_iterator minVisPtCut = minVisPtCuts_.begin();
785  minVisPtCut != minVisPtCuts_.end(); ++minVisPtCut ) {
786  //if ( verbosity_ ) minVisPtCut->print(std::cout);
787 
788  bool passesMinVisCut = true;
789 
790  for ( std::vector<MinVisPtCut>::const_iterator cut = minVisPtCut->cuts_.begin();
791  cut != minVisPtCut->cuts_.end(); ++cut ) {
792  std::vector<double>* collection = 0;
793  switch ( cut->type_ ) {
794  case MinVisPtCut::kELEC:
795  collection = &electronPts;
796  break;
797  case MinVisPtCut::kMU:
798  collection = &muonPts;
799  break;
800  case MinVisPtCut::kHAD:
801  collection = &tauJetPts;
802  break;
803  case MinVisPtCut::kTAU:
804  collection = &tauPts;
805  break;
806  }
807  assert(collection);
808 
809  // j-th tau decay product fails visible Pt cut
810  if ( cut->index_ >= collection->size() || (*collection)[cut->index_] < cut->threshold_ ) {
811  passesMinVisCut = false;
812  break;
813  }
814  }
815 
816  // all tau decay products satisfy visible Pt cuts for i-th path
817  //if ( verbosity_ ) std::cout << "passes vis. Pt cuts = " << passesMinVisCut << std::endl;
818  if ( passesMinVisCut ) return true;
819  }
820 
821  // visible Pt cuts failed for all paths
822  return false;
823 }
type
Definition: HCALResponse.h:21
std::vector< MinVisPtCutCombination > minVisPtCuts_
Abs< T >::type abs(const T &t)
Definition: Abs.h:22
math::XYZTLorentzVector LorentzVector
Lorentz vector.
Definition: Candidate.h:41
tuple cout
Definition: gather_cfg.py:121
void ParticleReplacerZtautau::transformMuMu2LepLep ( CLHEP::HepRandomEngine &  randomEngine,
reco::Particle muon1,
reco::Particle muon2 
)
private

Definition at line 887 of file ParticleReplacerZtautau.cc.

References funct::abs(), gather_cfg::cout, alignCSCRings::e, reco::Particle::p4(), reco::Particle::pdgId(), Pi, reco::print(), RecoTauCleanerPlugins::pt, rfRotationAngle_, svgfig::rotate(), reco::Particle::setP4(), reco::Particle::setPdgId(), reco::Particle::setStatus(), mathSSE::sqrt(), Clusterizer1DCommons::square(), targetParticle1AbsPdgID_, targetParticle1Mass_, targetParticle2AbsPdgID_, targetParticle2Mass_, and ParticleReplacerBase::verbosity_.

Referenced by produce().

888 {
889 //--- transform a muon pair into an electron/tau pair,
890 // taking into account the difference between muon and electron/tau mass
891 
892  reco::Particle::LorentzVector muon1P4_lab = muon1->p4();
893  reco::Particle::LorentzVector muon2P4_lab = muon2->p4();
894  reco::Particle::LorentzVector zP4_lab = muon1P4_lab + muon2P4_lab;
895 
896  ROOT::Math::Boost boost_to_rf(zP4_lab.BoostToCM());
897  ROOT::Math::Boost boost_to_lab(boost_to_rf.Inverse());
898 
899  reco::Particle::LorentzVector zP4_rf = boost_to_rf(zP4_lab);
900 
901  reco::Particle::LorentzVector muon1P4_rf = boost_to_rf(muon1P4_lab);
902  reco::Particle::LorentzVector muon2P4_rf = boost_to_rf(muon2P4_lab);
903 
904  if ( verbosity_ ) {
905  std::cout << "before rotation:" << std::endl;
906  print("muon1(lab)", muon1P4_lab, &zP4_lab);
907  print("muon2(lab)", muon2P4_lab, &zP4_lab);
908  print("Z(lab)", zP4_lab);
909  print("muon1(rf)", muon1P4_rf, &zP4_lab);
910  print("muon2(rf)", muon2P4_rf, &zP4_lab);
911  print("Z(rf)", zP4_rf);
912  }
913 
914  if ( rfRotationAngle_ != 0. ) {
915  double rfRotationAngle_value = rfRotationAngle_;
916  if ( rfRotationAngle_ == -1. ) {
917  double u = randomEngine.flat();
918  rfRotationAngle_value = 2.*TMath::Pi()*u;
919  }
920 
921  muon1P4_rf = rotate(muon1P4_rf, zP4_lab, rfRotationAngle_value);
922  muon2P4_rf = rotate(muon2P4_rf, zP4_lab, rfRotationAngle_value);
923  }
924 
925  double muon1P_rf2 = square(muon1P4_rf.px()) + square(muon1P4_rf.py()) + square(muon1P4_rf.pz());
926  double lep1Mass2 = square(targetParticle1Mass_);
927  double lep1En_rf = 0.5*zP4_rf.E();
928  double lep1P_rf2 = square(lep1En_rf) - lep1Mass2;
929  if ( lep1P_rf2 < 0. ) lep1P_rf2 = 0.;
930  float scaleFactor1 = sqrt(lep1P_rf2/muon1P_rf2);
932  scaleFactor1*muon1P4_rf.px(), scaleFactor1*muon1P4_rf.py(), scaleFactor1*muon1P4_rf.pz(), lep1En_rf);
933 
934  double muon2P_rf2 = square(muon2P4_rf.px()) + square(muon2P4_rf.py()) + square(muon2P4_rf.pz());
935  double lep2Mass2 = square(targetParticle2Mass_);
936  double lep2En_rf = 0.5*zP4_rf.E();
937  double lep2P_rf2 = square(lep2En_rf) - lep2Mass2;
938  if ( lep2P_rf2 < 0. ) lep2P_rf2 = 0.;
939  float scaleFactor2 = sqrt(lep2P_rf2/muon2P_rf2);
941  scaleFactor2*muon2P4_rf.px(), scaleFactor2*muon2P4_rf.py(), scaleFactor2*muon2P4_rf.pz(), lep2En_rf);
942 
943  reco::Particle::LorentzVector lep1P4_lab = boost_to_lab(lep1P4_rf);
944  reco::Particle::LorentzVector lep2P4_lab = boost_to_lab(lep2P4_rf);
945 
946  if ( verbosity_ ) {
947  std::cout << "after rotation:" << std::endl;
948  print("lep1(rf)", muon1P4_rf, &zP4_lab);
949  print("lep2(rf)", muon2P4_rf, &zP4_lab);
950  reco::Particle::LorentzVector lep1p2_lab = lep1P4_lab + lep2P4_lab;
951  print("lep1(lab)", lep1P4_lab, &zP4_lab);
952  print("lep2(lab)", lep2P4_lab, &zP4_lab);
953  print("lep1+2(lab)", lep1p2_lab);
954  }
955 
956  // perform additional checks:
957  // the following tests guarantee a deviation of less than 0.1%
958  // for the following values of the original muons and the embedded electrons/taus in terms of:
959  // - invariant mass
960  // - transverse momentum
961  if ( !(fabs(zP4_lab.mass() - (lep1P4_lab + lep2P4_lab).mass()) < (1.e-3*zP4_lab.mass()) &&
962  fabs(zP4_lab.pt() - (lep1P4_lab + lep2P4_lab).pt()) < (1.e-3*zP4_lab.pt())) )
963  edm::LogError ("ParticleReplacerZtautau")
964  << "The kinematics of muons and embedded electrons/taus differ by more than 0.1%:" << std::endl
965  << " mass(muon1 + muon2) = " << zP4_lab.mass() << ", mass(lep1 + lep2) = " << (lep1P4_lab + lep2P4_lab).mass() << std::endl
966  << " Pt(muon1 + muon2) = " << zP4_lab.pt() << ", Pt(lep1 + lep2) = " << (lep1P4_lab + lep2P4_lab).pt() << " --> please CHECK !!" << std::endl;
967 
968  muon1->setP4(lep1P4_lab);
969  muon2->setP4(lep2P4_lab);
970 
971  muon1->setPdgId(targetParticle1AbsPdgID_*muon1->pdgId()/abs(muon1->pdgId()));
972  muon2->setPdgId(targetParticle2AbsPdgID_*muon2->pdgId()/abs(muon2->pdgId()));
973 
974  muon1->setStatus(1);
975  muon2->setStatus(1);
976 
977  return;
978 }
CLHEP::HepRandomEngine * randomEngine
Definition: Dummies.cc:7
const double Pi
void setP4(const LorentzVector &p4)
set 4-momentum
Definition: Particle.cc:182
std::string print(const Track &, edm::Verbosity=edm::Concise)
Track print utility.
Definition: print.cc:8
const LorentzVector & p4() const
four-momentum Lorentz vector
Definition: Particle.cc:86
T sqrt(T t)
Definition: SSEVec.h:48
Abs< T >::type abs(const T &t)
Definition: Abs.h:22
int pdgId() const
PDG identifier.
Definition: Particle.cc:246
def rotate
Definition: svgfig.py:704
void setPdgId(int pdgId)
Definition: Particle.cc:250
double square(const double a)
tuple cout
Definition: gather_cfg.py:121
void setStatus(int status)
set status word
Definition: Particle.cc:258
math::XYZTLorentzVector LorentzVector
Lorentz vector.
Definition: Particle.h:27
void ParticleReplacerZtautau::transformMuMu2TauNu ( reco::Particle muon1,
reco::Particle muon2 
)
private

Definition at line 980 of file ParticleReplacerZtautau.cc.

References funct::abs(), breitWignerWidthW, breitWignerWidthZ, alignCSCRings::e, nomMassW, nomMassZ, reco::Particle::p4(), reco::Particle::pdgId(), phi, RecoTauCleanerPlugins::pt, reco::Particle::setP4(), reco::Particle::setPdgId(), reco::Particle::setStatus(), mathSSE::sqrt(), Clusterizer1DCommons::square(), targetParticle1AbsPdgID_, targetParticle1Mass_, targetParticle2AbsPdgID_, targetParticle2Mass_, and theta().

Referenced by produce().

981 {
982 //--- transform a muon pair into tau + nu (replacing a Z by W boson)
983 
984  reco::Particle::LorentzVector muon1P4_lab = muon1->p4();
985  reco::Particle::LorentzVector muon2P4_lab = muon2->p4();
986  reco::Particle::LorentzVector zP4_lab = muon1P4_lab + muon2P4_lab;
987 
988  ROOT::Math::Boost boost_to_rf(zP4_lab.BoostToCM());
989  ROOT::Math::Boost boost_to_lab(boost_to_rf.Inverse());
990 
991  reco::Particle::LorentzVector zP4_rf = boost_to_rf(zP4_lab);
992 
993  double wMass = (zP4_rf.mass() - nomMassZ)*(breitWignerWidthW/breitWignerWidthZ) + nomMassW;
994 
995  reco::Particle::LorentzVector muon1P4_rf = boost_to_rf(muon1P4_lab);
996  reco::Particle::LorentzVector muon2P4_rf = boost_to_rf(muon2P4_lab);
997 
998  double muon1P_rf2 = square(muon1P4_rf.px()) + square(muon1P4_rf.py()) + square(muon1P4_rf.pz());
999  double tauMass2 = square(targetParticle1Mass_);
1000  double tauEn_rf = 0.5*zP4_rf.E();
1001  double tauP_rf2 = square(tauEn_rf) - tauMass2;
1002  if ( tauP_rf2 < 0. ) tauP_rf2 = 0.;
1003  float scaleFactor1 = sqrt(tauP_rf2/muon1P_rf2)*(wMass/zP4_rf.mass());
1005  scaleFactor1*muon1P4_rf.px(), scaleFactor1*muon1P4_rf.py(), scaleFactor1*muon1P4_rf.pz(), tauEn_rf);
1006 
1007  double muon2P_rf2 = square(muon2P4_rf.px()) + square(muon2P4_rf.py()) + square(muon2P4_rf.pz());
1008  double nuMass2 = square(targetParticle2Mass_);
1009  assert(nuMass2 < 1.e-4);
1010  double nuEn_rf = 0.5*zP4_rf.E();
1011  double nuP_rf2 = square(nuEn_rf) - nuMass2;
1012  if ( nuP_rf2 < 0. ) nuP_rf2 = 0.;
1013  float scaleFactor2 = sqrt(nuP_rf2/muon2P_rf2)*(wMass/zP4_rf.mass());
1015  scaleFactor2*muon2P4_rf.px(), scaleFactor2*muon2P4_rf.py(), scaleFactor2*muon2P4_rf.pz(), nuEn_rf);
1016 
1017  reco::Particle::LorentzVector tauP4_lab = boost_to_lab(tauP4_rf);
1018  reco::Particle::LorentzVector nuP4_lab = boost_to_lab(nuP4_rf);
1019 
1020  // perform additional checks:
1021  // the following tests guarantee a deviation of less than 0.1%
1022  // for the following values of the original muons and the embedded electrons/taus in terms of:
1023  // - theta
1024  // - phi
1025  if ( !(std::abs(zP4_lab.theta() - (tauP4_lab + nuP4_lab).theta())/zP4_lab.theta() < 1.e-3 &&
1026  std::abs(zP4_lab.phi() - (tauP4_lab + nuP4_lab).phi())/zP4_lab.phi() < 1.e-3) )
1027  edm::LogError ("Replacer")
1028  << "The kinematics of muons and embedded tau/neutrino differ by more than 0.1%:" << std::endl
1029  << " mass(muon1 + muon2) = " << zP4_lab.mass() << ", mass(lep1 + lep2) = " << (tauP4_lab + nuP4_lab).mass() << std::endl
1030  << " Pt(muon1 + muon2) = " << zP4_lab.pt() << ", Pt(lep1 + lep2) = " << (tauP4_lab + nuP4_lab).pt() << " --> please CHECK !!" << std::endl;
1031 
1032  muon1->setP4(tauP4_lab);
1033  muon2->setP4(nuP4_lab);
1034 
1035  muon1->setPdgId(targetParticle1AbsPdgID_*muon1->pdgId()/abs(muon1->pdgId()));
1036  muon2->setPdgId(targetParticle2AbsPdgID_*muon2->pdgId()/abs(muon2->pdgId()));
1037 
1038  muon1->setStatus(1);
1039  muon2->setStatus(1);
1040 
1041  return;
1042 }
void setP4(const LorentzVector &p4)
set 4-momentum
Definition: Particle.cc:182
Geom::Theta< T > theta() const
const LorentzVector & p4() const
four-momentum Lorentz vector
Definition: Particle.cc:86
T sqrt(T t)
Definition: SSEVec.h:48
Abs< T >::type abs(const T &t)
Definition: Abs.h:22
const double nomMassW
const double breitWignerWidthW
int pdgId() const
PDG identifier.
Definition: Particle.cc:246
const double nomMassZ
void setPdgId(int pdgId)
Definition: Particle.cc:250
double square(const double a)
void setStatus(int status)
set status word
Definition: Particle.cc:258
math::XYZTLorentzVector LorentzVector
Lorentz vector.
Definition: Particle.h:27
const double breitWignerWidthZ
Definition: DDAxes.h:10

Member Data Documentation

bool ParticleReplacerZtautau::applyMuonRadiationCorrection_
private

Definition at line 89 of file ParticleReplacerZtautau.h.

Referenced by ParticleReplacerZtautau(), and produce().

double ParticleReplacerZtautau::beamEnergy_
private

Definition at line 65 of file ParticleReplacerZtautau.h.

Referenced by ParticleReplacerZtautau(), and produce().

std::string ParticleReplacerZtautau::generatorMode_
private

Definition at line 64 of file ParticleReplacerZtautau.h.

Referenced by ParticleReplacerZtautau(), and produce().

int ParticleReplacerZtautau::maxNumberOfAttempts_
private

Definition at line 134 of file ParticleReplacerZtautau.h.

Referenced by ParticleReplacerZtautau(), and produce().

std::vector<MinVisPtCutCombination> ParticleReplacerZtautau::minVisPtCuts_
private

Definition at line 127 of file ParticleReplacerZtautau.h.

Referenced by ParticleReplacerZtautau(), and testEvent().

int ParticleReplacerZtautau::motherParticleID_
private

Definition at line 75 of file ParticleReplacerZtautau.h.

Referenced by ParticleReplacerZtautau(), and produce().

GenMuonRadiationAlgorithm* ParticleReplacerZtautau::muonRadiationAlgo_
private
bool ParticleReplacerZtautau::printEvent_
private

Definition at line 94 of file ParticleReplacerZtautau.h.

gen::Pythia6Service ParticleReplacerZtautau::pythia_
private

Definition at line 92 of file ParticleReplacerZtautau.h.

Referenced by beginJob(), and produce().

double ParticleReplacerZtautau::rfRotationAngle_
private

Definition at line 79 of file ParticleReplacerZtautau.h.

Referenced by ParticleReplacerZtautau(), and transformMuMu2LepLep().

int ParticleReplacerZtautau::targetParticle1AbsPdgID_
private

Definition at line 130 of file ParticleReplacerZtautau.h.

Referenced by produce(), transformMuMu2LepLep(), and transformMuMu2TauNu().

double ParticleReplacerZtautau::targetParticle1Mass_
private

Definition at line 129 of file ParticleReplacerZtautau.h.

Referenced by produce(), transformMuMu2LepLep(), and transformMuMu2TauNu().

int ParticleReplacerZtautau::targetParticle2AbsPdgID_
private

Definition at line 132 of file ParticleReplacerZtautau.h.

Referenced by produce(), transformMuMu2LepLep(), and transformMuMu2TauNu().

double ParticleReplacerZtautau::targetParticle2Mass_
private

Definition at line 131 of file ParticleReplacerZtautau.h.

Referenced by produce(), transformMuMu2LepLep(), and transformMuMu2TauNu().

gen::TauolaInterfaceBase* ParticleReplacerZtautau::tauola_
private

Definition at line 83 of file ParticleReplacerZtautau.h.

Referenced by beginRun(), endJob(), ParticleReplacerZtautau(), and produce().

bool ParticleReplacerZtautau::tauola_isInitialized_ = false
staticprivate

Definition at line 87 of file ParticleReplacerZtautau.h.

Referenced by beginRun().

unsigned int ParticleReplacerZtautau::transformationMode_
private

Definition at line 73 of file ParticleReplacerZtautau.h.

Referenced by ParticleReplacerZtautau(), and produce().

bool ParticleReplacerZtautau::useExternalGenerators_
private

Definition at line 76 of file ParticleReplacerZtautau.h.

bool ParticleReplacerZtautau::useTauola_
private

Definition at line 77 of file ParticleReplacerZtautau.h.

bool ParticleReplacerZtautau::useTauolaPolarization_
private

Definition at line 78 of file ParticleReplacerZtautau.h.