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_
 
bool rfMirror_
 
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_, ztail::d, 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, rfMirror_, 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  rfMirror_ = cfg.getParameter<bool>("rfMirror");
147 
148  std::string applyMuonRadiationCorrection_string = cfg.getParameter<std::string>("applyMuonRadiationCorrection");
149  if ( applyMuonRadiationCorrection_string != "" ) {
150  edm::ParameterSet cfgMuonRadiationAlgo;
151  cfgMuonRadiationAlgo.addParameter<double>("beamEnergy", beamEnergy_);
152  cfgMuonRadiationAlgo.addParameter<std::string>("mode", applyMuonRadiationCorrection_string);
153  cfgMuonRadiationAlgo.addParameter<int>("verbosity", 0);
154  edm::ParameterSet cfgPhotosOptions;
155  cfgMuonRadiationAlgo.addParameter<edm::ParameterSet>("PhotosOptions", cfgPhotosOptions);
156  edm::ParameterSet cfgPythiaParameters = cfg.getParameter<edm::ParameterSet>("PythiaParameters");
157  cfgMuonRadiationAlgo.addParameter<edm::ParameterSet>("PythiaParameters", cfgPythiaParameters);
158  muonRadiationAlgo_ = new GenMuonRadiationAlgorithm(cfgMuonRadiationAlgo);
160  }
161 }
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 &)
tuple d
Definition: ztail.py:151
gen::TauolaInterfaceBase * tauola_
void addParameter(std::string const &name, T const &value)
Definition: ParameterSet.h:144
tuple cout
Definition: gather_cfg.py:121
GenMuonRadiationAlgorithm * muonRadiationAlgo_
T get(const Candidate &c)
Definition: component.h:55
ParticleReplacerZtautau::~ParticleReplacerZtautau ( )

Definition at line 163 of file ParticleReplacerZtautau.cc.

References muonRadiationAlgo_.

164 {
165  delete muonRadiationAlgo_;
166 }
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 699 of file ParticleReplacerZtautau.cc.

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

700 {
701  if ( !tauola_isInitialized_ ) {
702  std::cout << "<ParticleReplacerZtautau::beginRun>: Initializing TAUOLA interface." << std::endl;
703  tauola_->init(es);
704  tauola_isInitialized_ = true;
705  }
706 }
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 826 of file ParticleReplacerZtautau.cc.

References repairBarcodes().

Referenced by produce().

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

Reimplemented from ParticleReplacerBase.

Definition at line 168 of file ParticleReplacerZtautau.cc.

References MCParticleReplacer::call_produces().

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

Reimplemented from ParticleReplacerBase.

Definition at line 708 of file ParticleReplacerZtautau.cc.

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

709 {
710  tauola_->statistics();
711 }
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 234 of file ParticleReplacerZtautau.cc.

References funct::abs(), applyMuonRadiationCorrection_, assert(), beamEnergy_, MCParticleReplacer::call_put(), call_pyexec(), reco::Particle::charge(), cleanEvent(), GenMuonRadiationAlgorithm::compFSR(), conv, gather_cfg::cout, gen::TauolaInterfaceBase::decay(), decayRandomEngine, deltaR(), alignCSCRings::e, electronMass, Exception, generatorMode_, GenParticle::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().

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

Definition at line 713 of file ParticleReplacerZtautau.cc.

References funct::abs(), assert(), runEdmFileComparison::collection, gather_cfg::cout, GOODCOLL_filter_cfg::cut, GenParticle::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().

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

Definition at line 912 of file ParticleReplacerZtautau.cc.

References funct::abs(), beamEnergy_, gather_cfg::cout, alignCSCRings::e, reco::Particle::p4(), reco::Particle::pdgId(), Pi, reco::print(), protonMass, EnergyCorrector::pt, rfMirror_, 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().

913 {
914 //--- transform a muon pair into an electron/tau pair,
915 // taking into account the difference between muon and electron/tau mass
916 
917  reco::Particle::LorentzVector muon1P4_lab = muon1->p4();
918  reco::Particle::LorentzVector muon2P4_lab = muon2->p4();
919  reco::Particle::LorentzVector zP4_lab = muon1P4_lab + muon2P4_lab;
920 
921  ROOT::Math::Boost boost_to_rf(zP4_lab.BoostToCM());
922  ROOT::Math::Boost boost_to_lab(boost_to_rf.Inverse());
923 
924  reco::Particle::LorentzVector zP4_rf = boost_to_rf(zP4_lab);
925 
926  reco::Particle::LorentzVector muon1P4_rf = boost_to_rf(muon1P4_lab);
927  reco::Particle::LorentzVector muon2P4_rf = boost_to_rf(muon2P4_lab);
928 
929  if ( verbosity_ ) {
930  std::cout << "before rotation:" << std::endl;
931  print("muon1(lab)", muon1P4_lab, &zP4_lab);
932  print("muon2(lab)", muon2P4_lab, &zP4_lab);
933  print("Z(lab)", zP4_lab);
934  print("muon1(rf)", muon1P4_rf, &zP4_lab);
935  print("muon2(rf)", muon2P4_rf, &zP4_lab);
936  print("Z(rf)", zP4_rf);
937  }
938 
939  if ( rfRotationAngle_ != 0. ) {
940  double rfRotationAngle_value = rfRotationAngle_;
941  if ( rfRotationAngle_ == -1. ) {
942  double u = randomEngine.flat();
943  rfRotationAngle_value = 2.*TMath::Pi()*u;
944  }
945 
946  muon1P4_rf = rotate(muon1P4_rf, zP4_lab, rfRotationAngle_value);
947  muon2P4_rf = rotate(muon2P4_rf, zP4_lab, rfRotationAngle_value);
948  }
949 
950  if ( rfMirror_ ) {
951  double protonEn = beamEnergy_;
952  double protonPz = sqrt(square(protonEn) - square(protonMass));
953  const reco::Particle::LorentzVector pplus_lab(0., 0., protonPz, protonEn);
954  const reco::Particle::LorentzVector pplus_rf = boost_to_rf(pplus_lab);
955 
956  muon1P4_rf = mirror(muon1P4_rf, zP4_lab, pplus_rf);
957  muon2P4_rf = mirror(muon2P4_rf, zP4_lab, pplus_rf);
958  }
959 
960  double muon1P_rf2 = square(muon1P4_rf.px()) + square(muon1P4_rf.py()) + square(muon1P4_rf.pz());
961  double lep1Mass2 = square(targetParticle1Mass_);
962  double lep1En_rf = 0.5*zP4_rf.E();
963  double lep1P_rf2 = square(lep1En_rf) - lep1Mass2;
964  if ( lep1P_rf2 < 0. ) lep1P_rf2 = 0.;
965  float scaleFactor1 = sqrt(lep1P_rf2/muon1P_rf2);
967  scaleFactor1*muon1P4_rf.px(), scaleFactor1*muon1P4_rf.py(), scaleFactor1*muon1P4_rf.pz(), lep1En_rf);
968 
969  double muon2P_rf2 = square(muon2P4_rf.px()) + square(muon2P4_rf.py()) + square(muon2P4_rf.pz());
970  double lep2Mass2 = square(targetParticle2Mass_);
971  double lep2En_rf = 0.5*zP4_rf.E();
972  double lep2P_rf2 = square(lep2En_rf) - lep2Mass2;
973  if ( lep2P_rf2 < 0. ) lep2P_rf2 = 0.;
974  float scaleFactor2 = sqrt(lep2P_rf2/muon2P_rf2);
976  scaleFactor2*muon2P4_rf.px(), scaleFactor2*muon2P4_rf.py(), scaleFactor2*muon2P4_rf.pz(), lep2En_rf);
977 
978  reco::Particle::LorentzVector lep1P4_lab = boost_to_lab(lep1P4_rf);
979  reco::Particle::LorentzVector lep2P4_lab = boost_to_lab(lep2P4_rf);
980 
981  if ( verbosity_ ) {
982  std::cout << "after rotation:" << std::endl;
983  print("lep1(rf)", muon1P4_rf, &zP4_lab);
984  print("lep2(rf)", muon2P4_rf, &zP4_lab);
985  reco::Particle::LorentzVector lep1p2_lab = lep1P4_lab + lep2P4_lab;
986  print("lep1(lab)", lep1P4_lab, &zP4_lab);
987  print("lep2(lab)", lep2P4_lab, &zP4_lab);
988  print("lep1+2(lab)", lep1p2_lab);
989  }
990 
991  // perform additional checks:
992  // the following tests guarantee a deviation of less than 0.1%
993  // for the following values of the original muons and the embedded electrons/taus in terms of:
994  // - invariant mass
995  // - transverse momentum
996  if ( !(fabs(zP4_lab.mass() - (lep1P4_lab + lep2P4_lab).mass()) < (1.e-3*zP4_lab.mass()) &&
997  fabs(zP4_lab.pt() - (lep1P4_lab + lep2P4_lab).pt()) < (1.e-3*zP4_lab.pt())) )
998  edm::LogError ("ParticleReplacerZtautau")
999  << "The kinematics of muons and embedded electrons/taus differ by more than 0.1%:" << std::endl
1000  << " mass(muon1 + muon2) = " << zP4_lab.mass() << ", mass(lep1 + lep2) = " << (lep1P4_lab + lep2P4_lab).mass() << std::endl
1001  << " Pt(muon1 + muon2) = " << zP4_lab.pt() << ", Pt(lep1 + lep2) = " << (lep1P4_lab + lep2P4_lab).pt() << " --> please CHECK !!" << std::endl;
1002 
1003  muon1->setP4(lep1P4_lab);
1004  muon2->setP4(lep2P4_lab);
1005 
1006  muon1->setPdgId(targetParticle1AbsPdgID_*muon1->pdgId()/abs(muon1->pdgId()));
1007  muon2->setPdgId(targetParticle2AbsPdgID_*muon2->pdgId()/abs(muon2->pdgId()));
1008 
1009  muon1->setStatus(1);
1010  muon2->setStatus(1);
1011 
1012  return;
1013 }
CLHEP::HepRandomEngine * randomEngine
Definition: Dummies.cc:7
const double Pi
const double protonMass
void setP4(const LorentzVector &p4)
set 4-momentum
Definition: Particle.h:116
std::string print(const Track &, edm::Verbosity=edm::Concise)
Track print utility.
Definition: print.cc:10
const LorentzVector & p4() const
four-momentum Lorentz vector
Definition: Particle.h:72
int pdgId() const
PDG identifier.
Definition: Particle.h:134
T sqrt(T t)
Definition: SSEVec.h:48
Abs< T >::type abs(const T &t)
Definition: Abs.h:22
void setPdgId(int pdgId)
Definition: Particle.h:136
def rotate
Definition: svgfig.py:704
double square(const double a)
tuple cout
Definition: gather_cfg.py:121
math::XYZTLorentzVector LorentzVector
Lorentz vector.
Definition: Particle.h:21
void setStatus(int status)
set status word
Definition: Particle.h:140
void ParticleReplacerZtautau::transformMuMu2TauNu ( reco::Particle muon1,
reco::Particle muon2 
)
private

Definition at line 1015 of file ParticleReplacerZtautau.cc.

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

Referenced by produce().

1016 {
1017 //--- transform a muon pair into tau + nu (replacing a Z by W boson)
1018 
1019  reco::Particle::LorentzVector muon1P4_lab = muon1->p4();
1020  reco::Particle::LorentzVector muon2P4_lab = muon2->p4();
1021  reco::Particle::LorentzVector zP4_lab = muon1P4_lab + muon2P4_lab;
1022 
1023  ROOT::Math::Boost boost_to_rf(zP4_lab.BoostToCM());
1024  ROOT::Math::Boost boost_to_lab(boost_to_rf.Inverse());
1025 
1026  reco::Particle::LorentzVector zP4_rf = boost_to_rf(zP4_lab);
1027 
1028  double wMass = (zP4_rf.mass() - nomMassZ)*(breitWignerWidthW/breitWignerWidthZ) + nomMassW;
1029 
1030  reco::Particle::LorentzVector muon1P4_rf = boost_to_rf(muon1P4_lab);
1031  reco::Particle::LorentzVector muon2P4_rf = boost_to_rf(muon2P4_lab);
1032 
1033  double muon1P_rf2 = square(muon1P4_rf.px()) + square(muon1P4_rf.py()) + square(muon1P4_rf.pz());
1034  double tauMass2 = square(targetParticle1Mass_);
1035  double tauEn_rf = 0.5*zP4_rf.E();
1036  double tauP_rf2 = square(tauEn_rf) - tauMass2;
1037  if ( tauP_rf2 < 0. ) tauP_rf2 = 0.;
1038  float scaleFactor1 = sqrt(tauP_rf2/muon1P_rf2)*(wMass/zP4_rf.mass());
1040  scaleFactor1*muon1P4_rf.px(), scaleFactor1*muon1P4_rf.py(), scaleFactor1*muon1P4_rf.pz(), tauEn_rf);
1041 
1042  double muon2P_rf2 = square(muon2P4_rf.px()) + square(muon2P4_rf.py()) + square(muon2P4_rf.pz());
1043  double nuMass2 = square(targetParticle2Mass_);
1044  assert(nuMass2 < 1.e-4);
1045  double nuEn_rf = 0.5*zP4_rf.E();
1046  double nuP_rf2 = square(nuEn_rf) - nuMass2;
1047  if ( nuP_rf2 < 0. ) nuP_rf2 = 0.;
1048  float scaleFactor2 = sqrt(nuP_rf2/muon2P_rf2)*(wMass/zP4_rf.mass());
1050  scaleFactor2*muon2P4_rf.px(), scaleFactor2*muon2P4_rf.py(), scaleFactor2*muon2P4_rf.pz(), nuEn_rf);
1051 
1052  reco::Particle::LorentzVector tauP4_lab = boost_to_lab(tauP4_rf);
1053  reco::Particle::LorentzVector nuP4_lab = boost_to_lab(nuP4_rf);
1054 
1055  // perform additional checks:
1056  // the following tests guarantee a deviation of less than 0.1%
1057  // for the following values of the original muons and the embedded electrons/taus in terms of:
1058  // - theta
1059  // - phi
1060  if ( !(std::abs(zP4_lab.theta() - (tauP4_lab + nuP4_lab).theta())/zP4_lab.theta() < 1.e-3 &&
1061  std::abs(zP4_lab.phi() - (tauP4_lab + nuP4_lab).phi())/zP4_lab.phi() < 1.e-3) )
1062  edm::LogError ("Replacer")
1063  << "The kinematics of muons and embedded tau/neutrino differ by more than 0.1%:" << std::endl
1064  << " mass(muon1 + muon2) = " << zP4_lab.mass() << ", mass(lep1 + lep2) = " << (tauP4_lab + nuP4_lab).mass() << std::endl
1065  << " Pt(muon1 + muon2) = " << zP4_lab.pt() << ", Pt(lep1 + lep2) = " << (tauP4_lab + nuP4_lab).pt() << " --> please CHECK !!" << std::endl;
1066 
1067  muon1->setP4(tauP4_lab);
1068  muon2->setP4(nuP4_lab);
1069 
1070  muon1->setPdgId(targetParticle1AbsPdgID_*muon1->pdgId()/abs(muon1->pdgId()));
1071  muon2->setPdgId(targetParticle2AbsPdgID_*muon2->pdgId()/abs(muon2->pdgId()));
1072 
1073  muon1->setStatus(1);
1074  muon2->setStatus(1);
1075 
1076  return;
1077 }
void setP4(const LorentzVector &p4)
set 4-momentum
Definition: Particle.h:116
assert(m_qm.get())
Geom::Theta< T > theta() const
const LorentzVector & p4() const
four-momentum Lorentz vector
Definition: Particle.h:72
int pdgId() const
PDG identifier.
Definition: Particle.h:134
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
void setPdgId(int pdgId)
Definition: Particle.h:136
const double nomMassZ
double square(const double a)
math::XYZTLorentzVector LorentzVector
Lorentz vector.
Definition: Particle.h:21
void setStatus(int status)
set status word
Definition: Particle.h:140
const double breitWignerWidthZ

Member Data Documentation

bool ParticleReplacerZtautau::applyMuonRadiationCorrection_
private

Definition at line 91 of file ParticleReplacerZtautau.h.

Referenced by ParticleReplacerZtautau(), and produce().

double ParticleReplacerZtautau::beamEnergy_
private
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 136 of file ParticleReplacerZtautau.h.

Referenced by ParticleReplacerZtautau(), and produce().

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

Definition at line 129 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 96 of file ParticleReplacerZtautau.h.

gen::Pythia6Service ParticleReplacerZtautau::pythia_
private

Definition at line 94 of file ParticleReplacerZtautau.h.

Referenced by beginJob(), and produce().

bool ParticleReplacerZtautau::rfMirror_
private

Definition at line 82 of file ParticleReplacerZtautau.h.

Referenced by ParticleReplacerZtautau(), and transformMuMu2LepLep().

double ParticleReplacerZtautau::rfRotationAngle_
private

Definition at line 79 of file ParticleReplacerZtautau.h.

Referenced by ParticleReplacerZtautau(), and transformMuMu2LepLep().

int ParticleReplacerZtautau::targetParticle1AbsPdgID_
private

Definition at line 132 of file ParticleReplacerZtautau.h.

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

double ParticleReplacerZtautau::targetParticle1Mass_
private

Definition at line 131 of file ParticleReplacerZtautau.h.

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

int ParticleReplacerZtautau::targetParticle2AbsPdgID_
private

Definition at line 134 of file ParticleReplacerZtautau.h.

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

double ParticleReplacerZtautau::targetParticle2Mass_
private

Definition at line 133 of file ParticleReplacerZtautau.h.

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

gen::TauolaInterfaceBase* ParticleReplacerZtautau::tauola_
private

Definition at line 85 of file ParticleReplacerZtautau.h.

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

bool ParticleReplacerZtautau::tauola_isInitialized_ = false
staticprivate

Definition at line 89 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.