CMS 3D CMS Logo

 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
ParticleReplacerClass.cc
Go to the documentation of this file.
2 
5 
6 #include "HepMC/IO_HEPEVT.h"
7 
8 #ifndef TXGIVE
9 #define TXGIVE txgive_
10 extern "C" {
11  void TXGIVE(const char*,int length);
12 }
13 #endif
14 
15 #ifndef TXGIVE_INIT
16 #define TXGIVE_INIT txgive_init_
17 extern "C" {
18  void TXGIVE_INIT();
19 }
20 #endif
21 
22 namespace ParticleReplacerVar{
23  CLHEP::HepRandomEngine* decayRandomEngine; // adding static var to replace missing value from ExternalDecays
24 }
25 
28  generatorMode_(pset.getParameter<std::string>("generatorMode")),
29  printEvent_(verbose),
30  outTree(0),
31  maxNumberOfAttempts_(pset.getUntrackedParameter<int>("maxNumberOfAttempts", 1000))
32 {
33  tauola_ = (gen::TauolaInterfaceBase*)(TauolaFactory::get()->create("Tauolapp105", pset.getParameter< edm::ParameterSet>("TauolaOptions")));
34  // using namespace reco;
35  using namespace edm;
36  using namespace std;
37 
38  //HepMC::HEPEVT_Wrapper::set_max_number_entries(4000);
39  //HepMC::HEPEVT_Wrapper::set_sizeof_real(8);
40 
41  // transformationMode =
42  // 0 - no transformation
43  // 1 - mumu -> tautau
44  transformationMode_ = pset.getUntrackedParameter<int>("transformationMode",1);
45  switch (transformationMode_)
46  {
47  case 0:
48  {
49  LogInfo("Replacer") << "won't do any transformation with the given mumu";
50  break;
51  }
52  case 1:
53  {
54  LogInfo("Replacer") << "will transform mumu into tautau";
55  break;
56  }
57  case 2:
58  {
59  LogInfo("Replacer") << "will transform mumu into taunu (as coming from a W boson)";
60  break;
61  }
62  case 3:
63  {
64  LogInfo("Replacer") << "Will transform mu-nu into tau-nu. No mass correction will be made.";
65  break;
66  }
67  default:
68  {
69  throw cms::Exception("ParticleReplacerClass") << "Unknown transformation mode!\n";
70  break;
71  }
72 
73  }
74 
75  // If one wants to use two instances of this module in one
76  // configuration file, there might occur some segmentation
77  // faults due to the second initialisation of Tauola. This
78  // can be prevented by setting noInitialisation to false.
79  // Caution: This option is not tested!
80  noInitialisation_ = pset.getUntrackedParameter<bool>("noInitialisation",false);
81 
82  motherParticleID_ = pset.getUntrackedParameter<int>("motherParticleID",23);
83 
84  // requires the visible decay products of a tau to have a sum transverse momentum
85  std::string minVisibleTransverseMomentumLine = pset.getUntrackedParameter<std::string>("minVisibleTransverseMomentum","");
86 
87  // fallback for backwards compatibility: If it's a single number then use this as a threshold for both particles
88  const char* startptr = minVisibleTransverseMomentumLine.c_str();
89  char* endptr;
90  double d = strtod(startptr, &endptr);
91  if(*endptr == '\0' && endptr != startptr)
92  {
93  MinVisPtCut cuts[2];
94  cuts[0].type_ = cuts[1].type_ = MinVisPtCut::TAU;
95  cuts[0].pt_ = cuts[1].pt_ = d;
96  cuts[0].index_ = 0; cuts[1].index_ = 1;
97  minVisPtCuts_.push_back(std::vector<MinVisPtCut>(cuts, cuts+2));
98  }
99  else
100  {
101  // string has new format: parse the minvistransversemomentum string
102  for(std::string::size_type prev = 0, pos = 0; prev < minVisibleTransverseMomentumLine.length(); prev = pos + 1)
103  {
104  pos = minVisibleTransverseMomentumLine.find(';', prev);
105  if(pos == std::string::npos) pos = minVisibleTransverseMomentumLine.length();
106 
107  std::string sub = minVisibleTransverseMomentumLine.substr(prev, pos - prev);
108  std::vector<MinVisPtCut> cuts;
109  const char* sub_c = sub.c_str();
110  while(*sub_c != '\0')
111  {
112  const char* sep = std::strchr(sub_c, '_');
113  if(sep == NULL) throw cms::Exception("Configuration") << "Minimum transverse parameter string must contain an underscore to separate type from pt threshold" << std::endl;
114  std::string type(sub_c, sep);
115 
117  if(type == "elec1") { cut.type_ = MinVisPtCut::ELEC; cut.index_ = 0; }
118  else if(type == "mu1") { cut.type_ = MinVisPtCut::MU; cut.index_ = 0; }
119  else if(type == "had1") { cut.type_ = MinVisPtCut::HAD; cut.index_ = 0; }
120  else if(type == "tau1") { cut.type_ = MinVisPtCut::TAU; cut.index_ = 0; }
121  else if(type == "elec2") { cut.type_ = MinVisPtCut::ELEC; cut.index_ = 1; }
122  else if(type == "mu2") { cut.type_ = MinVisPtCut::MU; cut.index_ = 1; }
123  else if(type == "had2") { cut.type_ = MinVisPtCut::HAD; cut.index_ = 1; }
124  else if(type == "tau2") { cut.type_ = MinVisPtCut::TAU; cut.index_ = 1; }
125  else throw cms::Exception("Configuration") << "'" << type << "' is not a valid type. Allowed values are elec1,mu1,had1,tau1,elec2,mu2,had2,tau2" << std::endl;
126 
127  char* endptr;
128  cut.pt_ = strtod(sep + 1, &endptr);
129  if(endptr == sep + 1) throw cms::Exception("Configuration") << "No pt threshold given" << std::endl;
130 
131  cuts.push_back(cut);
132  sub_c = endptr;
133  }
134  minVisPtCuts_.push_back(cuts);
135  }
136  }
137 
138  edm::Service<TFileService> fileService_;
139  if(fileService_.isAvailable()) {
140  outTree = fileService_->make<TTree>( "event_generation","This tree stores information about the event generation");
141  outTree->Branch("attempts",&attempts,"attempts/I");
142  }
143 
145  if(!rng.isAvailable()) {
146  throw cms::Exception("Configuration")
147  << "The RandomNumberProducer module requires the RandomNumberGeneratorService\n"
148  "which appears to be absent. Please add that service to your configuration\n"
149  "or remove the modules that require it." << std::endl;
150  }
151  // this is a global variable defined in GeneratorInterface/ExternalDecays/src/ExternalDecayDriver.cc
152  ParticleReplacerVar::decayRandomEngine = &rng->getEngine();
154  edm::LogInfo("Replacer") << "generatorMode = "<< generatorMode_<< "\n";
155 
156  return;
157 }
158 
160 {
161  // do anything here that needs to be done at desctruction time
162  // (e.g. close files, deallocate resources etc.)
163 }
164 
165 // ------------ method called to produce the data ------------
166 std::auto_ptr<HepMC::GenEvent> ParticleReplacerClass::produce(const reco::MuonCollection& muons, const reco::Vertex *pvtx, const HepMC::GenEvent *genEvt)
167 {
168  using namespace edm;
169  using namespace std;
170  using namespace HepMC;
171 
172  if(pvtx != 0)
173  throw cms::Exception("Configuration") << "ParticleReplacerClass does NOT support using primary vertex as the origin for taus" << std::endl;
174 
175  HepMC::GenEvent * evt=0;
176 
177  GenVertex * zvtx = new GenVertex();
178 
179  reco::GenParticle * part1=0;
180  reco::GenParticle * part2=0;
181 
183  std::vector<reco::Particle> particles;
184  switch (transformationMode_)
185  {
186  case 0: // mumu->mumu
187  {
188  if (muons.size()!=2)
189  {
190  LogError("Replacer") << "the decay mode Z->mumu requires exactly two muons, aborting processing";
191  return std::auto_ptr<HepMC::GenEvent>(0);
192  }
193 
194  targetParticleMass_ = 0.105658369;
196 
197  reco::Muon muon1 = muons.at(0);
198  reco::Muon muon2 = muons.at(1);
199  reco::Particle tau1(muon1.charge(), muon1.p4(), muon1.vertex(), muon1.pdgId(), 0, true);
200  reco::Particle tau2(muon2.charge(), muon2.p4(), muon2.vertex(), muon2.pdgId(), 0, true);
201  particles.push_back(tau1);
202  particles.push_back(tau2);
203  break;
204  }
205  case 1: // mumu->tautau
206  {
207  if (muons.size()!=2)
208  {
209  LogError("Replacer") << "the decay mode Z->tautau requires exactly two muons, aborting processing";
210  return std::auto_ptr<HepMC::GenEvent>(0);
211  }
212 
213  targetParticleMass_ = 1.77690;
215 
216  reco::Muon muon1 = muons.at(0);
217  reco::Muon muon2 = muons.at(1);
218  reco::Particle tau1(muon1.charge(), muon1.p4(), muon1.vertex(), muon1.pdgId(), 0, true);
219  reco::Particle tau2(muon2.charge(), muon2.p4(), muon2.vertex(), muon2.pdgId(), 0, true);
220  transformMuMu2TauTau(&tau1, &tau2);
221  particles.push_back(tau1);
222  particles.push_back(tau2);
223  break;
224  }
225  case 2: // mumu->taunu (W boson)
226  {
227  if (muons.size()!=2)
228  {
229  LogError("Replacer") << "the decay mode Z->tautau requires exactly two muons, aborting processing";
230  return std::auto_ptr<HepMC::GenEvent>(0);
231  }
232 
233  targetParticleMass_ = 1.77690;
235 
236  reco::Muon muon1 = muons.at(0);
237  reco::Muon muon2 = muons.at(1);
238  reco::Particle tau1(muon1.charge(), muon1.p4(), muon1.vertex(), muon1.pdgId(), 0, true);
239  reco::Particle tau2(muon2.charge(), muon2.p4(), muon2.vertex(), muon2.pdgId(), 0, true);
240  transformMuMu2TauNu(&tau1, &tau2);
241  particles.push_back(tau1);
242  particles.push_back(tau2);
243  break;
244  }
245  case 3: // mu-nu->tau-nu
246  {
247  if (muons.size()!=2)
248  {
249  LogError("Replacer") << "transformation mode mu-nu ->tau-nu - wrong input";
250  return std::auto_ptr<HepMC::GenEvent>(0);
251  }
252 
253  targetParticleMass_ = 1.77690;
255  int targetParticlePdgIDNu_ = 16;
256 
257  reco::Muon muon1 = muons.at(0);
258  reco::Muon::LorentzVector l(muon1.px(), muon1.py(), muon1.pz(),
259  sqrt(
260  muon1.px()*muon1.px()+
261  muon1.py()*muon1.py()+
262  muon1.pz()*muon1.pz()+targetParticleMass_*targetParticleMass_));
263 
264  reco::Particle tau1(muon1.charge(), l, muon1.vertex(), targetParticlePdgID_*std::abs(muon1.pdgId())/muon1.pdgId()
265  , 0, true
266  );
267  tau1.setStatus(1);
268  particles.push_back(tau1);
269 
270  reco::Muon nu = muons.at(1);
271  reco::Particle nutau( 0, nu.p4(), nu.vertex(), -targetParticlePdgIDNu_*std::abs(muon1.pdgId())/muon1.pdgId(), 0, true);
272  nutau.setStatus(1);
273  particles.push_back(nutau);
274 
275  break;
276  }
277 
278  }
279 
280  if (particles.size()==0)
281  {
282  LogError("Replacer") << "the creation of the new particles failed somehow";
283  return std::auto_ptr<HepMC::GenEvent>(0);
284  }
285  else
286  {
287  LogInfo("Replacer") << particles.size() << " particles found, continue processing";
288  }
289 
291  if (genEvt)
292  {
293 
294  evt = new HepMC::GenEvent(*genEvt);
295 
296  for ( GenEvent::vertex_iterator p = evt->vertices_begin(); p != evt->vertices_end(); p++ )
297  {
298  GenVertex * vtx=(*p);
299 
300  if ( vtx->particles_out_size()<=0 || vtx->particles_in_size()<=0)
301  continue;
302 
303  bool temp_muon1=false,temp_muon2=false,temp_z=false;
304  for (GenVertex::particles_out_const_iterator it = vtx->particles_out_const_begin(); it!=vtx->particles_out_const_end(); it++)
305  {
306  if ((*it)->pdg_id()==13) temp_muon1=true;
307  if ((*it)->pdg_id()==-13) temp_muon2=true;
308  if ((*it)->pdg_id()==23) temp_z=true;
309  }
310 
311  int mother_pdg=(*vtx->particles_in_const_begin())->pdg_id();
312 
313  if ((vtx->particles_out_size()==2 && vtx->particles_in_size()>0
314  && mother_pdg == 23
315  && temp_muon1
316  && temp_muon2)
317  || (vtx->particles_out_size()>2 && vtx->particles_in_size()>0
318  && mother_pdg == 23
319  && temp_muon1 && temp_muon2 && temp_z ))
320  {
321  zvtx=*p;
322  }
323  }
324 
325  cleanEvent(evt, zvtx);
326 
327  // prevent a decay of existing particles
328  // this is due to a bug in the PythiaInterface that should be fixed in newer versions
329  for (GenEvent::particle_iterator it=evt->particles_begin();it!=evt->particles_end();it++)
330  (*it)->set_status(0);
331 
332  for (std::vector<reco::Particle>::const_iterator it=particles.begin();it!=particles.end();it++)
333  {
334  zvtx->add_particle_out(new HepMC::GenParticle((FourVector)it->p4(), it->pdgId(), 1, Flow(), Polarization(0,0)));
335  }
336  }
337  // new product with tau decays
338  else
339  {
340  reco::Particle::LorentzVector mother_particle_p4;
341  for (std::vector<reco::Particle>::const_iterator it=particles.begin();it!=particles.end();it++)
342  mother_particle_p4+=it->p4();
343 
344  reco::Particle::Point production_point = particles.begin()->vertex();
345 
346  GenVertex* startVtx = new GenVertex(FourVector(production_point.x()*10,production_point.y()*10,production_point.z()*10,0));
347  startVtx->add_particle_in( new GenParticle( FourVector(0,0,7000,7000), 2212, 3 ) );
348  startVtx->add_particle_in( new GenParticle( FourVector(0,0,-7000,7000), 2212, 3 ) );
349 
350  GenVertex * decayvtx = new GenVertex(FourVector(production_point.x()*10,production_point.y()*10,production_point.z()*10,0));
351  HepMC::GenParticle * mother_particle = new HepMC::GenParticle((FourVector)mother_particle_p4, motherParticleID_, (generatorMode_=="Pythia" ? 3 : 2), Flow(), Polarization(0,0));
352  if (transformationMode_ == 3) {
353  //std::cout << "Overriding mother particle id\n" << std::endl;
354  int muPDG = particles.begin()->pdgId();
355  int id = -24*muPDG/std::abs(muPDG);
356  mother_particle->set_pdg_id(id);
357  }
358 
359  startVtx->add_particle_out(mother_particle);
360  decayvtx->add_particle_in(mother_particle);
361  evt = new HepMC::GenEvent();
362  for (std::vector<reco::Particle>::const_iterator it=particles.begin();it!=particles.end();it++)
363  {
364  //std::cout << "XXX" << it->p4().pt() << " " << it->pdgId() << std::endl;
365  decayvtx->add_particle_out(new HepMC::GenParticle((FourVector)it->p4(), it->pdgId(), 1, Flow(), Polarization(0,0)));
366  }
367 
368  evt->add_vertex(startVtx);
369  evt->add_vertex(decayvtx);
370  }
371  repairBarcodes(evt);
372 
373  HepMC::GenEvent * retevt = 0;
374  HepMC::GenEvent * tempevt = 0;
375 
377  int nr_of_trials=0;
378 
379  unsigned int cntVisPt_all = 0;
380  unsigned int cntVisPt_pass = 0;
381 
382  HepMC::IO_HEPEVT conv;
383  for (int i = 0; i<maxNumberOfAttempts_; i++)
384  {
385  ++cntVisPt_all;
386  if (generatorMode_ == "Pythia") // Pythia
387  {
388  LogError("Replacer") << "Pythia is currently not supported!";
389  return std::auto_ptr<HepMC::GenEvent>(evt);
390  }
391 
392  if (generatorMode_ == "Tauola") // TAUOLA
393  {
394  conv.write_event(evt);
395  tempevt=tauola_->decay(evt);
396  }
397 
398  if (testEvent(tempevt))
399  {
400  if (retevt==0) {
401  retevt=tempevt;
402  } else {
403  delete tempevt;
404  }
405  ++cntVisPt_pass;
406  } else {
407  delete tempevt;
408  }
409  }
410 
411  tried = cntVisPt_all;
412  passed = cntVisPt_pass;
413 
414  std::cout << /*minVisibleTransverseMomentum_ <<*/ " " << cntVisPt_pass << "\t" << cntVisPt_all << "\n";
415  if (!retevt)
416  {
417  LogError("Replacer") << "failed to create an event which satisfies the minimum visible transverse momentum cuts ";
418  attempts=-1;
419  if(outTree) outTree->Fill();
420  return std::auto_ptr<HepMC::GenEvent>(0);
421  }
422  attempts=nr_of_trials;
423  if(outTree) outTree->Fill();
424 
425  // recover the status codes
426  if (genEvt)
427  {
428  for (GenEvent::particle_iterator it=retevt->particles_begin();it!=retevt->particles_end();it++)
429  {
430  if ((*it)->end_vertex())
431  (*it)->set_status(2);
432  else
433  (*it)->set_status(1);
434  }
435  }
436 
437  std::auto_ptr<HepMC::GenEvent> ret(retevt);
438 
439  if (printEvent_)
440  retevt->print(std::cout);
441 
442  delete part1;
443  delete part2;
444  delete zvtx;
445  delete evt;
446  return ret;
447 }
448 
449 // ------------ method called once each job just before starting event loop ------------
451 {
452  tauola_->init(iSetup);
453 }
454 
455 // ------------ method called once each job just after ending the event loop ------------
456 void
458 {
459  tauola_->statistics();
460 }
461 
462 bool ParticleReplacerClass::testEvent(HepMC::GenEvent * evt)
463 {
464  using namespace HepMC;
465  using namespace edm;
466 
467  if (minVisPtCuts_.empty()) //ibleTransverseMomentum_<=0)
468  return true;
469 
470  std::vector<double> mus;
471  std::vector<double> elecs;
472  std::vector<double> hads;
473  std::vector<double> taus;
474 
475  for (GenEvent::particle_iterator it=evt->particles_begin();it!=evt->particles_end();it++)
476  {
477  if (abs((*it)->pdg_id())==15 && (*it)->end_vertex())
478  {
479  FourVector vis_mom();
480  math::PtEtaPhiMLorentzVector visible_momentum;
481  std::queue<const GenParticle *> decaying_particles;
482  decaying_particles.push(*it);
483  int t=0;
484  enum { ELEC, MU, HAD } type = HAD;
485  while(!decaying_particles.empty() && (++t < 30))
486  {
487  const GenParticle * front = decaying_particles.front();
488  decaying_particles.pop();
489 
490  if (!front->end_vertex())
491  {
492  int pdgId=abs(front->pdg_id());
493  if (pdgId>10 && pdgId!=12 && pdgId!=14 && pdgId!=16)
494  visible_momentum+=(math::PtEtaPhiMLorentzVector)front->momentum();
495 
496  if(pdgId == 11) type = ELEC;
497  if(pdgId == 13) type = MU;
498  }
499  else
500  {
501  GenVertex * temp_vert = front->end_vertex();
502  for (GenVertex::particles_out_const_iterator it2=temp_vert->particles_out_const_begin();it2!=temp_vert->particles_out_const_end();it2++)
503  decaying_particles.push((*it2));
504  }
505  }
506 
507  double vis_pt = visible_momentum.pt();
508  taus.push_back(vis_pt);
509  if(type == MU) mus.push_back(vis_pt);
510  if(type == ELEC) elecs.push_back(vis_pt);
511  if(type == HAD) hads.push_back(vis_pt);
512  }
513  }
514 
515  std::sort(taus.begin(), taus.end(), std::greater<double>());
516  std::sort(elecs.begin(), elecs.end(), std::greater<double>());
517  std::sort(mus.begin(), mus.end(), std::greater<double>());
518  std::sort(hads.begin(), hads.end(), std::greater<double>());
519 
520  for(std::vector<std::vector<MinVisPtCut> >::const_iterator iter = minVisPtCuts_.begin(); iter != minVisPtCuts_.end(); ++iter)
521  {
522  std::vector<MinVisPtCut>::const_iterator iter2;
523  for(iter2 = iter->begin(); iter2 != iter->end(); ++iter2)
524  {
525  std::vector<double>* collection;
526  switch(iter2->type_)
527  {
528  case MinVisPtCut::ELEC: collection = &elecs; break;
529  case MinVisPtCut::MU: collection = &mus; break;
530  case MinVisPtCut::HAD: collection = &hads; break;
531  case MinVisPtCut::TAU: collection = &taus; break;
532  default: assert(false); break;
533  }
534 
535  // subcut fail
536  if(iter2->index_ >= collection->size() || (*collection)[iter2->index_] < iter2->pt_)
537  break;
538  }
539 
540  // no subcut failed: This cut passed
541  if(iter2 == iter->end())
542  return true;
543  }
544 
545  LogInfo("Replacer") << "refusing the event as the sum of the visible transverse momenta is too small\n";
546  return false;
547 }
548 
549 void ParticleReplacerClass::cleanEvent(HepMC::GenEvent * evt, HepMC::GenVertex * vtx)
550 {
551  using namespace HepMC;
552  using namespace std;
553  using namespace edm;
554  using namespace reco;
555 
556  stack<HepMC::GenParticle *> deleteParticle;
557 
558  stack<GenVertex *> deleteVertex;
559  stack<GenVertex *> queueVertex;
560 
561  if (vtx->particles_out_size()>0)
562  {
563  for (GenVertex::particles_out_const_iterator it=vtx->particles_out_const_begin();it!=vtx->particles_out_const_end();it++)
564  {
565  deleteParticle.push(*it);
566  if ((*it)->end_vertex())
567  queueVertex.push((*it)->end_vertex());
568  }
569  }
570 
571  while (!queueVertex.empty())
572  {
573  GenVertex * temp_vtx=queueVertex.top();
574  if (temp_vtx->particles_out_size()>0)
575  {
576  for (GenVertex::particles_out_const_iterator it=temp_vtx->particles_out_const_begin();it!=temp_vtx->particles_out_const_end();it++)
577  {
578  if ((*it)->end_vertex())
579  queueVertex.push((*it)->end_vertex());
580  }
581  delete temp_vtx;
582  }
583  deleteVertex.push(queueVertex.top());
584  queueVertex.pop();
585  }
586 
587  while (!deleteVertex.empty())
588  {
589  evt->remove_vertex(deleteVertex.top());
590  deleteVertex.pop();
591  }
592 
593  while (!deleteParticle.empty())
594  {
595  delete vtx->remove_particle(deleteParticle.top());
596  deleteParticle.pop();
597  }
598 
599  while (!deleteVertex.empty())
600  deleteVertex.pop();
601  while (!queueVertex.empty())
602  queueVertex.pop();
603 
604  repairBarcodes(evt);
605 }
606 
607 void ParticleReplacerClass::repairBarcodes(HepMC::GenEvent * evt)
608 {
609  using namespace HepMC;
610 
611  // repair the barcodes
612  int max_barc=0;
613  for (GenEvent::vertex_iterator it=evt->vertices_begin(), next;it!=evt->vertices_end();it=next)
614  {
615  next=it;++next;
616  while (!(*it)->suggest_barcode(-1*(++max_barc)))
617  ;
618  }
619 
620  max_barc=0;
621  for (GenEvent::particle_iterator it=evt->particles_begin(), next;it!=evt->particles_end();it=next)
622  {
623  next=it;++next;
624  while (!(*it)->suggest_barcode(++max_barc))
625  ;
626  }
627 }
628 
631 {
632  using namespace edm;
633  using namespace reco;
634  using namespace std;
635 
636  reco::Particle::LorentzVector muon1_momentum = muon1->p4();
637  reco::Particle::LorentzVector muon2_momentum = muon2->p4();
638  reco::Particle::LorentzVector z_momentum = muon1_momentum + muon2_momentum;
639 
640  ROOT::Math::Boost booster(z_momentum.BoostToCM());
641  ROOT::Math::Boost invbooster(booster.Inverse());
642 
643  reco::Particle::LorentzVector Zb = booster(z_momentum);
644 
645  reco::Particle::LorentzVector muon1b = booster(muon1_momentum);
646  reco::Particle::LorentzVector muon2b = booster(muon2_momentum);
647 
648  double tau_mass2 = targetParticleMass_*targetParticleMass_;
649 
650  double muonxb_mom2 = muon1b.x()*muon1b.x() + muon1b.y()*muon1b.y() + muon1b.z() * muon1b.z();
651  double tauxb_mom2 = 0.25 * Zb.t() * Zb.t() - tau_mass2;
652 
653  float scaling1 = sqrt(tauxb_mom2 / muonxb_mom2);
654  float scaling2 = scaling1;
655 
656  float tauEnergy= Zb.t() / 2.;
657 
658  if (tauEnergy*tauEnergy<tau_mass2)
659  return;
660 
661  reco::Particle::LorentzVector tau1b_mom = reco::Particle::LorentzVector(scaling1*muon1b.x(),scaling1*muon1b.y(),scaling1*muon1b.z(),tauEnergy);
662  reco::Particle::LorentzVector tau2b_mom = reco::Particle::LorentzVector(scaling2*muon2b.x(),scaling2*muon2b.y(),scaling2*muon2b.z(),tauEnergy);
663 
664  reco::Particle::LorentzVector tau1_mom = (invbooster(tau1b_mom));
665  reco::Particle::LorentzVector tau2_mom = (invbooster(tau2b_mom));
666 
667  // some additional checks
668  // the following tests guarantee a deviation of less
669  // than 0.1% for the following values of the original
670  // muons and the placed taus
671  // invariant mass
672  // transverse momentum
673  assert(std::abs((muon1_momentum+muon2_momentum).mass()-(tau1_mom+tau2_mom).mass())/(muon1_momentum+muon2_momentum).mass()<0.001);
674  assert(std::abs((muon1_momentum+muon2_momentum).pt()-(tau1_mom+tau2_mom).pt())/(muon1_momentum+muon2_momentum).pt()<0.001);
675 
676  muon1->setP4(tau1_mom);
677  muon2->setP4(tau2_mom);
678 
679  muon1->setPdgId(targetParticlePdgID_*muon1->pdgId()/abs(muon1->pdgId()));
680  muon2->setPdgId(targetParticlePdgID_*muon2->pdgId()/abs(muon2->pdgId()));
681 
682  muon1->setStatus(1);
683  muon2->setStatus(1);
684 
685  return;
686 }
689 {
690  using namespace edm;
691  using namespace reco;
692  using namespace std;
693 
694  reco::Particle::LorentzVector muon1_momentum = part1->p4();
695  reco::Particle::LorentzVector muon2_momentum = part2->p4();
696  reco::Particle::LorentzVector z_momentum = muon1_momentum + muon2_momentum;
697 
698  ROOT::Math::Boost booster(z_momentum.BoostToCM());
699  ROOT::Math::Boost invbooster(booster.Inverse());
700 
701  reco::Particle::LorentzVector Zb = booster(z_momentum);
702 
703  const double breitWignerWidth_Z = 2.4952;
704  const double breitWignerWidth_W = 2.141;
705  const double knownMass_W = 80.398;
706  const double knownMass_Z = 91.1876;
707 
708  double Wb_mass = ( Zb.mass() - knownMass_Z ) * ( breitWignerWidth_W / breitWignerWidth_Z ) + knownMass_W;
709  std::cout << "Wb_mass: " << Wb_mass << "\n";
710 
711  reco::Particle::LorentzVector muon1b = booster(muon1_momentum);
712  reco::Particle::LorentzVector muon2b = booster(muon2_momentum);
713 
714  double tau_mass2 = targetParticleMass_*targetParticleMass_;
715 
716  double muonxb_mom2 = muon1b.x()*muon1b.x() + muon1b.y()*muon1b.y() + muon1b.z() * muon1b.z();
717  double tauxb_mom2 = 0.25 * Zb.t() * Zb.t() - tau_mass2;
718 
719  float scaling1 = sqrt(tauxb_mom2 / muonxb_mom2) * Wb_mass/Zb.mass();
720  float scaling2 = scaling1;
721 
722  float tauEnergy= Zb.t() / 2.;
723 
724  if (tauEnergy*tauEnergy<tau_mass2)
725  return;
726 
727  reco::Particle::LorentzVector tau1b_mom = reco::Particle::LorentzVector(scaling1*muon1b.x(),scaling1*muon1b.y(),scaling1*muon1b.z(),tauEnergy* Wb_mass/Zb.mass());
728  reco::Particle::LorentzVector tau2b_mom = reco::Particle::LorentzVector(scaling2*muon2b.x(),scaling2*muon2b.y(),scaling2*muon2b.z(),tauEnergy* Wb_mass/Zb.mass());
729 
730  std::cout << "muon1b_momentum: " << muon1b << "\n";
731  std::cout << "muon2b_momentum: " << muon2b << "\n";
732 
733  std::cout << "tau1b_momentum: " << tau1b_mom << "\n";
734  std::cout << "tau2b_momentum: " << tau2b_mom << "\n";
735 
736  std::cout << "zb_momentum: " << Zb << "\n";
737  std::cout << "wb_momentum: " << (tau1b_mom+tau2b_mom) << "\n";
738 
739  // some checks
740  // the following test guarantees a deviation
741  // of less than 0.1% for phi and theta for the
742  // original muons and the placed taus
743  // (in the centre-of-mass system of the z boson)
744  assert((muon1b.phi()-tau1b_mom.phi())/muon1b.phi()<0.001);
745  assert((muon2b.phi()-tau2b_mom.phi())/muon2b.phi()<0.001);
746  assert((muon1b.theta()-tau1b_mom.theta())/muon1b.theta()<0.001);
747  assert((muon2b.theta()-tau2b_mom.theta())/muon2b.theta()<0.001);
748 
749  reco::Particle::LorentzVector tau1_mom = (invbooster(tau1b_mom));
750  reco::Particle::LorentzVector tau2_mom = (invbooster(tau2b_mom));
751 
752  // some additional checks
753  // the following tests guarantee a deviation of less
754  // than 0.1% for the following values of the original
755  // muons and the placed taus
756  // invariant mass
757  // transverse momentum
758  //assert(((muon1_momentum+muon1_momentum).mass()-(tau1_mom+tau2_mom).mass())/(muon1_momentum+muon1_momentum).mass()<0.001);
759  //assert(((muon1_momentum+muon2_momentum).pt()-(tau1_mom+tau2_mom).pt())/(muon1_momentum+muon1_momentum).pt()<0.001);
760 
761  part1->setP4(tau1_mom);
762  part2->setP4(tau2_mom);
763 
764  part1->setPdgId(15*part1->pdgId()/abs(part1->pdgId()));
765  part2->setPdgId(16*part2->pdgId()/abs(part2->pdgId()));
766 
767  part1->setStatus(1);
768  part2->setStatus(1);
769 
770  return;
771 }
772 
773 
774 //define this as a plug-in
775 //DEFINE_FWK_MODULE(Replacer);
type
Definition: HCALResponse.h:21
T getParameter(std::string const &) const
T getUntrackedParameter(std::string const &, T const &) const
int i
Definition: DBlmapReader.cc:9
void repairBarcodes(HepMC::GenEvent *evt)
virtual void SetDecayRandomEngine(CLHEP::HepRandomEngine *decayRandomEngine)
void setP4(const LorentzVector &p4)
set 4-momentum
Definition: Particle.h:105
virtual const LorentzVector & p4() const GCC11_FINAL
four-momentum Lorentz vector
virtual void init(const edm::EventSetup &)
static HepMC::IO_HEPEVT conv
virtual const Point & vertex() const
vertex position (overwritten by PF...)
virtual int pdgId() const GCC11_FINAL
PDG identifier.
ParticleReplacerClass(const edm::ParameterSet &, bool)
bool testEvent(HepMC::GenEvent *evt)
#define abs(x)
Definition: mlp_lapack.h:159
#define NULL
Definition: scimark2.h:8
const LorentzVector & p4() const
four-momentum Lorentz vector
Definition: Particle.h:64
uint16_t size_type
virtual double pz() const GCC11_FINAL
z coordinate of momentum vector
virtual double py() const GCC11_FINAL
y coordinate of momentum vector
int pdgId() const
PDG identifier.
Definition: Particle.h:150
std::vector< Muon > MuonCollection
collection of Muon objects
Definition: MuonFwd.h:9
virtual void beginRun(const edm::Run &iRun, const edm::EventSetup &iSetup)
PtEtaPhiMLorentzVectorD PtEtaPhiMLorentzVector
Lorentz vector with cartesian internal representation.
Definition: LorentzVector.h:26
gen::TauolaInterfaceBase * tauola_
T sqrt(T t)
Definition: SSEVec.h:48
enum ParticleReplacerClass::MinVisPtCut::@520 type_
virtual double px() const GCC11_FINAL
x coordinate of momentum vector
math::XYZPoint Point
point in the space
Definition: Particle.h:29
#define TXGIVE
#define TXGIVE_INIT
virtual int charge() const GCC11_FINAL
electric charge
void setPdgId(int pdgId)
Definition: Particle.h:152
virtual HepMC::GenEvent * decay(HepMC::GenEvent *evt)
math::XYZTLorentzVector LorentzVector
Lorentz vector.
Definition: Candidate.h:41
void cleanEvent(HepMC::GenEvent *evt, HepMC::GenVertex *vtx)
void transformMuMu2TauNu(reco::Particle *muon1, reco::Particle *muon2)
transform a muon pair into tau nu (as coming from a W boson)
tuple muons
Definition: patZpeak.py:38
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
CLHEP::HepRandomEngine * decayRandomEngine
void transformMuMu2TauTau(reco::Particle *muon1, reco::Particle *muon2)
transform a muon pair into a tau pair
virtual std::auto_ptr< HepMC::GenEvent > produce(const reco::MuonCollection &muons, const reco::Vertex *pvtx=0, const HepMC::GenEvent *genEvt=0)
math::XYZTLorentzVector LorentzVector
Lorentz vector.
Definition: Particle.h:25
void setStatus(int status)
set status word
Definition: Particle.h:156
std::vector< std::vector< MinVisPtCut > > minVisPtCuts_
T get(const Candidate &c)
Definition: component.h:56
Definition: Run.h:36