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_(pset.getParameter< edm::ParameterSet>("TauolaOptions")),
00027
00028 printEvent_(verbose),
00029 outTree(0),
00030 maxNumberOfAttempts_(pset.getUntrackedParameter<int>("maxNumberOfAttempts", 1000))
00031 {
00032
00033
00034 using namespace edm;
00035 using namespace std;
00036
00037
00038
00039
00040
00041
00042
00043 transformationMode_ = pset.getUntrackedParameter<int>("transformationMode",1);
00044 switch (transformationMode_)
00045 {
00046 case 0:
00047 {
00048 LogInfo("Replacer") << "won't do any transformation with the given mumu";
00049 break;
00050 }
00051 case 1:
00052 {
00053 LogInfo("Replacer") << "will transform mumu into tautau";
00054 break;
00055 }
00056 case 2:
00057 {
00058 LogInfo("Replacer") << "will transform mumu into taunu (as coming from a W boson)";
00059 break;
00060 }
00061 case 3:
00062 {
00063 LogInfo("Replacer") << "Will transform mu-nu into tau-nu. No mass correction will be made.";
00064 break;
00065 }
00066 default:
00067 {
00068 throw cms::Exception("ParticleReplacerClass") << "Unknown transformation mode!\n";
00069 break;
00070 }
00071
00072 }
00073
00074
00075
00076
00077
00078
00079 noInitialisation_ = pset.getUntrackedParameter<bool>("noInitialisation",false);
00080
00081 motherParticleID_ = pset.getUntrackedParameter<int>("motherParticleID",23);
00082
00083
00084 std::string minVisibleTransverseMomentumLine = pset.getUntrackedParameter<std::string>("minVisibleTransverseMomentum","");
00085
00086
00087 const char* startptr = minVisibleTransverseMomentumLine.c_str();
00088 char* endptr;
00089 double d = strtod(startptr, &endptr);
00090 if(*endptr == '\0' && endptr != startptr)
00091 {
00092 MinVisPtCut cuts[2];
00093 cuts[0].type_ = cuts[1].type_ = MinVisPtCut::TAU;
00094 cuts[0].pt_ = cuts[1].pt_ = d;
00095 cuts[0].index_ = 0; cuts[1].index_ = 1;
00096 minVisPtCuts_.push_back(std::vector<MinVisPtCut>(cuts, cuts+2));
00097 }
00098 else
00099 {
00100
00101 for(std::string::size_type prev = 0, pos = 0; prev < minVisibleTransverseMomentumLine.length(); prev = pos + 1)
00102 {
00103 pos = minVisibleTransverseMomentumLine.find(';', prev);
00104 if(pos == std::string::npos) pos = minVisibleTransverseMomentumLine.length();
00105
00106 std::string sub = minVisibleTransverseMomentumLine.substr(prev, pos - prev);
00107 std::vector<MinVisPtCut> cuts;
00108 const char* sub_c = sub.c_str();
00109 while(*sub_c != '\0')
00110 {
00111 const char* sep = std::strchr(sub_c, '_');
00112 if(sep == NULL) throw cms::Exception("Configuration") << "Minimum transverse parameter string must contain an underscore to separate type from pt threshold" << std::endl;
00113 std::string type(sub_c, sep);
00114
00115 MinVisPtCut cut;
00116 if(type == "elec1") { cut.type_ = MinVisPtCut::ELEC; cut.index_ = 0; }
00117 else if(type == "mu1") { cut.type_ = MinVisPtCut::MU; cut.index_ = 0; }
00118 else if(type == "had1") { cut.type_ = MinVisPtCut::HAD; cut.index_ = 0; }
00119 else if(type == "tau1") { cut.type_ = MinVisPtCut::TAU; cut.index_ = 0; }
00120 else if(type == "elec2") { cut.type_ = MinVisPtCut::ELEC; cut.index_ = 1; }
00121 else if(type == "mu2") { cut.type_ = MinVisPtCut::MU; cut.index_ = 1; }
00122 else if(type == "had2") { cut.type_ = MinVisPtCut::HAD; cut.index_ = 1; }
00123 else if(type == "tau2") { cut.type_ = MinVisPtCut::TAU; cut.index_ = 1; }
00124 else throw cms::Exception("Configuration") << "'" << type << "' is not a valid type. Allowed values are elec1,mu1,had1,tau1,elec2,mu2,had2,tau2" << std::endl;
00125
00126 char* endptr;
00127 cut.pt_ = strtod(sep + 1, &endptr);
00128 if(endptr == sep + 1) throw cms::Exception("Configuration") << "No pt threshold given" << std::endl;
00129
00130 cuts.push_back(cut);
00131 sub_c = endptr;
00132 }
00133 minVisPtCuts_.push_back(cuts);
00134 }
00135 }
00136
00137 edm::Service<TFileService> fileService_;
00138 if(fileService_.isAvailable()) {
00139 outTree = fileService_->make<TTree>( "event_generation","This tree stores information about the event generation");
00140 outTree->Branch("attempts",&attempts,"attempts/I");
00141 }
00142
00143 edm::Service<RandomNumberGenerator> rng;
00144 if(!rng.isAvailable()) {
00145 throw cms::Exception("Configuration")
00146 << "The RandomNumberProducer module requires the RandomNumberGeneratorService\n"
00147 "which appears to be absent. Please add that service to your configuration\n"
00148 "or remove the modules that require it." << std::endl;
00149 }
00150
00151 decayRandomEngine = &rng->getEngine();
00152
00153 edm::LogInfo("Replacer") << "generatorMode = "<< generatorMode_<< "\n";
00154 edm::LogInfo("Replacer") << "replacementMode = "<< replacementMode_<< "\n";
00155
00156 return;
00157 }
00158
00159 ParticleReplacerClass::~ParticleReplacerClass()
00160 {
00161
00162
00163 }
00164
00165
00166 std::auto_ptr<HepMC::GenEvent> ParticleReplacerClass::produce(const reco::MuonCollection& muons, const reco::Vertex *pvtx, const HepMC::GenEvent *genEvt)
00167 {
00168 using namespace edm;
00169 using namespace std;
00170 using namespace HepMC;
00171
00172 if(pvtx != 0)
00173 throw cms::Exception("Configuration") << "ParticleReplacerClass does NOT support using primary vertex as the origin for taus" << std::endl;
00174
00175 HepMC::GenEvent * evt=0;
00176
00177 GenVertex * zvtx = new GenVertex();
00178
00179 reco::GenParticle * part1=0;
00180 reco::GenParticle * part2=0;
00181
00183 std::vector<reco::Particle> particles;
00184 switch (transformationMode_)
00185 {
00186 case 0:
00187 {
00188 if (muons.size()!=2)
00189 {
00190 LogError("Replacer") << "the decay mode Z->mumu requires exactly two muons, aborting processing";
00191 return std::auto_ptr<HepMC::GenEvent>(0);
00192 }
00193
00194 targetParticleMass_ = 0.105658369;
00195 targetParticlePdgID_ = 13;
00196
00197 reco::Muon muon1 = muons.at(0);
00198 reco::Muon muon2 = muons.at(1);
00199 reco::Particle tau1(muon1.charge(), muon1.p4(), muon1.vertex(), muon1.pdgId(), 0, true);
00200 reco::Particle tau2(muon2.charge(), muon2.p4(), muon2.vertex(), muon2.pdgId(), 0, true);
00201 particles.push_back(tau1);
00202 particles.push_back(tau2);
00203 break;
00204 }
00205 case 1:
00206 {
00207 if (muons.size()!=2)
00208 {
00209 LogError("Replacer") << "the decay mode Z->tautau requires exactly two muons, aborting processing";
00210 return std::auto_ptr<HepMC::GenEvent>(0);
00211 }
00212
00213 targetParticleMass_ = 1.77690;
00214 targetParticlePdgID_ = 15;
00215
00216 reco::Muon muon1 = muons.at(0);
00217 reco::Muon muon2 = muons.at(1);
00218 reco::Particle tau1(muon1.charge(), muon1.p4(), muon1.vertex(), muon1.pdgId(), 0, true);
00219 reco::Particle tau2(muon2.charge(), muon2.p4(), muon2.vertex(), muon2.pdgId(), 0, true);
00220 transformMuMu2TauTau(&tau1, &tau2);
00221 particles.push_back(tau1);
00222 particles.push_back(tau2);
00223 break;
00224 }
00225 case 2:
00226 {
00227 if (muons.size()!=2)
00228 {
00229 LogError("Replacer") << "the decay mode Z->tautau requires exactly two muons, aborting processing";
00230 return std::auto_ptr<HepMC::GenEvent>(0);
00231 }
00232
00233 targetParticleMass_ = 1.77690;
00234 targetParticlePdgID_ = 15;
00235
00236 reco::Muon muon1 = muons.at(0);
00237 reco::Muon muon2 = muons.at(1);
00238 reco::Particle tau1(muon1.charge(), muon1.p4(), muon1.vertex(), muon1.pdgId(), 0, true);
00239 reco::Particle tau2(muon2.charge(), muon2.p4(), muon2.vertex(), muon2.pdgId(), 0, true);
00240 transformMuMu2TauNu(&tau1, &tau2);
00241 particles.push_back(tau1);
00242 particles.push_back(tau2);
00243 break;
00244 }
00245 case 3:
00246 {
00247 if (muons.size()!=2)
00248 {
00249 LogError("Replacer") << "transformation mode mu-nu ->tau-nu - wrong input";
00250 return std::auto_ptr<HepMC::GenEvent>(0);
00251 }
00252
00253 targetParticleMass_ = 1.77690;
00254 targetParticlePdgID_ = 15;
00255 int targetParticlePdgIDNu_ = 16;
00256
00257 reco::Muon muon1 = muons.at(0);
00258 reco::Muon::LorentzVector l(muon1.px(), muon1.py(), muon1.pz(),
00259 sqrt(
00260 muon1.px()*muon1.px()+
00261 muon1.py()*muon1.py()+
00262 muon1.pz()*muon1.pz()+targetParticleMass_*targetParticleMass_));
00263
00264 reco::Particle tau1(muon1.charge(), l, muon1.vertex(), targetParticlePdgID_*std::abs(muon1.pdgId())/muon1.pdgId()
00265 , 0, true
00266 );
00267 tau1.setStatus(1);
00268 particles.push_back(tau1);
00269
00270 reco::Muon nu = muons.at(1);
00271 reco::Particle nutau( 0, nu.p4(), nu.vertex(), -targetParticlePdgIDNu_*std::abs(muon1.pdgId())/muon1.pdgId(), 0, true);
00272 nutau.setStatus(1);
00273 particles.push_back(nutau);
00274
00275 break;
00276 }
00277
00278 }
00279
00280 if (particles.size()==0)
00281 {
00282 LogError("Replacer") << "the creation of the new particles failed somehow";
00283 return std::auto_ptr<HepMC::GenEvent>(0);
00284 }
00285 else
00286 {
00287 LogInfo("Replacer") << particles.size() << " particles found, continue processing";
00288 }
00289
00291 if (genEvt)
00292 {
00293
00294 evt = new HepMC::GenEvent(*genEvt);
00295
00296 for ( GenEvent::vertex_iterator p = evt->vertices_begin(); p != evt->vertices_end(); p++ )
00297 {
00298 GenVertex * vtx=(*p);
00299
00300 if ( vtx->particles_out_size()<=0 || vtx->particles_in_size()<=0)
00301 continue;
00302
00303 bool temp_muon1=false,temp_muon2=false,temp_z=false;
00304 for (GenVertex::particles_out_const_iterator it = vtx->particles_out_const_begin(); it!=vtx->particles_out_const_end(); it++)
00305 {
00306 if ((*it)->pdg_id()==13) temp_muon1=true;
00307 if ((*it)->pdg_id()==-13) temp_muon2=true;
00308 if ((*it)->pdg_id()==23) temp_z=true;
00309 }
00310
00311 int mother_pdg=(*vtx->particles_in_const_begin())->pdg_id();
00312
00313 if ((vtx->particles_out_size()==2 && vtx->particles_in_size()>0
00314 && mother_pdg == 23
00315 && temp_muon1
00316 && temp_muon2)
00317 || (vtx->particles_out_size()>2 && vtx->particles_in_size()>0
00318 && mother_pdg == 23
00319 && temp_muon1 && temp_muon2 && temp_z ))
00320 {
00321 zvtx=*p;
00322 }
00323 }
00324
00325 cleanEvent(evt, zvtx);
00326
00327
00328
00329 for (GenEvent::particle_iterator it=evt->particles_begin();it!=evt->particles_end();it++)
00330 (*it)->set_status(0);
00331
00332 for (std::vector<reco::Particle>::const_iterator it=particles.begin();it!=particles.end();it++)
00333 {
00334 zvtx->add_particle_out(new HepMC::GenParticle((FourVector)it->p4(), it->pdgId(), 1, Flow(), Polarization(0,0)));
00335 }
00336 }
00337
00338 else
00339 {
00340 reco::Particle::LorentzVector mother_particle_p4;
00341 for (std::vector<reco::Particle>::const_iterator it=particles.begin();it!=particles.end();it++)
00342 mother_particle_p4+=it->p4();
00343
00344 reco::Particle::Point production_point = particles.begin()->vertex();
00345
00346 GenVertex* startVtx = new GenVertex(FourVector(production_point.x()*10,production_point.y()*10,production_point.z()*10,0));
00347 startVtx->add_particle_in( new GenParticle( FourVector(0,0,7000,7000), 2212, 3 ) );
00348 startVtx->add_particle_in( new GenParticle( FourVector(0,0,-7000,7000), 2212, 3 ) );
00349
00350 GenVertex * decayvtx = new GenVertex(FourVector(production_point.x()*10,production_point.y()*10,production_point.z()*10,0));
00351 HepMC::GenParticle * mother_particle = new HepMC::GenParticle((FourVector)mother_particle_p4, motherParticleID_, (generatorMode_=="Pythia" ? 3 : 2), Flow(), Polarization(0,0));
00352 if (transformationMode_ == 3) {
00353
00354 int muPDG = particles.begin()->pdgId();
00355 int id = -24*muPDG/std::abs(muPDG);
00356 mother_particle->set_pdg_id(id);
00357 }
00358
00359 startVtx->add_particle_out(mother_particle);
00360 decayvtx->add_particle_in(mother_particle);
00361 evt = new HepMC::GenEvent();
00362 for (std::vector<reco::Particle>::const_iterator it=particles.begin();it!=particles.end();it++)
00363 {
00364
00365 decayvtx->add_particle_out(new HepMC::GenParticle((FourVector)it->p4(), it->pdgId(), 1, Flow(), Polarization(0,0)));
00366 }
00367
00368 evt->add_vertex(startVtx);
00369 evt->add_vertex(decayvtx);
00370 }
00371 repairBarcodes(evt);
00372
00373 HepMC::GenEvent * retevt = 0;
00374 HepMC::GenEvent * tempevt = 0;
00375
00377 int nr_of_trials=0;
00378
00379 unsigned int cntVisPt_all = 0;
00380 unsigned int cntVisPt_pass = 0;
00381
00382 HepMC::IO_HEPEVT conv;
00383 for (int i = 0; i<maxNumberOfAttempts_; i++)
00384 {
00385 ++cntVisPt_all;
00386 if (generatorMode_ == "Pythia")
00387 {
00388 LogError("Replacer") << "Pythia is currently not supported!";
00389 return std::auto_ptr<HepMC::GenEvent>(evt);
00390 }
00391
00392 if (generatorMode_ == "Tauola")
00393 {
00394 conv.write_event(evt);
00395 tempevt=tauola_.decay(evt);
00396 }
00397
00398 if (testEvent(tempevt))
00399 {
00400 if (retevt==0) {
00401 retevt=tempevt;
00402 } else {
00403 delete tempevt;
00404 }
00405 ++cntVisPt_pass;
00406 } else {
00407 delete tempevt;
00408 }
00409 }
00410 eventWeight = (double)cntVisPt_pass / (double)cntVisPt_all;
00411 std::cout << " " << cntVisPt_pass << "\t" << cntVisPt_all << "\n";
00412 if (!retevt)
00413 {
00414 LogError("Replacer") << "failed to create an event which satisfies the minimum visible transverse momentum cuts ";
00415 attempts=-1;
00416 eventWeight=0;
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 (replacementMode_==0)
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();it!=evt->vertices_end();it++)
00612 while (!(*it)->suggest_barcode(-1*(++max_barc)))
00613 ;
00614
00615 max_barc=0;
00616 for (GenEvent::particle_iterator it=evt->particles_begin();it!=evt->particles_end();it++)
00617 while (!(*it)->suggest_barcode(++max_barc))
00618 ;
00619 }
00620
00622 void ParticleReplacerClass::transformMuMu2TauTau(reco::Particle * muon1, reco::Particle * muon2)
00623 {
00624 using namespace edm;
00625 using namespace reco;
00626 using namespace std;
00627
00628 reco::Particle::LorentzVector muon1_momentum = muon1->p4();
00629 reco::Particle::LorentzVector muon2_momentum = muon2->p4();
00630 reco::Particle::LorentzVector z_momentum = muon1_momentum + muon2_momentum;
00631
00632 ROOT::Math::Boost booster(z_momentum.BoostToCM());
00633 ROOT::Math::Boost invbooster(booster.Inverse());
00634
00635 reco::Particle::LorentzVector Zb = booster(z_momentum);
00636
00637 reco::Particle::LorentzVector muon1b = booster(muon1_momentum);
00638 reco::Particle::LorentzVector muon2b = booster(muon2_momentum);
00639
00640 double tau_mass2 = targetParticleMass_*targetParticleMass_;
00641
00642 double muonxb_mom2 = muon1b.x()*muon1b.x() + muon1b.y()*muon1b.y() + muon1b.z() * muon1b.z();
00643 double tauxb_mom2 = 0.25 * Zb.t() * Zb.t() - tau_mass2;
00644
00645 float scaling1 = sqrt(tauxb_mom2 / muonxb_mom2);
00646 float scaling2 = scaling1;
00647
00648 float tauEnergy= Zb.t() / 2.;
00649
00650 if (tauEnergy*tauEnergy<tau_mass2)
00651 return;
00652
00653 reco::Particle::LorentzVector tau1b_mom = reco::Particle::LorentzVector(scaling1*muon1b.x(),scaling1*muon1b.y(),scaling1*muon1b.z(),tauEnergy);
00654 reco::Particle::LorentzVector tau2b_mom = reco::Particle::LorentzVector(scaling2*muon2b.x(),scaling2*muon2b.y(),scaling2*muon2b.z(),tauEnergy);
00655
00656 reco::Particle::LorentzVector tau1_mom = (invbooster(tau1b_mom));
00657 reco::Particle::LorentzVector tau2_mom = (invbooster(tau2b_mom));
00658
00659
00660
00661
00662
00663
00664
00665 assert(std::abs((muon1_momentum+muon2_momentum).mass()-(tau1_mom+tau2_mom).mass())/(muon1_momentum+muon2_momentum).mass()<0.001);
00666 assert(std::abs((muon1_momentum+muon2_momentum).pt()-(tau1_mom+tau2_mom).pt())/(muon1_momentum+muon2_momentum).pt()<0.001);
00667
00668 muon1->setP4(tau1_mom);
00669 muon2->setP4(tau2_mom);
00670
00671 muon1->setPdgId(targetParticlePdgID_*muon1->pdgId()/abs(muon1->pdgId()));
00672 muon2->setPdgId(targetParticlePdgID_*muon2->pdgId()/abs(muon2->pdgId()));
00673
00674 muon1->setStatus(1);
00675 muon2->setStatus(1);
00676
00677 return;
00678 }
00680 void ParticleReplacerClass::transformMuMu2TauNu(reco::Particle * part1, reco::Particle * part2)
00681 {
00682 using namespace edm;
00683 using namespace reco;
00684 using namespace std;
00685
00686 reco::Particle::LorentzVector muon1_momentum = part1->p4();
00687 reco::Particle::LorentzVector muon2_momentum = part2->p4();
00688 reco::Particle::LorentzVector z_momentum = muon1_momentum + muon2_momentum;
00689
00690 ROOT::Math::Boost booster(z_momentum.BoostToCM());
00691 ROOT::Math::Boost invbooster(booster.Inverse());
00692
00693 reco::Particle::LorentzVector Zb = booster(z_momentum);
00694
00695 const double breitWignerWidth_Z = 2.4952;
00696 const double breitWignerWidth_W = 2.141;
00697 const double knownMass_W = 80.398;
00698 const double knownMass_Z = 91.1876;
00699
00700 double Wb_mass = ( Zb.mass() - knownMass_Z ) * ( breitWignerWidth_W / breitWignerWidth_Z ) + knownMass_W;
00701 std::cout << "Wb_mass: " << Wb_mass << "\n";
00702
00703 reco::Particle::LorentzVector muon1b = booster(muon1_momentum);
00704 reco::Particle::LorentzVector muon2b = booster(muon2_momentum);
00705
00706 double tau_mass2 = targetParticleMass_*targetParticleMass_;
00707
00708 double muonxb_mom2 = muon1b.x()*muon1b.x() + muon1b.y()*muon1b.y() + muon1b.z() * muon1b.z();
00709 double tauxb_mom2 = 0.25 * Zb.t() * Zb.t() - tau_mass2;
00710
00711 float scaling1 = sqrt(tauxb_mom2 / muonxb_mom2) * Wb_mass/Zb.mass();
00712 float scaling2 = scaling1;
00713
00714 float tauEnergy= Zb.t() / 2.;
00715
00716 if (tauEnergy*tauEnergy<tau_mass2)
00717 return;
00718
00719 reco::Particle::LorentzVector tau1b_mom = reco::Particle::LorentzVector(scaling1*muon1b.x(),scaling1*muon1b.y(),scaling1*muon1b.z(),tauEnergy* Wb_mass/Zb.mass());
00720 reco::Particle::LorentzVector tau2b_mom = reco::Particle::LorentzVector(scaling2*muon2b.x(),scaling2*muon2b.y(),scaling2*muon2b.z(),tauEnergy* Wb_mass/Zb.mass());
00721
00722 std::cout << "muon1b_momentum: " << muon1b << "\n";
00723 std::cout << "muon2b_momentum: " << muon2b << "\n";
00724
00725 std::cout << "tau1b_momentum: " << tau1b_mom << "\n";
00726 std::cout << "tau2b_momentum: " << tau2b_mom << "\n";
00727
00728 std::cout << "zb_momentum: " << Zb << "\n";
00729 std::cout << "wb_momentum: " << (tau1b_mom+tau2b_mom) << "\n";
00730
00731
00732
00733
00734
00735
00736 assert((muon1b.phi()-tau1b_mom.phi())/muon1b.phi()<0.001);
00737 assert((muon2b.phi()-tau2b_mom.phi())/muon2b.phi()<0.001);
00738 assert((muon1b.theta()-tau1b_mom.theta())/muon1b.theta()<0.001);
00739 assert((muon2b.theta()-tau2b_mom.theta())/muon2b.theta()<0.001);
00740
00741 reco::Particle::LorentzVector tau1_mom = (invbooster(tau1b_mom));
00742 reco::Particle::LorentzVector tau2_mom = (invbooster(tau2b_mom));
00743
00744
00745
00746
00747
00748
00749
00750
00751
00752
00753 part1->setP4(tau1_mom);
00754 part2->setP4(tau2_mom);
00755
00756 part1->setPdgId(15*part1->pdgId()/abs(part1->pdgId()));
00757 part2->setPdgId(16*part2->pdgId()/abs(part2->pdgId()));
00758
00759 part1->setStatus(1);
00760 part2->setStatus(1);
00761
00762 return;
00763 }
00764
00765
00766
00767