CMS 3D CMS Logo

/data/refman/pasoursint/CMSSW_5_3_10_patch2/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_(pset.getParameter< edm::ParameterSet>("TauolaOptions")),
00027   //tauola_(gen::TauolaInterface::getInstance()),
00028   printEvent_(verbose),
00029   outTree(0),
00030   maxNumberOfAttempts_(pset.getUntrackedParameter<int>("maxNumberOfAttempts", 1000))
00031 {
00032 //      tauola_->setPSet(pset.getParameter< edm::ParameterSet>("TauolaOptions"));
00033 //      using namespace reco;
00034         using namespace edm;
00035         using namespace std;
00036 
00037         //HepMC::HEPEVT_Wrapper::set_max_number_entries(4000);
00038         //HepMC::HEPEVT_Wrapper::set_sizeof_real(8);
00039 
00040         // transformationMode =
00041         //  0 - no transformation
00042         //  1 - mumu -> tautau
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         // If one wants to use two instances of this module in one
00075         // configuration file, there might occur some segmentation
00076         // faults due to the second initialisation of Tauola. This
00077         // can be prevented by setting noInitialisation to false.
00078         //          Caution: This option is not tested!
00079         noInitialisation_ = pset.getUntrackedParameter<bool>("noInitialisation",false);
00080 
00081         motherParticleID_ = pset.getUntrackedParameter<int>("motherParticleID",23);
00082 
00083         // requires the visible decay products of a tau to have a sum transverse momentum
00084         std::string minVisibleTransverseMomentumLine = pset.getUntrackedParameter<std::string>("minVisibleTransverseMomentum","");
00085 
00086   // fallback for backwards compatibility: If it's a single number then use this as a threshold for both particles
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           // string has new format: parse the minvistransversemomentum string
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         // this is a global variable defined in GeneratorInterface/ExternalDecays/src/ExternalDecayDriver.cc
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         // do anything here that needs to be done at desctruction time
00162         // (e.g. close files, deallocate resources etc.)
00163 }
00164 
00165 // ------------ method called to produce the data  ------------
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: // mumu->mumu
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: // mumu->tautau
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: // mumu->taunu (W boson)
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: // mu-nu->tau-nu
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                         // prevent a decay of existing particles
00328                         // this is due to a bug in the PythiaInterface that should be fixed in newer versions
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         // new product with tau decays
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                   //std::cout << "Overriding mother particle id\n" << std::endl;
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                         //std::cout << "XXX" << it->p4().pt() << " " << it->pdgId() << std::endl;
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") // Pythia
00387                 {
00388                         LogError("Replacer") << "Pythia is currently not supported!";
00389                         return std::auto_ptr<HepMC::GenEvent>(evt);
00390                 }
00391 
00392                 if (generatorMode_ == "Tauola") // 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 << /*minVisibleTransverseMomentum_ <<*/ " " << 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         // recover the status codes
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 // ------------ 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();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         // some additional checks
00660         // the following tests guarantee a deviation of less
00661         // than 0.1% for the following values of the original
00662         // muons and the placed taus
00663         //      invariant mass
00664         //      transverse momentum
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         // some checks
00732         // the following test guarantees a deviation
00733         // of less than 0.1% for phi and theta for the
00734         // original muons and the placed taus
00735         // (in the centre-of-mass system of the z boson)
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         // some additional checks
00745         // the following tests guarantee a deviation of less
00746         // than 0.1% for the following values of the original
00747         // muons and the placed taus
00748         //      invariant mass
00749         //      transverse momentum
00750         //assert(((muon1_momentum+muon1_momentum).mass()-(tau1_mom+tau2_mom).mass())/(muon1_momentum+muon1_momentum).mass()<0.001);
00751         //assert(((muon1_momentum+muon2_momentum).pt()-(tau1_mom+tau2_mom).pt())/(muon1_momentum+muon1_momentum).pt()<0.001);
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 //define this as a plug-in
00767 //DEFINE_FWK_MODULE(Replacer);