00001 #include "TauAnalysis/MCEmbeddingTools/interface/ParticleReplacerClass.h"
00002
00003 #include "GeneratorInterface/ExternalDecays/interface/DecayRandomEngine.h"
00004 #include "FWCore/Utilities/interface/RandomNumberGenerator.h"
00005 #include "FWCore/Utilities/interface/Exception.h"
00006
00007 #include "HepMC/IO_HEPEVT.h"
00008
00009 #ifndef TXGIVE
00010 #define TXGIVE txgive_
00011 extern "C" {
00012 void TXGIVE(const char*,int length);
00013 }
00014 #endif
00015
00016 #ifndef TXGIVE_INIT
00017 #define TXGIVE_INIT txgive_init_
00018 extern "C" {
00019 void TXGIVE_INIT();
00020 }
00021 #endif
00022
00023 ParticleReplacerClass::ParticleReplacerClass(const edm::ParameterSet& pset, bool verbose):
00024 ParticleReplacerBase(pset),
00025 generatorMode_(pset.getParameter<std::string>("generatorMode")),
00026 tauola_(gen::TauolaInterface::getInstance()),
00027 printEvent_(verbose),
00028 outTree(0),
00029 maxNumberOfAttempts_(pset.getUntrackedParameter<int>("maxNumberOfAttempts", 1000))
00030 {
00031 tauola_->setPSet(pset.getParameter< edm::ParameterSet>("TauolaOptions"));
00032
00033 using namespace edm;
00034 using namespace std;
00035
00036
00037
00038
00039
00040
00041
00042 transformationMode_ = pset.getUntrackedParameter<int>("transformationMode",1);
00043 switch (transformationMode_)
00044 {
00045 case 0:
00046 {
00047 LogInfo("Replacer") << "won't do any transformation with the given mumu";
00048 break;
00049 }
00050 case 1:
00051 {
00052 LogInfo("Replacer") << "will transform mumu into tautau";
00053 break;
00054 }
00055 case 2:
00056 {
00057 LogInfo("Replacer") << "will transform mumu into taunu (as coming from a W boson)";
00058 break;
00059 }
00060 case 3:
00061 {
00062 LogInfo("Replacer") << "Will transform mu-nu into tau-nu. No mass correction will be made.";
00063 break;
00064 }
00065 default:
00066 {
00067 throw cms::Exception("ParticleReplacerClass") << "Unknown transformation mode!\n";
00068 break;
00069 }
00070
00071 }
00072
00073
00074
00075
00076
00077
00078 noInitialisation_ = pset.getUntrackedParameter<bool>("noInitialisation",false);
00079
00080 motherParticleID_ = pset.getUntrackedParameter<int>("motherParticleID",23);
00081
00082
00083 std::string minVisibleTransverseMomentumLine = pset.getUntrackedParameter<std::string>("minVisibleTransverseMomentum","");
00084
00085
00086 const char* startptr = minVisibleTransverseMomentumLine.c_str();
00087 char* endptr;
00088 double d = strtod(startptr, &endptr);
00089 if(*endptr == '\0' && endptr != startptr)
00090 {
00091 MinVisPtCut cuts[2];
00092 cuts[0].type_ = cuts[1].type_ = MinVisPtCut::TAU;
00093 cuts[0].pt_ = cuts[1].pt_ = d;
00094 cuts[0].index_ = 0; cuts[1].index_ = 1;
00095 minVisPtCuts_.push_back(std::vector<MinVisPtCut>(cuts, cuts+2));
00096 }
00097 else
00098 {
00099
00100 for(std::string::size_type prev = 0, pos = 0; prev < minVisibleTransverseMomentumLine.length(); prev = pos + 1)
00101 {
00102 pos = minVisibleTransverseMomentumLine.find(';', prev);
00103 if(pos == std::string::npos) pos = minVisibleTransverseMomentumLine.length();
00104
00105 std::string sub = minVisibleTransverseMomentumLine.substr(prev, pos - prev);
00106 std::vector<MinVisPtCut> cuts;
00107 const char* sub_c = sub.c_str();
00108 while(*sub_c != '\0')
00109 {
00110 const char* sep = std::strchr(sub_c, '_');
00111 if(sep == NULL) throw cms::Exception("Configuration") << "Minimum transverse parameter string must contain an underscore to separate type from pt threshold" << std::endl;
00112 std::string type(sub_c, sep);
00113
00114 MinVisPtCut cut;
00115 if(type == "elec1") { cut.type_ = MinVisPtCut::ELEC; cut.index_ = 0; }
00116 else if(type == "mu1") { cut.type_ = MinVisPtCut::MU; cut.index_ = 0; }
00117 else if(type == "had1") { cut.type_ = MinVisPtCut::HAD; cut.index_ = 0; }
00118 else if(type == "tau1") { cut.type_ = MinVisPtCut::TAU; cut.index_ = 0; }
00119 else if(type == "elec2") { cut.type_ = MinVisPtCut::ELEC; cut.index_ = 1; }
00120 else if(type == "mu2") { cut.type_ = MinVisPtCut::MU; cut.index_ = 1; }
00121 else if(type == "had2") { cut.type_ = MinVisPtCut::HAD; cut.index_ = 1; }
00122 else if(type == "tau2") { cut.type_ = MinVisPtCut::TAU; cut.index_ = 1; }
00123 else throw cms::Exception("Configuration") << "'" << type << "' is not a valid type. Allowed values are elec1,mu1,had1,tau1,elec2,mu2,had2,tau2" << std::endl;
00124
00125 char* endptr;
00126 cut.pt_ = strtod(sep + 1, &endptr);
00127 if(endptr == sep + 1) throw cms::Exception("Configuration") << "No pt threshold given" << std::endl;
00128
00129 cuts.push_back(cut);
00130 sub_c = endptr;
00131 }
00132 minVisPtCuts_.push_back(cuts);
00133 }
00134 }
00135
00136 edm::Service<TFileService> fileService_;
00137 if(fileService_.isAvailable()) {
00138 outTree = fileService_->make<TTree>( "event_generation","This tree stores information about the event generation");
00139 outTree->Branch("attempts",&attempts,"attempts/I");
00140 }
00141
00142 edm::Service<RandomNumberGenerator> rng;
00143 if(!rng.isAvailable()) {
00144 throw cms::Exception("Configuration")
00145 << "The RandomNumberProducer module requires the RandomNumberGeneratorService\n"
00146 "which appears to be absent. Please add that service to your configuration\n"
00147 "or remove the modules that require it." << std::endl;
00148 }
00149
00150 decayRandomEngine = &rng->getEngine();
00151
00152 edm::LogInfo("Replacer") << "generatorMode = "<< generatorMode_<< "\n";
00153
00154 return;
00155 }
00156
00157 ParticleReplacerClass::~ParticleReplacerClass()
00158 {
00159
00160
00161 }
00162
00163
00164 std::auto_ptr<HepMC::GenEvent> ParticleReplacerClass::produce(const reco::MuonCollection& muons, const reco::Vertex *pvtx, const HepMC::GenEvent *genEvt)
00165 {
00166 using namespace edm;
00167 using namespace std;
00168 using namespace HepMC;
00169
00170 if(pvtx != 0)
00171 throw cms::Exception("Configuration") << "ParticleReplacerClass does NOT support using primary vertex as the origin for taus" << std::endl;
00172
00173 HepMC::GenEvent * evt=0;
00174
00175 GenVertex * zvtx = new GenVertex();
00176
00177 reco::GenParticle * part1=0;
00178 reco::GenParticle * part2=0;
00179
00181 std::vector<reco::Particle> particles;
00182 switch (transformationMode_)
00183 {
00184 case 0:
00185 {
00186 if (muons.size()!=2)
00187 {
00188 LogError("Replacer") << "the decay mode Z->mumu requires exactly two muons, aborting processing";
00189 return std::auto_ptr<HepMC::GenEvent>(0);
00190 }
00191
00192 targetParticleMass_ = 0.105658369;
00193 targetParticlePdgID_ = 13;
00194
00195 reco::Muon muon1 = muons.at(0);
00196 reco::Muon muon2 = muons.at(1);
00197 reco::Particle tau1(muon1.charge(), muon1.p4(), muon1.vertex(), muon1.pdgId(), 0, true);
00198 reco::Particle tau2(muon2.charge(), muon2.p4(), muon2.vertex(), muon2.pdgId(), 0, true);
00199 particles.push_back(tau1);
00200 particles.push_back(tau2);
00201 break;
00202 }
00203 case 1:
00204 {
00205 if (muons.size()!=2)
00206 {
00207 LogError("Replacer") << "the decay mode Z->tautau requires exactly two muons, aborting processing";
00208 return std::auto_ptr<HepMC::GenEvent>(0);
00209 }
00210
00211 targetParticleMass_ = 1.77690;
00212 targetParticlePdgID_ = 15;
00213
00214 reco::Muon muon1 = muons.at(0);
00215 reco::Muon muon2 = muons.at(1);
00216 reco::Particle tau1(muon1.charge(), muon1.p4(), muon1.vertex(), muon1.pdgId(), 0, true);
00217 reco::Particle tau2(muon2.charge(), muon2.p4(), muon2.vertex(), muon2.pdgId(), 0, true);
00218 transformMuMu2TauTau(&tau1, &tau2);
00219 particles.push_back(tau1);
00220 particles.push_back(tau2);
00221 break;
00222 }
00223 case 2:
00224 {
00225 if (muons.size()!=2)
00226 {
00227 LogError("Replacer") << "the decay mode Z->tautau requires exactly two muons, aborting processing";
00228 return std::auto_ptr<HepMC::GenEvent>(0);
00229 }
00230
00231 targetParticleMass_ = 1.77690;
00232 targetParticlePdgID_ = 15;
00233
00234 reco::Muon muon1 = muons.at(0);
00235 reco::Muon muon2 = muons.at(1);
00236 reco::Particle tau1(muon1.charge(), muon1.p4(), muon1.vertex(), muon1.pdgId(), 0, true);
00237 reco::Particle tau2(muon2.charge(), muon2.p4(), muon2.vertex(), muon2.pdgId(), 0, true);
00238 transformMuMu2TauNu(&tau1, &tau2);
00239 particles.push_back(tau1);
00240 particles.push_back(tau2);
00241 break;
00242 }
00243 case 3:
00244 {
00245 if (muons.size()!=2)
00246 {
00247 LogError("Replacer") << "transformation mode mu-nu ->tau-nu - wrong input";
00248 return std::auto_ptr<HepMC::GenEvent>(0);
00249 }
00250
00251 targetParticleMass_ = 1.77690;
00252 targetParticlePdgID_ = 15;
00253 int targetParticlePdgIDNu_ = 16;
00254
00255 reco::Muon muon1 = muons.at(0);
00256 reco::Muon::LorentzVector l(muon1.px(), muon1.py(), muon1.pz(),
00257 sqrt(
00258 muon1.px()*muon1.px()+
00259 muon1.py()*muon1.py()+
00260 muon1.pz()*muon1.pz()+targetParticleMass_*targetParticleMass_));
00261
00262 reco::Particle tau1(muon1.charge(), l, muon1.vertex(), targetParticlePdgID_*std::abs(muon1.pdgId())/muon1.pdgId()
00263 , 0, true
00264 );
00265 tau1.setStatus(1);
00266 particles.push_back(tau1);
00267
00268 reco::Muon nu = muons.at(1);
00269 reco::Particle nutau( 0, nu.p4(), nu.vertex(), -targetParticlePdgIDNu_*std::abs(muon1.pdgId())/muon1.pdgId(), 0, true);
00270 nutau.setStatus(1);
00271 particles.push_back(nutau);
00272
00273 break;
00274 }
00275
00276 }
00277
00278 if (particles.size()==0)
00279 {
00280 LogError("Replacer") << "the creation of the new particles failed somehow";
00281 return std::auto_ptr<HepMC::GenEvent>(0);
00282 }
00283 else
00284 {
00285 LogInfo("Replacer") << particles.size() << " particles found, continue processing";
00286 }
00287
00289 if (genEvt)
00290 {
00291
00292 evt = new HepMC::GenEvent(*genEvt);
00293
00294 for ( GenEvent::vertex_iterator p = evt->vertices_begin(); p != evt->vertices_end(); p++ )
00295 {
00296 GenVertex * vtx=(*p);
00297
00298 if ( vtx->particles_out_size()<=0 || vtx->particles_in_size()<=0)
00299 continue;
00300
00301 bool temp_muon1=false,temp_muon2=false,temp_z=false;
00302 for (GenVertex::particles_out_const_iterator it = vtx->particles_out_const_begin(); it!=vtx->particles_out_const_end(); it++)
00303 {
00304 if ((*it)->pdg_id()==13) temp_muon1=true;
00305 if ((*it)->pdg_id()==-13) temp_muon2=true;
00306 if ((*it)->pdg_id()==23) temp_z=true;
00307 }
00308
00309 int mother_pdg=(*vtx->particles_in_const_begin())->pdg_id();
00310
00311 if ((vtx->particles_out_size()==2 && vtx->particles_in_size()>0
00312 && mother_pdg == 23
00313 && temp_muon1
00314 && temp_muon2)
00315 || (vtx->particles_out_size()>2 && vtx->particles_in_size()>0
00316 && mother_pdg == 23
00317 && temp_muon1 && temp_muon2 && temp_z ))
00318 {
00319 zvtx=*p;
00320 }
00321 }
00322
00323 cleanEvent(evt, zvtx);
00324
00325
00326
00327 for (GenEvent::particle_iterator it=evt->particles_begin();it!=evt->particles_end();it++)
00328 (*it)->set_status(0);
00329
00330 for (std::vector<reco::Particle>::const_iterator it=particles.begin();it!=particles.end();it++)
00331 {
00332 zvtx->add_particle_out(new HepMC::GenParticle((FourVector)it->p4(), it->pdgId(), 1, Flow(), Polarization(0,0)));
00333 }
00334 }
00335
00336 else
00337 {
00338 reco::Particle::LorentzVector mother_particle_p4;
00339 for (std::vector<reco::Particle>::const_iterator it=particles.begin();it!=particles.end();it++)
00340 mother_particle_p4+=it->p4();
00341
00342 reco::Particle::Point production_point = particles.begin()->vertex();
00343
00344 GenVertex* startVtx = new GenVertex(FourVector(production_point.x()*10,production_point.y()*10,production_point.z()*10,0));
00345 startVtx->add_particle_in( new GenParticle( FourVector(0,0,7000,7000), 2212, 3 ) );
00346 startVtx->add_particle_in( new GenParticle( FourVector(0,0,-7000,7000), 2212, 3 ) );
00347
00348 GenVertex * decayvtx = new GenVertex(FourVector(production_point.x()*10,production_point.y()*10,production_point.z()*10,0));
00349 HepMC::GenParticle * mother_particle = new HepMC::GenParticle((FourVector)mother_particle_p4, motherParticleID_, (generatorMode_=="Pythia" ? 3 : 2), Flow(), Polarization(0,0));
00350 if (transformationMode_ == 3) {
00351
00352 int muPDG = particles.begin()->pdgId();
00353 int id = -24*muPDG/std::abs(muPDG);
00354 mother_particle->set_pdg_id(id);
00355 }
00356
00357 startVtx->add_particle_out(mother_particle);
00358 decayvtx->add_particle_in(mother_particle);
00359 evt = new HepMC::GenEvent();
00360 for (std::vector<reco::Particle>::const_iterator it=particles.begin();it!=particles.end();it++)
00361 {
00362
00363 decayvtx->add_particle_out(new HepMC::GenParticle((FourVector)it->p4(), it->pdgId(), 1, Flow(), Polarization(0,0)));
00364 }
00365
00366 evt->add_vertex(startVtx);
00367 evt->add_vertex(decayvtx);
00368 }
00369 repairBarcodes(evt);
00370
00371 HepMC::GenEvent * retevt = 0;
00372 HepMC::GenEvent * tempevt = 0;
00373
00375 int nr_of_trials=0;
00376
00377 unsigned int cntVisPt_all = 0;
00378 unsigned int cntVisPt_pass = 0;
00379
00380 HepMC::IO_HEPEVT conv;
00381 for (int i = 0; i<maxNumberOfAttempts_; i++)
00382 {
00383 ++cntVisPt_all;
00384 if (generatorMode_ == "Pythia")
00385 {
00386 LogError("Replacer") << "Pythia is currently not supported!";
00387 return std::auto_ptr<HepMC::GenEvent>(evt);
00388 }
00389
00390 if (generatorMode_ == "Tauola")
00391 {
00392 conv.write_event(evt);
00393 tempevt=tauola_->decay(evt);
00394 }
00395
00396 if (testEvent(tempevt))
00397 {
00398 if (retevt==0) {
00399 retevt=tempevt;
00400 } else {
00401 delete tempevt;
00402 }
00403 ++cntVisPt_pass;
00404 } else {
00405 delete tempevt;
00406 }
00407 }
00408
00409 tried = cntVisPt_all;
00410 passed = cntVisPt_pass;
00411
00412 std::cout << " " << cntVisPt_pass << "\t" << cntVisPt_all << "\n";
00413 if (!retevt)
00414 {
00415 LogError("Replacer") << "failed to create an event which satisfies the minimum visible transverse momentum cuts ";
00416 attempts=-1;
00417 if(outTree) outTree->Fill();
00418 return std::auto_ptr<HepMC::GenEvent>(0);
00419 }
00420 attempts=nr_of_trials;
00421 if(outTree) outTree->Fill();
00422
00423
00424 if (genEvt)
00425 {
00426 for (GenEvent::particle_iterator it=retevt->particles_begin();it!=retevt->particles_end();it++)
00427 {
00428 if ((*it)->end_vertex())
00429 (*it)->set_status(2);
00430 else
00431 (*it)->set_status(1);
00432 }
00433 }
00434
00435 std::auto_ptr<HepMC::GenEvent> ret(retevt);
00436
00437 if (printEvent_)
00438 retevt->print(std::cout);
00439
00440 delete part1;
00441 delete part2;
00442 delete zvtx;
00443 delete evt;
00444 return ret;
00445 }
00446
00447
00448 void ParticleReplacerClass::beginRun(edm::Run& iRun,const edm::EventSetup& iSetup)
00449 {
00450 tauola_->init(iSetup);
00451 }
00452
00453
00454 void
00455 ParticleReplacerClass::endJob()
00456 {
00457 tauola_->statistics();
00458 }
00459
00460 bool ParticleReplacerClass::testEvent(HepMC::GenEvent * evt)
00461 {
00462 using namespace HepMC;
00463 using namespace edm;
00464
00465 if (minVisPtCuts_.empty())
00466 return true;
00467
00468 std::vector<double> mus;
00469 std::vector<double> elecs;
00470 std::vector<double> hads;
00471 std::vector<double> taus;
00472
00473 for (GenEvent::particle_iterator it=evt->particles_begin();it!=evt->particles_end();it++)
00474 {
00475 if (abs((*it)->pdg_id())==15 && (*it)->end_vertex())
00476 {
00477 FourVector vis_mom();
00478 math::PtEtaPhiMLorentzVector visible_momentum;
00479 std::queue<const GenParticle *> decaying_particles;
00480 decaying_particles.push(*it);
00481 int t=0;
00482 enum { ELEC, MU, HAD } type = HAD;
00483 while(!decaying_particles.empty() && (++t < 30))
00484 {
00485 const GenParticle * front = decaying_particles.front();
00486 decaying_particles.pop();
00487
00488 if (!front->end_vertex())
00489 {
00490 int pdgId=abs(front->pdg_id());
00491 if (pdgId>10 && pdgId!=12 && pdgId!=14 && pdgId!=16)
00492 visible_momentum+=(math::PtEtaPhiMLorentzVector)front->momentum();
00493
00494 if(pdgId == 11) type = ELEC;
00495 if(pdgId == 13) type = MU;
00496 }
00497 else
00498 {
00499 GenVertex * temp_vert = front->end_vertex();
00500 for (GenVertex::particles_out_const_iterator it2=temp_vert->particles_out_const_begin();it2!=temp_vert->particles_out_const_end();it2++)
00501 decaying_particles.push((*it2));
00502 }
00503 }
00504
00505 double vis_pt = visible_momentum.pt();
00506 taus.push_back(vis_pt);
00507 if(type == MU) mus.push_back(vis_pt);
00508 if(type == ELEC) elecs.push_back(vis_pt);
00509 if(type == HAD) hads.push_back(vis_pt);
00510 }
00511 }
00512
00513 std::sort(taus.begin(), taus.end(), std::greater<double>());
00514 std::sort(elecs.begin(), elecs.end(), std::greater<double>());
00515 std::sort(mus.begin(), mus.end(), std::greater<double>());
00516 std::sort(hads.begin(), hads.end(), std::greater<double>());
00517
00518 for(std::vector<std::vector<MinVisPtCut> >::const_iterator iter = minVisPtCuts_.begin(); iter != minVisPtCuts_.end(); ++iter)
00519 {
00520 std::vector<MinVisPtCut>::const_iterator iter2;
00521 for(iter2 = iter->begin(); iter2 != iter->end(); ++iter2)
00522 {
00523 std::vector<double>* collection;
00524 switch(iter2->type_)
00525 {
00526 case MinVisPtCut::ELEC: collection = &elecs; break;
00527 case MinVisPtCut::MU: collection = &mus; break;
00528 case MinVisPtCut::HAD: collection = &hads; break;
00529 case MinVisPtCut::TAU: collection = &taus; break;
00530 default: assert(false); break;
00531 }
00532
00533
00534 if(iter2->index_ >= collection->size() || (*collection)[iter2->index_] < iter2->pt_)
00535 break;
00536 }
00537
00538
00539 if(iter2 == iter->end())
00540 return true;
00541 }
00542
00543 LogInfo("Replacer") << "refusing the event as the sum of the visible transverse momenta is too small\n";
00544 return false;
00545 }
00546
00547 void ParticleReplacerClass::cleanEvent(HepMC::GenEvent * evt, HepMC::GenVertex * vtx)
00548 {
00549 using namespace HepMC;
00550 using namespace std;
00551 using namespace edm;
00552 using namespace reco;
00553
00554 stack<HepMC::GenParticle *> deleteParticle;
00555
00556 stack<GenVertex *> deleteVertex;
00557 stack<GenVertex *> queueVertex;
00558
00559 if (vtx->particles_out_size()>0)
00560 {
00561 for (GenVertex::particles_out_const_iterator it=vtx->particles_out_const_begin();it!=vtx->particles_out_const_end();it++)
00562 {
00563 deleteParticle.push(*it);
00564 if ((*it)->end_vertex())
00565 queueVertex.push((*it)->end_vertex());
00566 }
00567 }
00568
00569 while (!queueVertex.empty())
00570 {
00571 GenVertex * temp_vtx=queueVertex.top();
00572 if (temp_vtx->particles_out_size()>0)
00573 {
00574 for (GenVertex::particles_out_const_iterator it=temp_vtx->particles_out_const_begin();it!=temp_vtx->particles_out_const_end();it++)
00575 {
00576 if ((*it)->end_vertex())
00577 queueVertex.push((*it)->end_vertex());
00578 }
00579 delete temp_vtx;
00580 }
00581 deleteVertex.push(queueVertex.top());
00582 queueVertex.pop();
00583 }
00584
00585 while (!deleteVertex.empty())
00586 {
00587 evt->remove_vertex(deleteVertex.top());
00588 deleteVertex.pop();
00589 }
00590
00591 while (!deleteParticle.empty())
00592 {
00593 delete vtx->remove_particle(deleteParticle.top());
00594 deleteParticle.pop();
00595 }
00596
00597 while (!deleteVertex.empty())
00598 deleteVertex.pop();
00599 while (!queueVertex.empty())
00600 queueVertex.pop();
00601
00602 repairBarcodes(evt);
00603 }
00604
00605 void ParticleReplacerClass::repairBarcodes(HepMC::GenEvent * evt)
00606 {
00607 using namespace HepMC;
00608
00609
00610 int max_barc=0;
00611 for (GenEvent::vertex_iterator it=evt->vertices_begin(), next;it!=evt->vertices_end();it=next)
00612 {
00613 next=it;++next;
00614 while (!(*it)->suggest_barcode(-1*(++max_barc)))
00615 ;
00616 }
00617
00618 max_barc=0;
00619 for (GenEvent::particle_iterator it=evt->particles_begin(), next;it!=evt->particles_end();it=next)
00620 {
00621 next=it;++next;
00622 while (!(*it)->suggest_barcode(++max_barc))
00623 ;
00624 }
00625 }
00626
00628 void ParticleReplacerClass::transformMuMu2TauTau(reco::Particle * muon1, reco::Particle * muon2)
00629 {
00630 using namespace edm;
00631 using namespace reco;
00632 using namespace std;
00633
00634 reco::Particle::LorentzVector muon1_momentum = muon1->p4();
00635 reco::Particle::LorentzVector muon2_momentum = muon2->p4();
00636 reco::Particle::LorentzVector z_momentum = muon1_momentum + muon2_momentum;
00637
00638 ROOT::Math::Boost booster(z_momentum.BoostToCM());
00639 ROOT::Math::Boost invbooster(booster.Inverse());
00640
00641 reco::Particle::LorentzVector Zb = booster(z_momentum);
00642
00643 reco::Particle::LorentzVector muon1b = booster(muon1_momentum);
00644 reco::Particle::LorentzVector muon2b = booster(muon2_momentum);
00645
00646 double tau_mass2 = targetParticleMass_*targetParticleMass_;
00647
00648 double muonxb_mom2 = muon1b.x()*muon1b.x() + muon1b.y()*muon1b.y() + muon1b.z() * muon1b.z();
00649 double tauxb_mom2 = 0.25 * Zb.t() * Zb.t() - tau_mass2;
00650
00651 float scaling1 = sqrt(tauxb_mom2 / muonxb_mom2);
00652 float scaling2 = scaling1;
00653
00654 float tauEnergy= Zb.t() / 2.;
00655
00656 if (tauEnergy*tauEnergy<tau_mass2)
00657 return;
00658
00659 reco::Particle::LorentzVector tau1b_mom = reco::Particle::LorentzVector(scaling1*muon1b.x(),scaling1*muon1b.y(),scaling1*muon1b.z(),tauEnergy);
00660 reco::Particle::LorentzVector tau2b_mom = reco::Particle::LorentzVector(scaling2*muon2b.x(),scaling2*muon2b.y(),scaling2*muon2b.z(),tauEnergy);
00661
00662 reco::Particle::LorentzVector tau1_mom = (invbooster(tau1b_mom));
00663 reco::Particle::LorentzVector tau2_mom = (invbooster(tau2b_mom));
00664
00665
00666
00667
00668
00669
00670
00671 assert(std::abs((muon1_momentum+muon2_momentum).mass()-(tau1_mom+tau2_mom).mass())/(muon1_momentum+muon2_momentum).mass()<0.001);
00672 assert(std::abs((muon1_momentum+muon2_momentum).pt()-(tau1_mom+tau2_mom).pt())/(muon1_momentum+muon2_momentum).pt()<0.001);
00673
00674 muon1->setP4(tau1_mom);
00675 muon2->setP4(tau2_mom);
00676
00677 muon1->setPdgId(targetParticlePdgID_*muon1->pdgId()/abs(muon1->pdgId()));
00678 muon2->setPdgId(targetParticlePdgID_*muon2->pdgId()/abs(muon2->pdgId()));
00679
00680 muon1->setStatus(1);
00681 muon2->setStatus(1);
00682
00683 return;
00684 }
00686 void ParticleReplacerClass::transformMuMu2TauNu(reco::Particle * part1, reco::Particle * part2)
00687 {
00688 using namespace edm;
00689 using namespace reco;
00690 using namespace std;
00691
00692 reco::Particle::LorentzVector muon1_momentum = part1->p4();
00693 reco::Particle::LorentzVector muon2_momentum = part2->p4();
00694 reco::Particle::LorentzVector z_momentum = muon1_momentum + muon2_momentum;
00695
00696 ROOT::Math::Boost booster(z_momentum.BoostToCM());
00697 ROOT::Math::Boost invbooster(booster.Inverse());
00698
00699 reco::Particle::LorentzVector Zb = booster(z_momentum);
00700
00701 const double breitWignerWidth_Z = 2.4952;
00702 const double breitWignerWidth_W = 2.141;
00703 const double knownMass_W = 80.398;
00704 const double knownMass_Z = 91.1876;
00705
00706 double Wb_mass = ( Zb.mass() - knownMass_Z ) * ( breitWignerWidth_W / breitWignerWidth_Z ) + knownMass_W;
00707 std::cout << "Wb_mass: " << Wb_mass << "\n";
00708
00709 reco::Particle::LorentzVector muon1b = booster(muon1_momentum);
00710 reco::Particle::LorentzVector muon2b = booster(muon2_momentum);
00711
00712 double tau_mass2 = targetParticleMass_*targetParticleMass_;
00713
00714 double muonxb_mom2 = muon1b.x()*muon1b.x() + muon1b.y()*muon1b.y() + muon1b.z() * muon1b.z();
00715 double tauxb_mom2 = 0.25 * Zb.t() * Zb.t() - tau_mass2;
00716
00717 float scaling1 = sqrt(tauxb_mom2 / muonxb_mom2) * Wb_mass/Zb.mass();
00718 float scaling2 = scaling1;
00719
00720 float tauEnergy= Zb.t() / 2.;
00721
00722 if (tauEnergy*tauEnergy<tau_mass2)
00723 return;
00724
00725 reco::Particle::LorentzVector tau1b_mom = reco::Particle::LorentzVector(scaling1*muon1b.x(),scaling1*muon1b.y(),scaling1*muon1b.z(),tauEnergy* Wb_mass/Zb.mass());
00726 reco::Particle::LorentzVector tau2b_mom = reco::Particle::LorentzVector(scaling2*muon2b.x(),scaling2*muon2b.y(),scaling2*muon2b.z(),tauEnergy* Wb_mass/Zb.mass());
00727
00728 std::cout << "muon1b_momentum: " << muon1b << "\n";
00729 std::cout << "muon2b_momentum: " << muon2b << "\n";
00730
00731 std::cout << "tau1b_momentum: " << tau1b_mom << "\n";
00732 std::cout << "tau2b_momentum: " << tau2b_mom << "\n";
00733
00734 std::cout << "zb_momentum: " << Zb << "\n";
00735 std::cout << "wb_momentum: " << (tau1b_mom+tau2b_mom) << "\n";
00736
00737
00738
00739
00740
00741
00742 assert((muon1b.phi()-tau1b_mom.phi())/muon1b.phi()<0.001);
00743 assert((muon2b.phi()-tau2b_mom.phi())/muon2b.phi()<0.001);
00744 assert((muon1b.theta()-tau1b_mom.theta())/muon1b.theta()<0.001);
00745 assert((muon2b.theta()-tau2b_mom.theta())/muon2b.theta()<0.001);
00746
00747 reco::Particle::LorentzVector tau1_mom = (invbooster(tau1b_mom));
00748 reco::Particle::LorentzVector tau2_mom = (invbooster(tau2b_mom));
00749
00750
00751
00752
00753
00754
00755
00756
00757
00758
00759 part1->setP4(tau1_mom);
00760 part2->setP4(tau2_mom);
00761
00762 part1->setPdgId(15*part1->pdgId()/abs(part1->pdgId()));
00763 part2->setPdgId(16*part2->pdgId()/abs(part2->pdgId()));
00764
00765 part1->setStatus(1);
00766 part2->setStatus(1);
00767
00768 return;
00769 }
00770
00771
00772
00773