![]() |
HepMC Reference DocumentationHepMC |
00001 00002 // Matt.Dobbs@Cern.CH, January 2000 00003 // HEPEVT IO class 00005 00006 #include "HepMC/IO_HEPEVT.h" 00007 #include "HepMC/GenEvent.h" 00008 #include <cstdio> // needed for formatted output using sprintf 00009 00010 namespace HepMC { 00011 00012 IO_HEPEVT::IO_HEPEVT() : m_trust_mothers_before_daughters(1), 00013 m_trust_both_mothers_and_daughters(0), 00014 m_print_inconsistency_errors(1), 00015 m_trust_beam_particles(true) 00016 {} 00017 00018 IO_HEPEVT::~IO_HEPEVT(){} 00019 00020 void IO_HEPEVT::print( std::ostream& ostr ) const { 00021 ostr << "IO_HEPEVT: reads an event from the FORTRAN HEPEVT " 00022 << "common block. \n" 00023 << " trust_mothers_before_daughters = " 00024 << m_trust_mothers_before_daughters 00025 << " trust_both_mothers_and_daughters = " 00026 << m_trust_both_mothers_and_daughters 00027 << ", print_inconsistency_errors = " 00028 << m_print_inconsistency_errors << std::endl; 00029 } 00030 00031 bool IO_HEPEVT::fill_next_event( GenEvent* evt ) { 00045 // 00046 // 1. test that evt pointer is not null and set event number 00047 if ( !evt ) { 00048 std::cerr 00049 << "IO_HEPEVT::fill_next_event error - passed null event." 00050 << std::endl; 00051 return false; 00052 } 00053 evt->set_event_number( HEPEVT_Wrapper::event_number() ); 00054 // 00055 // 2. create a particle instance for each HEPEVT entry and fill a map 00056 // create a vector which maps from the HEPEVT particle index to the 00057 // GenParticle address 00058 // (+1 in size accounts for hepevt_particle[0] which is unfilled) 00059 std::vector<GenParticle*> hepevt_particle( 00060 HEPEVT_Wrapper::number_entries()+1 ); 00061 hepevt_particle[0] = 0; 00062 for ( int i1 = 1; i1 <= HEPEVT_Wrapper::number_entries(); ++i1 ) { 00063 hepevt_particle[i1] = build_particle(i1); 00064 } 00065 std::set<GenVertex*> new_vertices; 00066 // 00067 // Here we assume that the first two particles in the list 00068 // are the incoming beam particles. 00069 if( trust_beam_particles() ) { 00070 evt->set_beam_particles( hepevt_particle[1], hepevt_particle[2] ); 00071 } 00072 // 00073 // 3.+4. loop over HEPEVT particles AGAIN, this time creating vertices 00074 for ( int i = 1; i <= HEPEVT_Wrapper::number_entries(); ++i ) { 00075 // We go through and build EITHER the production or decay 00076 // vertex for each entry in hepevt, depending on the switch 00077 // m_trust_mothers_before_daughters (new 2001-02-28) 00078 // Note: since the HEPEVT pointers are bi-directional, it is 00080 // 00081 // 3. Build the production_vertex (if necessary) 00082 if ( m_trust_mothers_before_daughters || 00083 m_trust_both_mothers_and_daughters ) { 00084 build_production_vertex( i, hepevt_particle, evt ); 00085 } 00086 // 00087 // 4. Build the end_vertex (if necessary) 00088 // Identical steps as for production vertex 00089 if ( !m_trust_mothers_before_daughters || 00090 m_trust_both_mothers_and_daughters ) { 00091 build_end_vertex( i, hepevt_particle, evt ); 00092 } 00093 } 00094 // 5. 01.02.2000 00095 // handle the case of particles in HEPEVT which come from nowhere - 00096 // i.e. particles without mothers or daughters. 00097 // These particles need to be attached to a vertex, or else they 00098 // will never become part of the event. check for this situation 00099 for ( int i3 = 1; i3 <= HEPEVT_Wrapper::number_entries(); ++i3 ) { 00100 if ( !hepevt_particle[i3]->end_vertex() && 00101 !hepevt_particle[i3]->production_vertex() ) { 00102 GenVertex* prod_vtx = new GenVertex(); 00103 prod_vtx->add_particle_out( hepevt_particle[i3] ); 00104 evt->add_vertex( prod_vtx ); 00105 } 00106 } 00107 return true; 00108 } 00109 00110 void IO_HEPEVT::write_event( const GenEvent* evt ) { 00116 // 00117 if ( !evt ) return; 00118 // 00119 // map all particles onto a unique index 00120 std::vector<GenParticle*> index_to_particle( 00121 HEPEVT_Wrapper::max_number_entries()+1 ); 00122 index_to_particle[0]=0; 00123 std::map<GenParticle*,int> particle_to_index; 00124 int particle_counter=0; 00125 for ( GenEvent::vertex_const_iterator v = evt->vertices_begin(); 00126 v != evt->vertices_end(); ++v ) { 00127 // all "mothers" or particles_in are kept adjacent in the list 00128 // so that the mother indices in hepevt can be filled properly 00129 for ( GenVertex::particles_in_const_iterator p1 00130 = (*v)->particles_in_const_begin(); 00131 p1 != (*v)->particles_in_const_end(); ++p1 ) { 00132 ++particle_counter; 00133 if ( particle_counter > 00134 HEPEVT_Wrapper::max_number_entries() ) break; 00135 index_to_particle[particle_counter] = *p1; 00136 particle_to_index[*p1] = particle_counter; 00137 } 00138 // daughters are entered only if they aren't a mother of 00139 // another vtx 00140 for ( GenVertex::particles_out_const_iterator p2 00141 = (*v)->particles_out_const_begin(); 00142 p2 != (*v)->particles_out_const_end(); ++p2 ) { 00143 if ( !(*p2)->end_vertex() ) { 00144 ++particle_counter; 00145 if ( particle_counter > 00146 HEPEVT_Wrapper::max_number_entries() ) { 00147 break; 00148 } 00149 index_to_particle[particle_counter] = *p2; 00150 particle_to_index[*p2] = particle_counter; 00151 } 00152 } 00153 } 00154 if ( particle_counter > HEPEVT_Wrapper::max_number_entries() ) { 00155 particle_counter = HEPEVT_Wrapper::max_number_entries(); 00156 } 00157 // 00158 // fill the HEPEVT event record 00159 HEPEVT_Wrapper::set_event_number( evt->event_number() ); 00160 HEPEVT_Wrapper::set_number_entries( particle_counter ); 00161 for ( int i = 1; i <= particle_counter; ++i ) { 00162 HEPEVT_Wrapper::set_status( i, index_to_particle[i]->status() ); 00163 HEPEVT_Wrapper::set_id( i, index_to_particle[i]->pdg_id() ); 00164 FourVector m = index_to_particle[i]->momentum(); 00165 HEPEVT_Wrapper::set_momentum( i, m.px(), m.py(), m.pz(), m.e() ); 00166 HEPEVT_Wrapper::set_mass( i, index_to_particle[i]->generatedMass() ); 00167 // there should ALWAYS be particles in any vertex, but some generators 00168 // are making non-kosher HepMC events 00169 if ( index_to_particle[i]->production_vertex() && 00170 index_to_particle[i]->production_vertex()->particles_in_size()) { 00171 FourVector p = index_to_particle[i]-> 00172 production_vertex()->position(); 00173 HEPEVT_Wrapper::set_position( i, p.x(), p.y(), p.z(), p.t() ); 00174 int num_mothers = index_to_particle[i]->production_vertex()-> 00175 particles_in_size(); 00176 int first_mother = find_in_map( particle_to_index, 00177 *(index_to_particle[i]-> 00178 production_vertex()-> 00179 particles_in_const_begin())); 00180 int last_mother = first_mother + num_mothers - 1; 00181 if ( first_mother == 0 ) last_mother = 0; 00182 HEPEVT_Wrapper::set_parents( i, first_mother, last_mother ); 00183 } else { 00184 HEPEVT_Wrapper::set_position( i, 0, 0, 0, 0 ); 00185 HEPEVT_Wrapper::set_parents( i, 0, 0 ); 00186 } 00187 HEPEVT_Wrapper::set_children( i, 0, 0 ); 00188 } 00189 } 00190 00191 void IO_HEPEVT::build_production_vertex(int i, 00192 std::vector<HepMC::GenParticle*>& 00193 hepevt_particle, 00194 GenEvent* evt ) { 00198 GenParticle* p = hepevt_particle[i]; 00199 // a. search to see if a production vertex already exists 00200 int mother = HEPEVT_Wrapper::first_parent(i); 00201 GenVertex* prod_vtx = p->production_vertex(); 00202 while ( !prod_vtx && mother > 0 ) { 00203 prod_vtx = hepevt_particle[mother]->end_vertex(); 00204 if ( prod_vtx ) prod_vtx->add_particle_out( p ); 00205 // increment mother for next iteration 00206 if ( ++mother > HEPEVT_Wrapper::last_parent(i) ) mother = 0; 00207 } 00208 // b. if no suitable production vertex exists - and the particle 00209 // has atleast one mother or position information to store - 00210 // make one 00211 FourVector prod_pos( HEPEVT_Wrapper::x(i), HEPEVT_Wrapper::y(i), 00212 HEPEVT_Wrapper::z(i), HEPEVT_Wrapper::t(i) 00213 ); 00214 if ( !prod_vtx && (HEPEVT_Wrapper::number_parents(i)>0 00215 || prod_pos!=FourVector(0,0,0,0)) ) 00216 { 00217 prod_vtx = new GenVertex(); 00218 prod_vtx->add_particle_out( p ); 00219 evt->add_vertex( prod_vtx ); 00220 } 00221 // c. if prod_vtx doesn't already have position specified, fill it 00222 if ( prod_vtx && prod_vtx->position()==FourVector(0,0,0,0) ) { 00223 prod_vtx->set_position( prod_pos ); 00224 } 00225 // d. loop over mothers to make sure their end_vertices are 00226 // consistent 00227 mother = HEPEVT_Wrapper::first_parent(i); 00228 while ( prod_vtx && mother > 0 ) { 00229 if ( !hepevt_particle[mother]->end_vertex() ) { 00230 // if end vertex of the mother isn't specified, do it now 00231 prod_vtx->add_particle_in( hepevt_particle[mother] ); 00232 } else if (hepevt_particle[mother]->end_vertex() != prod_vtx ) { 00233 // problem scenario --- the mother already has a decay 00234 // vertex which differs from the daughter's produciton 00235 // vertex. This means there is internal 00236 // inconsistency in the HEPEVT event record. Print an 00237 // error 00238 // Note: we could provide a fix by joining the two 00239 // vertices with a dummy particle if the problem 00240 // arrises often with any particular generator. 00241 if ( m_print_inconsistency_errors ) std::cerr 00242 << "HepMC::IO_HEPEVT: inconsistent mother/daugher " 00243 << "information in HEPEVT event " 00244 << HEPEVT_Wrapper::event_number() 00245 << ". \n I recommend you try " 00246 << "inspecting the event first with " 00247 << "\n\tHEPEVT_Wrapper::check_hepevt_consistency()" 00248 << "\n This warning can be turned off with the " 00249 << "IO_HEPEVT::print_inconsistency_errors switch." 00250 << std::endl; 00251 } 00252 if ( ++mother > HEPEVT_Wrapper::last_parent(i) ) mother = 0; 00253 } 00254 } 00255 00256 void IO_HEPEVT::build_end_vertex 00257 ( int i, std::vector<HepMC::GenParticle*>& hepevt_particle, GenEvent* evt ) 00258 { 00262 // Identical steps as for build_production_vertex 00263 GenParticle* p = hepevt_particle[i]; 00264 // a. 00265 int daughter = HEPEVT_Wrapper::first_child(i); 00266 GenVertex* end_vtx = p->end_vertex(); 00267 while ( !end_vtx && daughter > 0 ) { 00268 end_vtx = hepevt_particle[daughter]->production_vertex(); 00269 if ( end_vtx ) end_vtx->add_particle_in( p ); 00270 if ( ++daughter > HEPEVT_Wrapper::last_child(i) ) daughter = 0; 00271 } 00272 // b. (different from 3c. because HEPEVT particle can not know its 00273 // decay position ) 00274 if ( !end_vtx && HEPEVT_Wrapper::number_children(i)>0 ) { 00275 end_vtx = new GenVertex(); 00276 end_vtx->add_particle_in( p ); 00277 evt->add_vertex( end_vtx ); 00278 } 00279 // c+d. loop over daughters to make sure their production vertices 00280 // point back to the current vertex. 00281 // We get the vertex position from the daughter as well. 00282 daughter = HEPEVT_Wrapper::first_child(i); 00283 while ( end_vtx && daughter > 0 ) { 00284 if ( !hepevt_particle[daughter]->production_vertex() ) { 00285 // if end vertex of the mother isn't specified, do it now 00286 end_vtx->add_particle_out( hepevt_particle[daughter] ); 00287 // 00288 // 2001-03-29 M.Dobbs, fill vertex the position. 00289 if ( end_vtx->position()==FourVector(0,0,0,0) ) { 00290 FourVector prod_pos( HEPEVT_Wrapper::x(daughter), 00291 HEPEVT_Wrapper::y(daughter), 00292 HEPEVT_Wrapper::z(daughter), 00293 HEPEVT_Wrapper::t(daughter) 00294 ); 00295 if ( prod_pos != FourVector(0,0,0,0) ) { 00296 end_vtx->set_position( prod_pos ); 00297 } 00298 } 00299 } else if (hepevt_particle[daughter]->production_vertex() 00300 != end_vtx){ 00301 // problem scenario --- the daughter already has a prod 00302 // vertex which differs from the mother's end 00303 // vertex. This means there is internal 00304 // inconsistency in the HEPEVT event record. Print an 00305 // error 00306 if ( m_print_inconsistency_errors ) std::cerr 00307 << "HepMC::IO_HEPEVT: inconsistent mother/daugher " 00308 << "information in HEPEVT event " 00309 << HEPEVT_Wrapper::event_number() 00310 << ". \n I recommend you try " 00311 << "inspecting the event first with " 00312 << "\n\tHEPEVT_Wrapper::check_hepevt_consistency()" 00313 << "\n This warning can be turned off with the " 00314 << "IO_HEPEVT::print_inconsistency_errors switch." 00315 << std::endl; 00316 } 00317 if ( ++daughter > HEPEVT_Wrapper::last_child(i) ) daughter = 0; 00318 } 00319 if ( !p->end_vertex() && !p->production_vertex() ) { 00320 // Added 2001-11-04, to try and handle Isajet problems. 00321 build_production_vertex( i, hepevt_particle, evt ); 00322 } 00323 } 00324 00325 GenParticle* IO_HEPEVT::build_particle( int index ) { 00327 // 00328 GenParticle* p 00329 = new GenParticle( FourVector( HEPEVT_Wrapper::px(index), 00330 HEPEVT_Wrapper::py(index), 00331 HEPEVT_Wrapper::pz(index), 00332 HEPEVT_Wrapper::e(index) ), 00333 HEPEVT_Wrapper::id(index), 00334 HEPEVT_Wrapper::status(index) ); 00335 p->setGeneratedMass( HEPEVT_Wrapper::m(index) ); 00336 p->suggest_barcode( index ); 00337 return p; 00338 } 00339 00340 int IO_HEPEVT::find_in_map( const std::map<HepMC::GenParticle*,int>& m, 00341 GenParticle* p) const { 00342 std::map<GenParticle*,int>::const_iterator iter = m.find(p); 00343 if ( iter == m.end() ) return 0; 00344 return iter->second; 00345 } 00346 00347 } // HepMC 00348 00349 00350