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.
1 
3 
6 
8 
9 #include "HepMC/IO_HEPEVT.h"
10 
11 #ifndef TXGIVE
12 #define TXGIVE txgive_
13 extern "C" {
14  void TXGIVE(const char*,int length);
15 }
16 #endif
17 
18 #ifndef TXGIVE_INIT
19 #define TXGIVE_INIT txgive_init_
20 extern "C" {
21  void TXGIVE_INIT();
22 }
23 #endif
24 
27  generatorMode_(pset.getParameter<std::string>("generatorMode")),
28  printEvent_(verbose),
29  outTree(0),
30  maxNumberOfAttempts_(pset.getUntrackedParameter<int>("maxNumberOfAttempts", 1000))
31 {
32  tauola_ = (gen::TauolaInterfaceBase*)(TauolaFactory::get()->create("Tauola271215", pset.getParameter< edm::ParameterSet>("TauolaOptions")));
33 
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  CLHEP::HepRandomEngine* decayRandomEngine = &rng->getEngine();
154 
155  edm::LogInfo("Replacer") << "generatorMode = "<< generatorMode_<< "\n";
156  edm::LogInfo("Replacer") << "replacementMode = "<< replacementMode_<< "\n";
157 
158  return;
159 }
160 
162 {
163  delete tauola_;
164  // do anything here that needs to be done at desctruction time
165  // (e.g. close files, deallocate resources etc.)
166 }
167 
168 // ------------ method called to produce the data ------------
169 std::auto_ptr<HepMC::GenEvent> ParticleReplacerClass::produce(const reco::MuonCollection& muons, const reco::Vertex *pvtx, const HepMC::GenEvent *genEvt)
170 {
171  using namespace edm;
172  using namespace std;
173  using namespace HepMC;
174 
175  if(pvtx != 0)
176  throw cms::Exception("Configuration") << "ParticleReplacerClass does NOT support using primary vertex as the origin for taus" << std::endl;
177 
178  HepMC::GenEvent * evt=0;
179 
180  GenVertex * zvtx = new GenVertex();
181 
182  reco::GenParticle * part1=0;
183  reco::GenParticle * part2=0;
184 
186  std::vector<reco::Particle> particles;
187  switch (transformationMode_)
188  {
189  case 0: // mumu->mumu
190  {
191  if (muons.size()!=2)
192  {
193  LogError("Replacer") << "the decay mode Z->mumu requires exactly two muons, aborting processing";
194  return std::auto_ptr<HepMC::GenEvent>(0);
195  }
196 
197  targetParticleMass_ = 0.105658369;
199 
200  reco::Muon muon1 = muons.at(0);
201  reco::Muon muon2 = muons.at(1);
202  reco::Particle tau1(muon1.charge(), muon1.p4(), muon1.vertex(), muon1.pdgId(), 0, true);
203  reco::Particle tau2(muon2.charge(), muon2.p4(), muon2.vertex(), muon2.pdgId(), 0, true);
204  particles.push_back(tau1);
205  particles.push_back(tau2);
206  break;
207  }
208  case 1: // mumu->tautau
209  {
210  if (muons.size()!=2)
211  {
212  LogError("Replacer") << "the decay mode Z->tautau requires exactly two muons, aborting processing";
213  return std::auto_ptr<HepMC::GenEvent>(0);
214  }
215 
216  targetParticleMass_ = 1.77690;
218 
219  reco::Muon muon1 = muons.at(0);
220  reco::Muon muon2 = muons.at(1);
221  reco::Particle tau1(muon1.charge(), muon1.p4(), muon1.vertex(), muon1.pdgId(), 0, true);
222  reco::Particle tau2(muon2.charge(), muon2.p4(), muon2.vertex(), muon2.pdgId(), 0, true);
223  transformMuMu2TauTau(&tau1, &tau2);
224  particles.push_back(tau1);
225  particles.push_back(tau2);
226  break;
227  }
228  case 2: // mumu->taunu (W boson)
229  {
230  if (muons.size()!=2)
231  {
232  LogError("Replacer") << "the decay mode Z->tautau requires exactly two muons, aborting processing";
233  return std::auto_ptr<HepMC::GenEvent>(0);
234  }
235 
236  targetParticleMass_ = 1.77690;
238 
239  reco::Muon muon1 = muons.at(0);
240  reco::Muon muon2 = muons.at(1);
241  reco::Particle tau1(muon1.charge(), muon1.p4(), muon1.vertex(), muon1.pdgId(), 0, true);
242  reco::Particle tau2(muon2.charge(), muon2.p4(), muon2.vertex(), muon2.pdgId(), 0, true);
243  transformMuMu2TauNu(&tau1, &tau2);
244  particles.push_back(tau1);
245  particles.push_back(tau2);
246  break;
247  }
248  case 3: // mu-nu->tau-nu
249  {
250  if (muons.size()!=2)
251  {
252  LogError("Replacer") << "transformation mode mu-nu ->tau-nu - wrong input";
253  return std::auto_ptr<HepMC::GenEvent>(0);
254  }
255 
256  targetParticleMass_ = 1.77690;
258  int targetParticlePdgIDNu_ = 16;
259 
260  reco::Muon muon1 = muons.at(0);
261  reco::Muon::LorentzVector l(muon1.px(), muon1.py(), muon1.pz(),
262  sqrt(
263  muon1.px()*muon1.px()+
264  muon1.py()*muon1.py()+
265  muon1.pz()*muon1.pz()+targetParticleMass_*targetParticleMass_));
266 
267  reco::Particle tau1(muon1.charge(), l, muon1.vertex(), targetParticlePdgID_*std::abs(muon1.pdgId())/muon1.pdgId()
268  , 0, true
269  );
270  tau1.setStatus(1);
271  particles.push_back(tau1);
272 
273  reco::Muon nu = muons.at(1);
274  reco::Particle nutau( 0, nu.p4(), nu.vertex(), -targetParticlePdgIDNu_*std::abs(muon1.pdgId())/muon1.pdgId(), 0, true);
275  nutau.setStatus(1);
276  particles.push_back(nutau);
277 
278  break;
279  }
280 
281  }
282 
283  if (particles.size()==0)
284  {
285  LogError("Replacer") << "the creation of the new particles failed somehow";
286  return std::auto_ptr<HepMC::GenEvent>(0);
287  }
288  else
289  {
290  LogInfo("Replacer") << particles.size() << " particles found, continue processing";
291  }
292 
294  if (genEvt)
295  {
296 
297  evt = new HepMC::GenEvent(*genEvt);
298 
299  for ( GenEvent::vertex_iterator p = evt->vertices_begin(); p != evt->vertices_end(); p++ )
300  {
301  GenVertex * vtx=(*p);
302 
303  if ( vtx->particles_out_size()<=0 || vtx->particles_in_size()<=0)
304  continue;
305 
306  bool temp_muon1=false,temp_muon2=false,temp_z=false;
307  for (GenVertex::particles_out_const_iterator it = vtx->particles_out_const_begin(); it!=vtx->particles_out_const_end(); it++)
308  {
309  if ((*it)->pdg_id()==13) temp_muon1=true;
310  if ((*it)->pdg_id()==-13) temp_muon2=true;
311  if ((*it)->pdg_id()==23) temp_z=true;
312  }
313 
314  int mother_pdg=(*vtx->particles_in_const_begin())->pdg_id();
315 
316  if ((vtx->particles_out_size()==2 && vtx->particles_in_size()>0
317  && mother_pdg == 23
318  && temp_muon1
319  && temp_muon2)
320  || (vtx->particles_out_size()>2 && vtx->particles_in_size()>0
321  && mother_pdg == 23
322  && temp_muon1 && temp_muon2 && temp_z ))
323  {
324  zvtx=*p;
325  }
326  }
327 
328  cleanEvent(evt, zvtx);
329 
330  // prevent a decay of existing particles
331  // this is due to a bug in the PythiaInterface that should be fixed in newer versions
332  for (GenEvent::particle_iterator it=evt->particles_begin();it!=evt->particles_end();it++)
333  (*it)->set_status(0);
334 
335  for (std::vector<reco::Particle>::const_iterator it=particles.begin();it!=particles.end();it++)
336  {
337  zvtx->add_particle_out(new HepMC::GenParticle((FourVector)it->p4(), it->pdgId(), 1, Flow(), Polarization(0,0)));
338  }
339  }
340  // new product with tau decays
341  else
342  {
343  reco::Particle::LorentzVector mother_particle_p4;
344  for (std::vector<reco::Particle>::const_iterator it=particles.begin();it!=particles.end();it++)
345  mother_particle_p4+=it->p4();
346 
347  reco::Particle::Point production_point = particles.begin()->vertex();
348 
349  GenVertex* startVtx = new GenVertex(FourVector(production_point.x()*10,production_point.y()*10,production_point.z()*10,0));
350  startVtx->add_particle_in( new GenParticle( FourVector(0,0,7000,7000), 2212, 3 ) );
351  startVtx->add_particle_in( new GenParticle( FourVector(0,0,-7000,7000), 2212, 3 ) );
352 
353  GenVertex * decayvtx = new GenVertex(FourVector(production_point.x()*10,production_point.y()*10,production_point.z()*10,0));
354  HepMC::GenParticle * mother_particle = new HepMC::GenParticle((FourVector)mother_particle_p4, motherParticleID_, (generatorMode_=="Pythia" ? 3 : 2), Flow(), Polarization(0,0));
355  if (transformationMode_ == 3) {
356  //std::cout << "Overriding mother particle id\n" << std::endl;
357  int muPDG = particles.begin()->pdgId();
358  int id = -24*muPDG/std::abs(muPDG);
359  mother_particle->set_pdg_id(id);
360  }
361 
362  startVtx->add_particle_out(mother_particle);
363  decayvtx->add_particle_in(mother_particle);
364  evt = new HepMC::GenEvent();
365  for (std::vector<reco::Particle>::const_iterator it=particles.begin();it!=particles.end();it++)
366  {
367  //std::cout << "XXX" << it->p4().pt() << " " << it->pdgId() << std::endl;
368  decayvtx->add_particle_out(new HepMC::GenParticle((FourVector)it->p4(), it->pdgId(), 1, Flow(), Polarization(0,0)));
369  }
370 
371  evt->add_vertex(startVtx);
372  evt->add_vertex(decayvtx);
373  }
374  repairBarcodes(evt);
375 
376  HepMC::GenEvent * retevt = 0;
377  HepMC::GenEvent * tempevt = 0;
378 
380  int nr_of_trials=0;
381 
382  unsigned int cntVisPt_all = 0;
383  unsigned int cntVisPt_pass = 0;
384 
385  HepMC::IO_HEPEVT conv;
386  for (int i = 0; i<maxNumberOfAttempts_; i++)
387  {
388  ++cntVisPt_all;
389  if (generatorMode_ == "Pythia") // Pythia
390  {
391  LogError("Replacer") << "Pythia is currently not supported!";
392  return std::auto_ptr<HepMC::GenEvent>(evt);
393  }
394 
395  if (generatorMode_ == "Tauola") // TAUOLA
396  {
397  conv.write_event(evt);
398  tempevt=tauola_->decay(evt);
399  }
400 
401  if (testEvent(tempevt))
402  {
403  if (retevt==0) {
404  retevt=tempevt;
405  } else {
406  delete tempevt;
407  }
408  ++cntVisPt_pass;
409  } else {
410  delete tempevt;
411  }
412  }
413  eventWeight = (double)cntVisPt_pass / (double)cntVisPt_all;
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  eventWeight=0;
420  if(outTree) outTree->Fill();
421  return std::auto_ptr<HepMC::GenEvent>(0);
422  }
423  attempts=nr_of_trials;
424  if(outTree) outTree->Fill();
425 
426  // recover the status codes
427  if (replacementMode_==0)
428  {
429  for (GenEvent::particle_iterator it=retevt->particles_begin();it!=retevt->particles_end();it++)
430  {
431  if ((*it)->end_vertex())
432  (*it)->set_status(2);
433  else
434  (*it)->set_status(1);
435  }
436  }
437 
438  std::auto_ptr<HepMC::GenEvent> ret(retevt);
439 
440  if (printEvent_)
441  retevt->print(std::cout);
442 
443  delete part1;
444  delete part2;
445  delete zvtx;
446  delete evt;
447  return ret;
448 }
449 
450 // ------------ method called once each job just before starting event loop ------------
452 {
453  tauola_->init(iSetup);
454 }
455 
456 // ------------ method called once each job just after ending the event loop ------------
457 void
459 {
460  tauola_->statistics();
461 }
462 
463 bool ParticleReplacerClass::testEvent(HepMC::GenEvent * evt)
464 {
465  using namespace HepMC;
466  using namespace edm;
467 
468  if (minVisPtCuts_.empty()) //ibleTransverseMomentum_<=0)
469  return true;
470 
471  std::vector<double> mus;
472  std::vector<double> elecs;
473  std::vector<double> hads;
474  std::vector<double> taus;
475 
476  for (GenEvent::particle_iterator it=evt->particles_begin();it!=evt->particles_end();it++)
477  {
478  if (abs((*it)->pdg_id())==15 && (*it)->end_vertex())
479  {
480  FourVector vis_mom();
481  math::PtEtaPhiMLorentzVector visible_momentum;
482  std::queue<const GenParticle *> decaying_particles;
483  decaying_particles.push(*it);
484  int t=0;
485  enum { ELEC, MU, HAD } type = HAD;
486  while(!decaying_particles.empty() && (++t < 30))
487  {
488  const GenParticle * front = decaying_particles.front();
489  decaying_particles.pop();
490 
491  if (!front->end_vertex())
492  {
493  int pdgId=abs(front->pdg_id());
494  if (pdgId>10 && pdgId!=12 && pdgId!=14 && pdgId!=16)
495  visible_momentum+=(math::PtEtaPhiMLorentzVector)front->momentum();
496 
497  if(pdgId == 11) type = ELEC;
498  if(pdgId == 13) type = MU;
499  }
500  else
501  {
502  GenVertex * temp_vert = front->end_vertex();
503  for (GenVertex::particles_out_const_iterator it2=temp_vert->particles_out_const_begin();it2!=temp_vert->particles_out_const_end();it2++)
504  decaying_particles.push((*it2));
505  }
506  }
507 
508  double vis_pt = visible_momentum.pt();
509  taus.push_back(vis_pt);
510  if(type == MU) mus.push_back(vis_pt);
511  if(type == ELEC) elecs.push_back(vis_pt);
512  if(type == HAD) hads.push_back(vis_pt);
513  }
514  }
515 
516  std::sort(taus.begin(), taus.end(), std::greater<double>());
517  std::sort(elecs.begin(), elecs.end(), std::greater<double>());
518  std::sort(mus.begin(), mus.end(), std::greater<double>());
519  std::sort(hads.begin(), hads.end(), std::greater<double>());
520 
521  for(std::vector<std::vector<MinVisPtCut> >::const_iterator iter = minVisPtCuts_.begin(); iter != minVisPtCuts_.end(); ++iter)
522  {
523  std::vector<MinVisPtCut>::const_iterator iter2;
524  for(iter2 = iter->begin(); iter2 != iter->end(); ++iter2)
525  {
526  std::vector<double>* collection;
527  switch(iter2->type_)
528  {
529  case MinVisPtCut::ELEC: collection = &elecs; break;
530  case MinVisPtCut::MU: collection = &mus; break;
531  case MinVisPtCut::HAD: collection = &hads; break;
532  case MinVisPtCut::TAU: collection = &taus; break;
533  default: assert(false); break;
534  }
535 
536  // subcut fail
537  if(iter2->index_ >= collection->size() || (*collection)[iter2->index_] < iter2->pt_)
538  break;
539  }
540 
541  // no subcut failed: This cut passed
542  if(iter2 == iter->end())
543  return true;
544  }
545 
546  LogInfo("Replacer") << "refusing the event as the sum of the visible transverse momenta is too small\n";
547  return false;
548 }
549 
550 void ParticleReplacerClass::cleanEvent(HepMC::GenEvent * evt, HepMC::GenVertex * vtx)
551 {
552  using namespace HepMC;
553  using namespace std;
554  using namespace edm;
555  using namespace reco;
556 
557  stack<HepMC::GenParticle *> deleteParticle;
558 
559  stack<GenVertex *> deleteVertex;
560  stack<GenVertex *> queueVertex;
561 
562  if (vtx->particles_out_size()>0)
563  {
564  for (GenVertex::particles_out_const_iterator it=vtx->particles_out_const_begin();it!=vtx->particles_out_const_end();it++)
565  {
566  deleteParticle.push(*it);
567  if ((*it)->end_vertex())
568  queueVertex.push((*it)->end_vertex());
569  }
570  }
571 
572  while (!queueVertex.empty())
573  {
574  GenVertex * temp_vtx=queueVertex.top();
575  if (temp_vtx->particles_out_size()>0)
576  {
577  for (GenVertex::particles_out_const_iterator it=temp_vtx->particles_out_const_begin();it!=temp_vtx->particles_out_const_end();it++)
578  {
579  if ((*it)->end_vertex())
580  queueVertex.push((*it)->end_vertex());
581  }
582  delete temp_vtx;
583  }
584  deleteVertex.push(queueVertex.top());
585  queueVertex.pop();
586  }
587 
588  while (!deleteVertex.empty())
589  {
590  evt->remove_vertex(deleteVertex.top());
591  deleteVertex.pop();
592  }
593 
594  while (!deleteParticle.empty())
595  {
596  delete vtx->remove_particle(deleteParticle.top());
597  deleteParticle.pop();
598  }
599 
600  while (!deleteVertex.empty())
601  deleteVertex.pop();
602  while (!queueVertex.empty())
603  queueVertex.pop();
604 
605  repairBarcodes(evt);
606 }
607 
608 void ParticleReplacerClass::repairBarcodes(HepMC::GenEvent * evt)
609 {
610  using namespace HepMC;
611 
612  // repair the barcodes
613  int max_barc=0;
614  for (GenEvent::vertex_iterator it=evt->vertices_begin();it!=evt->vertices_end();it++)
615  while (!(*it)->suggest_barcode(-1*(++max_barc)))
616  ;
617 
618  max_barc=0;
619  for (GenEvent::particle_iterator it=evt->particles_begin();it!=evt->particles_end();it++)
620  while (!(*it)->suggest_barcode(++max_barc))
621  ;
622 }
623 
626 {
627  using namespace edm;
628  using namespace reco;
629  using namespace std;
630 
631  reco::Particle::LorentzVector muon1_momentum = muon1->p4();
632  reco::Particle::LorentzVector muon2_momentum = muon2->p4();
633  reco::Particle::LorentzVector z_momentum = muon1_momentum + muon2_momentum;
634 
635  ROOT::Math::Boost booster(z_momentum.BoostToCM());
636  ROOT::Math::Boost invbooster(booster.Inverse());
637 
638  reco::Particle::LorentzVector Zb = booster(z_momentum);
639 
640  reco::Particle::LorentzVector muon1b = booster(muon1_momentum);
641  reco::Particle::LorentzVector muon2b = booster(muon2_momentum);
642 
643  double tau_mass2 = targetParticleMass_*targetParticleMass_;
644 
645  double muonxb_mom2 = muon1b.x()*muon1b.x() + muon1b.y()*muon1b.y() + muon1b.z() * muon1b.z();
646  double tauxb_mom2 = 0.25 * Zb.t() * Zb.t() - tau_mass2;
647 
648  float scaling1 = sqrt(tauxb_mom2 / muonxb_mom2);
649  float scaling2 = scaling1;
650 
651  float tauEnergy= Zb.t() / 2.;
652 
653  if (tauEnergy*tauEnergy<tau_mass2)
654  return;
655 
656  reco::Particle::LorentzVector tau1b_mom = reco::Particle::LorentzVector(scaling1*muon1b.x(),scaling1*muon1b.y(),scaling1*muon1b.z(),tauEnergy);
657  reco::Particle::LorentzVector tau2b_mom = reco::Particle::LorentzVector(scaling2*muon2b.x(),scaling2*muon2b.y(),scaling2*muon2b.z(),tauEnergy);
658 
659  reco::Particle::LorentzVector tau1_mom = (invbooster(tau1b_mom));
660  reco::Particle::LorentzVector tau2_mom = (invbooster(tau2b_mom));
661 
662  // some additional checks
663  // the following tests guarantee a deviation of less
664  // than 0.1% for the following values of the original
665  // muons and the placed taus
666  // invariant mass
667  // transverse momentum
668  assert(std::abs((muon1_momentum+muon2_momentum).mass()-(tau1_mom+tau2_mom).mass())/(muon1_momentum+muon2_momentum).mass()<0.001);
669  assert(std::abs((muon1_momentum+muon2_momentum).pt()-(tau1_mom+tau2_mom).pt())/(muon1_momentum+muon2_momentum).pt()<0.001);
670 
671  muon1->setP4(tau1_mom);
672  muon2->setP4(tau2_mom);
673 
674  muon1->setPdgId(targetParticlePdgID_*muon1->pdgId()/abs(muon1->pdgId()));
675  muon2->setPdgId(targetParticlePdgID_*muon2->pdgId()/abs(muon2->pdgId()));
676 
677  muon1->setStatus(1);
678  muon2->setStatus(1);
679 
680  return;
681 }
684 {
685  using namespace edm;
686  using namespace reco;
687  using namespace std;
688 
689  reco::Particle::LorentzVector muon1_momentum = part1->p4();
690  reco::Particle::LorentzVector muon2_momentum = part2->p4();
691  reco::Particle::LorentzVector z_momentum = muon1_momentum + muon2_momentum;
692 
693  ROOT::Math::Boost booster(z_momentum.BoostToCM());
694  ROOT::Math::Boost invbooster(booster.Inverse());
695 
696  reco::Particle::LorentzVector Zb = booster(z_momentum);
697 
698  const double breitWignerWidth_Z = 2.4952;
699  const double breitWignerWidth_W = 2.141;
700  const double knownMass_W = 80.398;
701  const double knownMass_Z = 91.1876;
702 
703  double Wb_mass = ( Zb.mass() - knownMass_Z ) * ( breitWignerWidth_W / breitWignerWidth_Z ) + knownMass_W;
704  std::cout << "Wb_mass: " << Wb_mass << "\n";
705 
706  reco::Particle::LorentzVector muon1b = booster(muon1_momentum);
707  reco::Particle::LorentzVector muon2b = booster(muon2_momentum);
708 
709  double tau_mass2 = targetParticleMass_*targetParticleMass_;
710 
711  double muonxb_mom2 = muon1b.x()*muon1b.x() + muon1b.y()*muon1b.y() + muon1b.z() * muon1b.z();
712  double tauxb_mom2 = 0.25 * Zb.t() * Zb.t() - tau_mass2;
713 
714  float scaling1 = sqrt(tauxb_mom2 / muonxb_mom2) * Wb_mass/Zb.mass();
715  float scaling2 = scaling1;
716 
717  float tauEnergy= Zb.t() / 2.;
718 
719  if (tauEnergy*tauEnergy<tau_mass2)
720  return;
721 
722  reco::Particle::LorentzVector tau1b_mom = reco::Particle::LorentzVector(scaling1*muon1b.x(),scaling1*muon1b.y(),scaling1*muon1b.z(),tauEnergy* Wb_mass/Zb.mass());
723  reco::Particle::LorentzVector tau2b_mom = reco::Particle::LorentzVector(scaling2*muon2b.x(),scaling2*muon2b.y(),scaling2*muon2b.z(),tauEnergy* Wb_mass/Zb.mass());
724 
725  std::cout << "muon1b_momentum: " << muon1b << "\n";
726  std::cout << "muon2b_momentum: " << muon2b << "\n";
727 
728  std::cout << "tau1b_momentum: " << tau1b_mom << "\n";
729  std::cout << "tau2b_momentum: " << tau2b_mom << "\n";
730 
731  std::cout << "zb_momentum: " << Zb << "\n";
732  std::cout << "wb_momentum: " << (tau1b_mom+tau2b_mom) << "\n";
733 
734  // some checks
735  // the following test guarantees a deviation
736  // of less than 0.1% for phi and theta for the
737  // original muons and the placed taus
738  // (in the centre-of-mass system of the z boson)
739  assert((muon1b.phi()-tau1b_mom.phi())/muon1b.phi()<0.001);
740  assert((muon2b.phi()-tau2b_mom.phi())/muon2b.phi()<0.001);
741  assert((muon1b.theta()-tau1b_mom.theta())/muon1b.theta()<0.001);
742  assert((muon2b.theta()-tau2b_mom.theta())/muon2b.theta()<0.001);
743 
744  reco::Particle::LorentzVector tau1_mom = (invbooster(tau1b_mom));
745  reco::Particle::LorentzVector tau2_mom = (invbooster(tau2b_mom));
746 
747  // some additional checks
748  // the following tests guarantee a deviation of less
749  // than 0.1% for the following values of the original
750  // muons and the placed taus
751  // invariant mass
752  // transverse momentum
753  //assert(((muon1_momentum+muon1_momentum).mass()-(tau1_mom+tau2_mom).mass())/(muon1_momentum+muon1_momentum).mass()<0.001);
754  //assert(((muon1_momentum+muon2_momentum).pt()-(tau1_mom+tau2_mom).pt())/(muon1_momentum+muon1_momentum).pt()<0.001);
755 
756  part1->setP4(tau1_mom);
757  part2->setP4(tau2_mom);
758 
759  part1->setPdgId(15*part1->pdgId()/abs(part1->pdgId()));
760  part2->setPdgId(16*part2->pdgId()/abs(part2->pdgId()));
761 
762  part1->setStatus(1);
763  part2->setStatus(1);
764 
765  return;
766 }
767 
768 
769 //define this as a plug-in
770 //DEFINE_FWK_MODULE(Replacer);
type
Definition: HCALResponse.h:22
T getParameter(std::string const &) const
T getUntrackedParameter(std::string const &, T const &) const
int i
Definition: DBlmapReader.cc:9
virtual int pdgId() const
PDG identifier.
void repairBarcodes(HepMC::GenEvent *evt)
virtual void SetDecayRandomEngine(CLHEP::HepRandomEngine *decayRandomEngine)
void setP4(const LorentzVector &p4)
set 4-momentum
Definition: Particle.h:105
CLHEP::HepRandomEngine * decayRandomEngine
virtual void init(const edm::EventSetup &)
static HepMC::IO_HEPEVT conv
virtual const Point & vertex() const
vertex position
ParticleReplacerClass(const edm::ParameterSet &, bool)
bool testEvent(HepMC::GenEvent *evt)
#define abs(x)
Definition: mlp_lapack.h:159
#define NULL
Definition: scimark2.h:8
unsigned int replacementMode_
replace mode:
const LorentzVector & p4() const
four-momentum Lorentz vector
Definition: Particle.h:64
uint16_t size_type
int pdgId() const
PDG identifier.
Definition: Particle.h:150
std::vector< Muon > MuonCollection
collection of Muon objects
Definition: MuonFwd.h:9
PtEtaPhiMLorentzVectorD PtEtaPhiMLorentzVector
Lorentz vector with cartesian internal representation.
Definition: LorentzVector.h:26
gen::TauolaInterfaceBase * tauola_
T sqrt(T t)
Definition: SSEVec.h:46
enum ParticleReplacerClass::MinVisPtCut::@638 type_
virtual int charge() const
electric charge
math::XYZPoint Point
point in the space
Definition: Particle.h:29
#define TXGIVE
#define TXGIVE_INIT
virtual double px() const
x coordinate of momentum vector
void setPdgId(int pdgId)
Definition: Particle.h:152
virtual HepMC::GenEvent * decay(HepMC::GenEvent *evt)
virtual double pz() const
z coordinate of momentum vector
math::XYZTLorentzVector LorentzVector
Lorentz vector.
Definition: Candidate.h:38
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 mass
Definition: scaleCards.py:27
virtual void beginRun(edm::Run &iRun, const edm::EventSetup &iSetup)
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
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)
virtual const LorentzVector & p4() const
four-momentum Lorentz vector
math::XYZTLorentzVector LorentzVector
Lorentz vector.
Definition: Particle.h:25
void setStatus(int status)
set status word
Definition: Particle.h:156
virtual double py() const
y coordinate of momentum vector
std::vector< std::vector< MinVisPtCut > > minVisPtCuts_
T get(const Candidate &c)
Definition: component.h:56
Definition: Run.h:33