#include "ATOOLS/Org/CXXFLAGS_PACKAGES.H" #ifdef USING__DELPHES #ifndef USING__ROOT #error Delphes cannot be used without Root. \ Please reconfigure with --enable-root #endif #include "SHERPA/Tools/Output_Base.H" #include "SHERPA/Tools/HepMC2_Interface.H" #include "Utilities/ExRootAnalysis/interface/ExRootTreeWriter.h" #include "Utilities/ExRootAnalysis/interface/BlockClasses.h" namespace HepMC { class IO_GenEvent; class GenCrossSection; class GenEvent; } namespace DELPHES { class Output_Delphes: public SHERPA::Output_Base { private: SHERPA::HepMC2_Interface m_hepmc2; HepMC::IO_GenEvent *p_iogenevent; HepMC::GenCrossSection *p_xs; HepMC::GenEvent *p_event; ExRootTreeWriter *p_treeWriter; ExRootTreeBranch *p_branchGenEvent; ExRootTreeBranch *p_branchGenParticle; std::string m_basename, m_ext; int m_mode; void AnalyseParticles(ExRootTreeBranch *branch,const HepMC::GenEvent& evt); void AnalyseEvent(ExRootTreeBranch *branch,const HepMC::GenEvent& evt, const Long64_t eventNumber,const double weight); void ReadStats(); void getStatsFromTuple(int &mo1, int &mo2, int &da1, int &da2, int &status, int &pid, int j) const; std::vector index_to_particle; std::map particle_to_index; inline int find_in_map(HepMC::GenParticle *p) const { std::map::const_iterator iter = particle_to_index.find(p); return (iter == particle_to_index.end()) ? 0 : iter->second; } public: Output_Delphes(const SHERPA::Output_Arguments &args,int mode); ~Output_Delphes(); void SetXS(const double& xs, const double& xserr); void Output(ATOOLS::Blob_List* blobs); void ChangeFile(); };// end of class Output_Delphes class Output_Delphes_GenEvent: public Output_Delphes {}; }// end of namespace DELPHES #include "HepMC/GenEvent.h" #include "ATOOLS/Org/Shell_Tools.H" #include "ATOOLS/Org/MyStrStream.H" #include "ATOOLS/Org/Exception.H" #ifdef USING__HEPMC2__DEFS #include "HepMC/HepMCDefs.h" #ifdef HEPMC_HAS_CROSS_SECTION #include "HepMC/GenCrossSection.h" #endif #endif #include "Utilities/ExRootAnalysis/interface/ExRootTreeWriter.h" #include "Utilities/ExRootAnalysis/interface/BlockClasses.h" #include "Utilities/ExRootAnalysis/interface/ExRootTreeBranch.h" using namespace DELPHES; using namespace SHERPA; using namespace ATOOLS; Output_Delphes::Output_Delphes(const Output_Arguments &args,int mode): Output_Base(mode?"Delphes":"DelphesS"), p_event(NULL), m_mode(mode) { m_basename=args.m_outpath+"/"+args.m_outfile; m_ext=m_mode?"_ge.root":".root"; #ifdef HEPMC_HAS_CROSS_SECTION p_xs = new HepMC::GenCrossSection(); #endif if (m_mode==0) p_event = new HepMC::GenEvent(); p_treeWriter = new ExRootTreeWriter(m_basename+m_ext,"GEN"); p_branchGenEvent = p_treeWriter->NewBranch ("Event", TRootLHEFEvent::Class()); p_branchGenParticle = p_treeWriter->NewBranch ("Particle", TRootC::GenParticle::Class()); } Output_Delphes::~Output_Delphes() { p_treeWriter->Write(); delete p_treeWriter; p_treeWriter=NULL; if (m_mode==0) delete p_event; } void Output_Delphes::SetXS(const double& xs, const double& xserr) { #ifdef HEPMC_HAS_CROSS_SECTION p_xs->set_cross_section(xs, xserr); #endif } void Output_Delphes::Output(Blob_List* blobs) { #ifdef USING__HEPMC2__IOGENEVENT if (m_mode==0) { p_event->clear(); m_hepmc2.Sherpa2ShortHepMC(blobs,*p_event); } else { m_hepmc2.Sherpa2HepMC(blobs); p_event = m_hepmc2.GenEvent(); } #ifdef HEPMC_HAS_CROSS_SECTION p_event->set_cross_section(*p_xs); #endif p_treeWriter->Clear(); const auto weight(blobs->Weight()); AnalyseEvent(p_branchGenEvent,*p_event, p_event->event_number()+1,weight); AnalyseParticles(p_branchGenParticle,*p_event); p_treeWriter->Fill(); #endif } void Output_Delphes::ChangeFile() { } void Output_Delphes::AnalyseEvent (ExRootTreeBranch *branch,const HepMC::GenEvent& evt, const Long64_t eventNumber,const double weight) { TRootLHEFEvent *element; element = static_cast(branch->NewEntry()); element->Number = eventNumber; element->Nparticles = evt.particles_size(); element->ProcessID = evt.signal_process_id(); element->Weight = weight; element->ScalePDF = evt.event_scale(); element->CouplingQED = evt.alphaQED(); element->CouplingQCD = evt.alphaQCD(); } void Output_Delphes::ReadStats() { unsigned int particle_counter=0; index_to_particle.clear(); particle_to_index.clear(); index_to_particle.reserve(p_event->particles_size()); index_to_particle[0] = 0; HepMC::GenEvent::vertex_const_iterator v; for (v = p_event->vertices_begin(); v != p_event->vertices_end(); ++v ) { // making a list of incoming particles of the vertices // so that the mother indices in HEPEVT can be filled properly HepMC::GenVertex::particles_out_const_iterator p1; for (p1 = (*v)->particles_in_const_begin();p1 != (*v)->particles_in_const_end(); ++p1 ) { ++particle_counter; //particle_counter can be very large for heavy ions if(particle_counter >= index_to_particle.size() ) { //make it large enough to hold up to this index index_to_particle.resize(particle_counter+1); } index_to_particle[particle_counter] = *p1; particle_to_index[*p1] = particle_counter; } // daughters are entered only if they aren't a mother of // another vertex HepMC::GenVertex::particles_out_const_iterator p2; for (p2 = (*v)->particles_out_const_begin();p2 != (*v)->particles_out_const_end(); ++p2) { if (!(*p2)->end_vertex()) { ++particle_counter; //particle_counter can be very large for heavy ions if(particle_counter >= index_to_particle.size() ) { //make it large enough to hold up to this index index_to_particle.resize(particle_counter+1); } index_to_particle[particle_counter] = *p2; particle_to_index[*p2] = particle_counter; } } } } void Output_Delphes::getStatsFromTuple(int &mo1, int &mo2, int &da1, int &da2, int &status, int &pid, int j) const { status = index_to_particle[j]->status(); pid = index_to_particle[j]->pdg_id(); if ( index_to_particle[j]->production_vertex() ) { int num_mothers = index_to_particle[j]->production_vertex()->particles_in_size(); if (num_mothers ==0) { mo1 = 0; mo2 = 0; } else { int first_mother = find_in_map(*(index_to_particle[j]->production_vertex()->particles_in_const_begin())); int last_mother = first_mother + num_mothers - 1; if ( first_mother == 0 ) last_mother = 0; mo1=first_mother; mo2=last_mother; } // if num_mothers !=0 } else // no data on production_vertex { mo1 =0; mo2 =0; } if (index_to_particle[j]->end_vertex()) { // make sure first and last daughter are indeed the first and last int first_daughter = find_in_map(*(index_to_particle[j]->end_vertex()->particles_begin(HepMC::children))); int last_daughter = 0; HepMC::GenVertex::particle_iterator ic; for (ic = index_to_particle[j]->end_vertex()->particles_begin(HepMC::children);ic != index_to_particle[j]->end_vertex()->particles_end(HepMC::children); ++ic) { int current_daughter = find_in_map(*ic) ; if (current_daughter < first_daughter) first_daughter = current_daughter; if (current_daughter > last_daughter) last_daughter = current_daughter; } if (first_daughter== 0) last_daughter = 0; da1=first_daughter; da2=last_daughter; } else { da1=0; da2=0; } } void Output_Delphes::AnalyseParticles(ExRootTreeBranch *branch, const HepMC::GenEvent& evt) { TRootC::GenParticle *element; TLorentzVector momentum; Double_t signPz; ReadStats(); for(int n=1; n<=evt.particles_size(); n++) { int mo1, mo2, da1, da2, status, pid; getStatsFromTuple(mo1,mo2,da1,da2,status,pid,n); element = static_cast(branch->NewEntry()); element->PID = pid; element->Status = status; element->M1 = mo1 - 1; // added -1 as the numbering in the tree starts from 0 element->M2 = mo2 - 1; element->D1 = da1 - 1; element->D2 = da2 - 1; element->E = index_to_particle[n]->momentum().e(); element->Px = index_to_particle[n]->momentum().px(); element->Py = index_to_particle[n]->momentum().py(); element->Pz = index_to_particle[n]->momentum().pz(); element->PT = sqrt(pow(element->Px,2)+pow(element->Py,2)); momentum.SetPxPyPzE(element->Px, element->Py, element->Pz, element->E); signPz = (element->Pz >= 0.0) ? 1.0 : -1.0; element->Eta = element->PT < 1e-6 ? signPz*999.9 : momentum.Eta(); element->Phi = index_to_particle[n]->momentum().phi(); HepMC::GenVertex* vrtI = (index_to_particle[n])->production_vertex(); HepMC::GenVertex::particles_in_const_iterator partI; if(vrtI) { element->T = vrtI->position().t(); element->X = vrtI->position().x(); element->Y = vrtI->position().y(); element->Z = vrtI->position().z(); } else { element->T = 0.; element->X = 0.; element->Y = 0.; element->Z = 0.; } } } DECLARE_GETTER(Output_Delphes,"Delphes_Short", Output_Base,Output_Arguments); Output_Base *ATOOLS::Getter:: operator()(const Output_Arguments &args) const { return new Output_Delphes(args,0); } void ATOOLS::Getter:: PrintInfo(std::ostream &str,const size_t width) const { str<<"Delphes short output"; } DECLARE_GETTER(Output_Delphes_GenEvent,"Delphes_GenEvent", Output_Base,Output_Arguments); Output_Base *ATOOLS::Getter:: operator()(const Output_Arguments &args) const { return new Output_Delphes(args,1); } void ATOOLS::Getter:: PrintInfo(std::ostream &str,const size_t width) const { str<<"Delphes long output"; } #endif