00001 #include "AGILe/Run.hh" 00002 00003 using namespace std; 00004 00005 namespace AGILe { 00006 00007 00008 Run::Run(Generator& gen) 00009 : _gen(&gen), _filter(Run::DOCFILT)//, _ostr(0), _io(0) 00010 { 00011 // 00012 } 00013 00014 00015 // Make a generator run with a particular gen and I/O target 00016 Run::Run(Generator& gen, const string& evtfile, int precision) 00017 : _gen(&gen), _filter(Run::DOCFILT) 00018 { 00019 if (evtfile.size() > 0) { 00020 if (evtfile == "-") { 00021 _io.reset(new HepMC::IO_GenEvent(std::cout)); 00022 } else { 00023 // Ignore the HepMC::IO_GenEvent(filename, ios) constructor, since only available from HepMC >= 2.4 00024 _ostr.reset(new std::fstream(evtfile.c_str(), std::ios::out)); 00025 _io.reset(new HepMC::IO_GenEvent(*_ostr)); 00026 } 00027 // Use the cross-section #define as a proxy for precision() being available 00028 #ifdef HEPMC_HAS_CROSS_SECTION 00029 _io->precision(precision); 00030 #endif 00031 } 00032 } 00033 00034 00035 void filterEvent(HepMC::GenEvent* ge, Run::FilterLevel filterlevel) { 00036 // Escape fast if there's nothing to do 00037 if (filterlevel == Run::NOFILT) return; 00038 00039 // We treat beam particles a bit specially 00040 const std::pair<HepMC::GenParticle*, HepMC::GenParticle*> beams = ge->beam_particles(); 00041 00042 // Make list of non-physical particle entries 00043 std::vector<HepMC::GenParticle*> unphys_particles; 00044 for (HepMC::GenEvent::particle_const_iterator pi = ge->particles_begin(); 00045 pi != ge->particles_end(); ++pi) { 00046 // Beam particles might not have status = 4, but we want them anyway 00047 if (beams.first == *pi || beams.second == *pi) continue; 00048 // Filter by status 00049 const int status = (*pi)->status(); 00050 const bool keep = (status == 1 || status == 4 || (filterlevel != Run::UNSTABLEFILT && status == 2)); 00051 if (!keep) { 00052 unphys_particles.push_back(*pi); 00053 } 00054 } 00055 00056 // Remove each unphysical particle from the list 00057 while (unphys_particles.size()) { 00058 HepMC::GenParticle* gp = unphys_particles.back(); 00059 00060 // Get start and end vertices 00061 HepMC::GenVertex* vstart = gp->production_vertex(); 00062 HepMC::GenVertex* vend = gp->end_vertex(); 00063 00064 if (vend == vstart) { 00065 // Deal with loops 00066 vstart->remove_particle(gp); 00067 } else { 00068 00069 // Connect decay particles from end vertex to start vertex 00071 if (vend && vend->particles_out_size()) { 00072 std::vector<HepMC::GenParticle*> end_particles; 00073 for (HepMC::GenVertex::particles_out_const_iterator gpe = vend->particles_out_const_begin(); 00074 gpe != vend->particles_out_const_end(); ++gpe) { 00075 end_particles.push_back(*gpe); 00076 } 00077 // Reset production vertices of child particles to bypass unphysical particle 00078 for (std::vector<HepMC::GenParticle*>::const_iterator gpe = end_particles.begin(); 00079 gpe != end_particles.end(); ++gpe) { 00080 //std::cout << vstart << ", " << vend << std::endl; 00081 if (vstart) vstart->add_particle_out(*gpe); 00082 } 00083 } else { 00084 // If null end_vertex... stable unphysical particle? 00085 } 00086 00087 // Delete unphysical particle and its orphaned end vertex 00088 delete vend; 00089 if (vstart) { 00090 delete vstart->remove_particle(gp); 00091 } 00092 } 00093 00094 // Remove deleted particle from list 00095 unphys_particles.pop_back(); 00096 //std::cout << unphys_particles.size() << std::endl; 00097 } 00098 00099 // Delete any orphaned vertices 00100 std::vector<HepMC::GenVertex*> orphaned_vtxs; 00101 for (HepMC::GenEvent::vertex_const_iterator vi = ge->vertices_begin(); 00102 vi != ge->vertices_end(); ++vi) { 00103 if ((*vi)->particles_in_size() == 0 && (*vi)->particles_out_size() == 0) { 00104 orphaned_vtxs.push_back(*vi); 00105 } 00106 } 00107 while (orphaned_vtxs.size()) { 00108 delete orphaned_vtxs.back(); 00109 orphaned_vtxs.pop_back(); 00110 } 00111 } 00112 00113 00114 00115 // Generate an event and send it to the writer if it exists 00116 bool Run::makeEvent() { 00117 // Make and fill event 00118 _gen->makeEvent(_evt); 00119 00120 // Filter unphysical bits of event (reduces storage/transport size, and ensures physicality) 00121 filterEvent(&_evt, _filter); 00122 00123 // Do I/O streaming if required 00124 if (_io) { 00125 _io->write_event(&_evt); 00126 if (_io->rdstate() != 0) { 00127 return false; 00128 } 00129 } 00130 00131 return true; 00132 } 00133 00134 00135 // Return an event summary string 00136 string Run::eventSummary() const { 00137 std::ostringstream ss; 00138 int Nfs = 0; 00139 for (HepMC::GenEvent::particle_const_iterator pi = _evt.particles_begin(); 00140 pi != _evt.particles_end(); ++pi) { 00141 if ((*pi)->status() == 1) Nfs += 1; 00142 } 00143 ss << "HepMC::GenEvent { " 00144 << _evt.particles_size() << " particles " 00145 << "(" << Nfs << " in FS), " 00146 << _evt.vertices_size() << " vertices }"; 00147 return ss.str(); 00148 } 00149 00150 00151 }