CMS 3D CMS Logo

/data/refman/pasoursint/CMSSW_6_1_2_SLHC2/src/TauAnalysis/MCEmbeddingTools/src/ParticleReplacerClass.cc

Go to the documentation of this file.
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 //      using namespace reco;
00033         using namespace edm;
00034         using namespace std;
00035 
00036         //HepMC::HEPEVT_Wrapper::set_max_number_entries(4000);
00037         //HepMC::HEPEVT_Wrapper::set_sizeof_real(8);
00038 
00039         // transformationMode =
00040         //  0 - no transformation
00041         //  1 - mumu -> tautau
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         // If one wants to use two instances of this module in one
00074         // configuration file, there might occur some segmentation
00075         // faults due to the second initialisation of Tauola. This
00076         // can be prevented by setting noInitialisation to false.
00077         //          Caution: This option is not tested!
00078         noInitialisation_ = pset.getUntrackedParameter<bool>("noInitialisation",false);
00079 
00080         motherParticleID_ = pset.getUntrackedParameter<int>("motherParticleID",23);
00081 
00082         // requires the visible decay products of a tau to have a sum transverse momentum
00083         std::string minVisibleTransverseMomentumLine = pset.getUntrackedParameter<std::string>("minVisibleTransverseMomentum","");
00084 
00085   // fallback for backwards compatibility: If it's a single number then use this as a threshold for both particles
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           // string has new format: parse the minvistransversemomentum string
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         // this is a global variable defined in GeneratorInterface/ExternalDecays/src/ExternalDecayDriver.cc
00150         decayRandomEngine = &rng->getEngine();
00151 
00152         edm::LogInfo("Replacer") << "generatorMode = "<< generatorMode_<< "\n";
00153 
00154         return;
00155 }
00156 
00157 ParticleReplacerClass::~ParticleReplacerClass()
00158 {
00159         // do anything here that needs to be done at desctruction time
00160         // (e.g. close files, deallocate resources etc.)
00161 }
00162 
00163 // ------------ method called to produce the data  ------------
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: // mumu->mumu
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: // mumu->tautau
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: // mumu->taunu (W boson)
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: // mu-nu->tau-nu
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                         // prevent a decay of existing particles
00326                         // this is due to a bug in the PythiaInterface that should be fixed in newer versions
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         // new product with tau decays
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                   //std::cout << "Overriding mother particle id\n" << std::endl;
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                         //std::cout << "XXX" << it->p4().pt() << " " << it->pdgId() << std::endl;
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") // Pythia
00385                 {
00386                         LogError("Replacer") << "Pythia is currently not supported!";
00387                         return std::auto_ptr<HepMC::GenEvent>(evt);
00388                 }
00389 
00390                 if (generatorMode_ == "Tauola") // 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 << /*minVisibleTransverseMomentum_ <<*/ " " << 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         // recover the status codes
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 // ------------ method called once each job just before starting event loop  ------------
00448 void ParticleReplacerClass::beginRun(edm::Run& iRun,const edm::EventSetup& iSetup)
00449 {
00450         tauola_->init(iSetup);
00451 }
00452 
00453 // ------------ method called once each job just after ending the event loop  ------------
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()) //ibleTransverseMomentum_<=0)
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       // subcut fail
00534       if(iter2->index_ >= collection->size() || (*collection)[iter2->index_] < iter2->pt_)
00535         break;
00536     }
00537 
00538     // no subcut failed: This cut passed
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         // repair the barcodes
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         // some additional checks
00666         // the following tests guarantee a deviation of less
00667         // than 0.1% for the following values of the original
00668         // muons and the placed taus
00669         //      invariant mass
00670         //      transverse momentum
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         // some checks
00738         // the following test guarantees a deviation
00739         // of less than 0.1% for phi and theta for the
00740         // original muons and the placed taus
00741         // (in the centre-of-mass system of the z boson)
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         // some additional checks
00751         // the following tests guarantee a deviation of less
00752         // than 0.1% for the following values of the original
00753         // muons and the placed taus
00754         //      invariant mass
00755         //      transverse momentum
00756         //assert(((muon1_momentum+muon1_momentum).mass()-(tau1_mom+tau2_mom).mass())/(muon1_momentum+muon1_momentum).mass()<0.001);
00757         //assert(((muon1_momentum+muon2_momentum).pt()-(tau1_mom+tau2_mom).pt())/(muon1_momentum+muon1_momentum).pt()<0.001);
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 //define this as a plug-in
00773 //DEFINE_FWK_MODULE(Replacer);