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 (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::TauolaInterfacetauola_
 
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 38 of file ParticleReplacerZtautau.h.

Constructor & Destructor Documentation

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

Definition at line 46 of file ParticleReplacerZtautau.cc.

References edm::ParameterSet::addParameter(), applyMuonRadiationCorrection_, beamEnergy_, gather_cfg::cout, GOODCOLL_filter_cfg::cut, ParticleReplacerZtautau::MinVisPtCutCombination::cut_string_, ParticleReplacerZtautau::MinVisPtCutCombination::cuts_, decayRandomEngine, edm::hlt::Exception, edm::ParameterSet::exists(), generatorMode_, edm::RandomNumberGenerator::getEngine(), edm::ParameterSet::getParameter(), ParticleReplacerZtautau::MinVisPtCut::index_, edm::Service< T >::isAvailable(), ParticleReplacerZtautau::MinVisPtCut::kELEC, ParticleReplacerZtautau::MinVisPtCut::kHAD, ParticleReplacerZtautau::MinVisPtCut::kMU, ParticleReplacerZtautau::MinVisPtCut::kTAU, maxNumberOfAttempts_, minVisPtCuts_, motherParticleID_, muonRadiationAlgo_, NULL, Pi, rfRotationAngle_, gen::TauolaInterface::setPSet(), AlCaHLTBitMon_QueryRunRegistry::string, tauola_, ParticleReplacerZtautau::MinVisPtCut::threshold_, transformationMode_, ParticleReplacerZtautau::MinVisPtCut::type_, and ParticleReplacerBase::verbosity_.

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

Definition at line 174 of file ParticleReplacerZtautau.cc.

References muonRadiationAlgo_.

175 {
176  delete muonRadiationAlgo_;
177 }
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 700 of file ParticleReplacerZtautau.cc.

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

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

Definition at line 827 of file ParticleReplacerZtautau.cc.

References repairBarcodes().

Referenced by produce().

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

Reimplemented from ParticleReplacerBase.

Definition at line 179 of file ParticleReplacerZtautau.cc.

References MCParticleReplacer::call_produces().

180 {
181  producer->call_produces<ParticleCollection>("muonsBeforeRad");
182  producer->call_produces<ParticleCollection>("muonsAfterRad");
183 }
void call_produces(const std::string &instanceName)
std::vector< reco::Particle > ParticleCollection
void ParticleReplacerZtautau::endJob ( void  )
virtual

Reimplemented from ParticleReplacerBase.

Definition at line 709 of file ParticleReplacerZtautau.cc.

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

710 {
711  tauola_->statistics();
712 }
gen::TauolaInterface * 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 245 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::TauolaInterface::decay(), deltaR(), alignCSCRings::e, electronMass, edm::hlt::Exception, generatorMode_, configurableAnalysis::GenParticle, customizeTrackingMonitorSeedNumber::idx, 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(), 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().

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

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

Definition at line 889 of file ParticleReplacerZtautau.cc.

References funct::abs(), gather_cfg::cout, decayRandomEngine, 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().

890 {
891 //--- transform a muon pair into an electron/tau pair,
892 // taking into account the difference between muon and electron/tau mass
893 
894  reco::Particle::LorentzVector muon1P4_lab = muon1->p4();
895  reco::Particle::LorentzVector muon2P4_lab = muon2->p4();
896  reco::Particle::LorentzVector zP4_lab = muon1P4_lab + muon2P4_lab;
897 
898  ROOT::Math::Boost boost_to_rf(zP4_lab.BoostToCM());
899  ROOT::Math::Boost boost_to_lab(boost_to_rf.Inverse());
900 
901  reco::Particle::LorentzVector zP4_rf = boost_to_rf(zP4_lab);
902 
903  reco::Particle::LorentzVector muon1P4_rf = boost_to_rf(muon1P4_lab);
904  reco::Particle::LorentzVector muon2P4_rf = boost_to_rf(muon2P4_lab);
905 
906  if ( verbosity_ ) {
907  std::cout << "before rotation:" << std::endl;
908  print("muon1(lab)", muon1P4_lab, &zP4_lab);
909  print("muon2(lab)", muon2P4_lab, &zP4_lab);
910  print("Z(lab)", zP4_lab);
911  print("muon1(rf)", muon1P4_rf, &zP4_lab);
912  print("muon2(rf)", muon2P4_rf, &zP4_lab);
913  print("Z(rf)", zP4_rf);
914  }
915 
916  if ( rfRotationAngle_ != 0. ) {
917  double rfRotationAngle_value = rfRotationAngle_;
918  if ( rfRotationAngle_ == -1. ) {
919  double u = decayRandomEngine->flat();
920  rfRotationAngle_value = 2.*TMath::Pi()*u;
921  }
922 
923  muon1P4_rf = rotate(muon1P4_rf, zP4_lab, rfRotationAngle_value);
924  muon2P4_rf = rotate(muon2P4_rf, zP4_lab, rfRotationAngle_value);
925  }
926 
927  double muon1P_rf2 = square(muon1P4_rf.px()) + square(muon1P4_rf.py()) + square(muon1P4_rf.pz());
928  double lep1Mass2 = square(targetParticle1Mass_);
929  double lep1En_rf = 0.5*zP4_rf.E();
930  double lep1P_rf2 = square(lep1En_rf) - lep1Mass2;
931  if ( lep1P_rf2 < 0. ) lep1P_rf2 = 0.;
932  float scaleFactor1 = sqrt(lep1P_rf2/muon1P_rf2);
934  scaleFactor1*muon1P4_rf.px(), scaleFactor1*muon1P4_rf.py(), scaleFactor1*muon1P4_rf.pz(), lep1En_rf);
935 
936  double muon2P_rf2 = square(muon2P4_rf.px()) + square(muon2P4_rf.py()) + square(muon2P4_rf.pz());
937  double lep2Mass2 = square(targetParticle2Mass_);
938  double lep2En_rf = 0.5*zP4_rf.E();
939  double lep2P_rf2 = square(lep2En_rf) - lep2Mass2;
940  if ( lep2P_rf2 < 0. ) lep2P_rf2 = 0.;
941  float scaleFactor2 = sqrt(lep2P_rf2/muon2P_rf2);
943  scaleFactor2*muon2P4_rf.px(), scaleFactor2*muon2P4_rf.py(), scaleFactor2*muon2P4_rf.pz(), lep2En_rf);
944 
945  reco::Particle::LorentzVector lep1P4_lab = boost_to_lab(lep1P4_rf);
946  reco::Particle::LorentzVector lep2P4_lab = boost_to_lab(lep2P4_rf);
947 
948  if ( verbosity_ ) {
949  std::cout << "after rotation:" << std::endl;
950  print("lep1(rf)", muon1P4_rf, &zP4_lab);
951  print("lep2(rf)", muon2P4_rf, &zP4_lab);
952  reco::Particle::LorentzVector lep1p2_lab = lep1P4_lab + lep2P4_lab;
953  print("lep1(lab)", lep1P4_lab, &zP4_lab);
954  print("lep2(lab)", lep2P4_lab, &zP4_lab);
955  print("lep1+2(lab)", lep1p2_lab);
956  }
957 
958  // perform additional checks:
959  // the following tests guarantee a deviation of less than 0.1%
960  // for the following values of the original muons and the embedded electrons/taus in terms of:
961  // - invariant mass
962  // - transverse momentum
963  if ( !(fabs(zP4_lab.mass() - (lep1P4_lab + lep2P4_lab).mass()) < (1.e-3*zP4_lab.mass()) &&
964  fabs(zP4_lab.pt() - (lep1P4_lab + lep2P4_lab).pt()) < (1.e-3*zP4_lab.pt())) )
965  edm::LogError ("ParticleReplacerZtautau")
966  << "The kinematics of muons and embedded electrons/taus differ by more than 0.1%:" << std::endl
967  << " mass(muon1 + muon2) = " << zP4_lab.mass() << ", mass(lep1 + lep2) = " << (lep1P4_lab + lep2P4_lab).mass() << std::endl
968  << " Pt(muon1 + muon2) = " << zP4_lab.pt() << ", Pt(lep1 + lep2) = " << (lep1P4_lab + lep2P4_lab).pt() << " --> please CHECK !!" << std::endl;
969 
970  muon1->setP4(lep1P4_lab);
971  muon2->setP4(lep2P4_lab);
972 
973  muon1->setPdgId(targetParticle1AbsPdgID_*muon1->pdgId()/abs(muon1->pdgId()));
974  muon2->setPdgId(targetParticle2AbsPdgID_*muon2->pdgId()/abs(muon2->pdgId()));
975 
976  muon1->setStatus(1);
977  muon2->setStatus(1);
978 
979  return;
980 }
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
CLHEP::HepRandomEngine * decayRandomEngine
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 982 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().

983 {
984 //--- transform a muon pair into tau + nu (replacing a Z by W boson)
985 
986  reco::Particle::LorentzVector muon1P4_lab = muon1->p4();
987  reco::Particle::LorentzVector muon2P4_lab = muon2->p4();
988  reco::Particle::LorentzVector zP4_lab = muon1P4_lab + muon2P4_lab;
989 
990  ROOT::Math::Boost boost_to_rf(zP4_lab.BoostToCM());
991  ROOT::Math::Boost boost_to_lab(boost_to_rf.Inverse());
992 
993  reco::Particle::LorentzVector zP4_rf = boost_to_rf(zP4_lab);
994 
995  double wMass = (zP4_rf.mass() - nomMassZ)*(breitWignerWidthW/breitWignerWidthZ) + nomMassW;
996 
997  reco::Particle::LorentzVector muon1P4_rf = boost_to_rf(muon1P4_lab);
998  reco::Particle::LorentzVector muon2P4_rf = boost_to_rf(muon2P4_lab);
999 
1000  double muon1P_rf2 = square(muon1P4_rf.px()) + square(muon1P4_rf.py()) + square(muon1P4_rf.pz());
1001  double tauMass2 = square(targetParticle1Mass_);
1002  double tauEn_rf = 0.5*zP4_rf.E();
1003  double tauP_rf2 = square(tauEn_rf) - tauMass2;
1004  if ( tauP_rf2 < 0. ) tauP_rf2 = 0.;
1005  float scaleFactor1 = sqrt(tauP_rf2/muon1P_rf2)*(wMass/zP4_rf.mass());
1007  scaleFactor1*muon1P4_rf.px(), scaleFactor1*muon1P4_rf.py(), scaleFactor1*muon1P4_rf.pz(), tauEn_rf);
1008 
1009  double muon2P_rf2 = square(muon2P4_rf.px()) + square(muon2P4_rf.py()) + square(muon2P4_rf.pz());
1010  double nuMass2 = square(targetParticle2Mass_);
1011  assert(nuMass2 < 1.e-4);
1012  double nuEn_rf = 0.5*zP4_rf.E();
1013  double nuP_rf2 = square(nuEn_rf) - nuMass2;
1014  if ( nuP_rf2 < 0. ) nuP_rf2 = 0.;
1015  float scaleFactor2 = sqrt(nuP_rf2/muon2P_rf2)*(wMass/zP4_rf.mass());
1017  scaleFactor2*muon2P4_rf.px(), scaleFactor2*muon2P4_rf.py(), scaleFactor2*muon2P4_rf.pz(), nuEn_rf);
1018 
1019  reco::Particle::LorentzVector tauP4_lab = boost_to_lab(tauP4_rf);
1020  reco::Particle::LorentzVector nuP4_lab = boost_to_lab(nuP4_rf);
1021 
1022  // perform additional checks:
1023  // the following tests guarantee a deviation of less than 0.1%
1024  // for the following values of the original muons and the embedded electrons/taus in terms of:
1025  // - theta
1026  // - phi
1027  if ( !(std::abs(zP4_lab.theta() - (tauP4_lab + nuP4_lab).theta())/zP4_lab.theta() < 1.e-3 &&
1028  std::abs(zP4_lab.phi() - (tauP4_lab + nuP4_lab).phi())/zP4_lab.phi() < 1.e-3) )
1029  edm::LogError ("Replacer")
1030  << "The kinematics of muons and embedded tau/neutrino differ by more than 0.1%:" << std::endl
1031  << " mass(muon1 + muon2) = " << zP4_lab.mass() << ", mass(lep1 + lep2) = " << (tauP4_lab + nuP4_lab).mass() << std::endl
1032  << " Pt(muon1 + muon2) = " << zP4_lab.pt() << ", Pt(lep1 + lep2) = " << (tauP4_lab + nuP4_lab).pt() << " --> please CHECK !!" << std::endl;
1033 
1034  muon1->setP4(tauP4_lab);
1035  muon2->setP4(nuP4_lab);
1036 
1037  muon1->setPdgId(targetParticle1AbsPdgID_*muon1->pdgId()/abs(muon1->pdgId()));
1038  muon2->setPdgId(targetParticle2AbsPdgID_*muon2->pdgId()/abs(muon2->pdgId()));
1039 
1040  muon1->setStatus(1);
1041  muon2->setStatus(1);
1042 
1043  return;
1044 }
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 87 of file ParticleReplacerZtautau.h.

Referenced by ParticleReplacerZtautau(), and produce().

double ParticleReplacerZtautau::beamEnergy_
private

Definition at line 63 of file ParticleReplacerZtautau.h.

Referenced by ParticleReplacerZtautau(), and produce().

std::string ParticleReplacerZtautau::generatorMode_
private

Definition at line 62 of file ParticleReplacerZtautau.h.

Referenced by ParticleReplacerZtautau(), and produce().

int ParticleReplacerZtautau::maxNumberOfAttempts_
private

Definition at line 132 of file ParticleReplacerZtautau.h.

Referenced by ParticleReplacerZtautau(), and produce().

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

Definition at line 125 of file ParticleReplacerZtautau.h.

Referenced by ParticleReplacerZtautau(), and testEvent().

int ParticleReplacerZtautau::motherParticleID_
private

Definition at line 73 of file ParticleReplacerZtautau.h.

Referenced by ParticleReplacerZtautau(), and produce().

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

Definition at line 92 of file ParticleReplacerZtautau.h.

gen::Pythia6Service ParticleReplacerZtautau::pythia_
private

Definition at line 90 of file ParticleReplacerZtautau.h.

Referenced by beginJob(), and produce().

double ParticleReplacerZtautau::rfRotationAngle_
private

Definition at line 77 of file ParticleReplacerZtautau.h.

Referenced by ParticleReplacerZtautau(), and transformMuMu2LepLep().

int ParticleReplacerZtautau::targetParticle1AbsPdgID_
private

Definition at line 128 of file ParticleReplacerZtautau.h.

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

double ParticleReplacerZtautau::targetParticle1Mass_
private

Definition at line 127 of file ParticleReplacerZtautau.h.

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

int ParticleReplacerZtautau::targetParticle2AbsPdgID_
private

Definition at line 130 of file ParticleReplacerZtautau.h.

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

double ParticleReplacerZtautau::targetParticle2Mass_
private

Definition at line 129 of file ParticleReplacerZtautau.h.

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

gen::TauolaInterface* ParticleReplacerZtautau::tauola_
private

Definition at line 81 of file ParticleReplacerZtautau.h.

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

bool ParticleReplacerZtautau::tauola_isInitialized_ = false
staticprivate

Definition at line 85 of file ParticleReplacerZtautau.h.

Referenced by beginRun().

unsigned int ParticleReplacerZtautau::transformationMode_
private

Definition at line 71 of file ParticleReplacerZtautau.h.

Referenced by ParticleReplacerZtautau(), and produce().

bool ParticleReplacerZtautau::useExternalGenerators_
private

Definition at line 74 of file ParticleReplacerZtautau.h.

bool ParticleReplacerZtautau::useTauola_
private

Definition at line 75 of file ParticleReplacerZtautau.h.

bool ParticleReplacerZtautau::useTauolaPolarization_
private

Definition at line 76 of file ParticleReplacerZtautau.h.