![]() |
HepMC Reference DocumentationHepMC |
00001 //-------------------------------------------------------------------------- 00002 // 00003 // GenEventStreamIO.cc 00004 // Author: Lynn Garren 00005 // 00006 // Implement operator >> and operator << 00007 // 00008 // ---------------------------------------------------------------------- 00009 00010 #include <iostream> 00011 #include <ostream> 00012 #include <istream> 00013 #include <sstream> 00014 00015 #include "HepMC/GenEvent.h" 00016 #include "HepMC/GenCrossSection.h" 00017 #include "HepMC/StreamInfo.h" 00018 #include "HepMC/StreamHelpers.h" 00019 #include "HepMC/Version.h" 00020 #include "HepMC/IO_Exception.h" 00021 00022 namespace HepMC { 00023 00024 // ------------------------- local methods ---------------- 00025 00029 void HepMCStreamCallback(std::ios_base::event e, std::ios_base& b, int i) 00030 { 00031 // only clean up if the stream object is going away. 00032 if(i!=0 && e!= std::ios_base::erase_event) return; 00033 00034 // retrieve the pointer to the object 00035 StreamInfo* hd = (StreamInfo*)b.pword(i); 00036 b.pword(i) = 0; 00037 b.iword(i) = 0; 00038 #ifdef HEPMC_DEBUG 00039 // the following line is just for sanity checking 00040 if(hd) std::cerr << "deleted StreamInfo " << hd->stream_id() << "\n"; 00041 #endif 00042 delete hd; 00043 } 00044 00045 // ------------------------- iomanip ---------------- 00046 00050 template <class IO> 00051 StreamInfo& get_stream_info(IO& iost) 00052 { 00053 if(iost.iword(0) == 0) 00054 { 00055 // make sure we add the callback if this is the first time through 00056 iost.iword(0)=1; 00057 iost.register_callback(&HepMCStreamCallback, 0); 00058 // this is our special "context" record. 00059 // there is one of these at the head of each IO block. 00060 // allocate room for a StreamInfo in the userdata area 00061 iost.pword(0) = new StreamInfo; 00062 #ifdef HEPMC_DEBUG 00063 // the following line is just for sanity checking 00064 std::cerr << "created StreamInfo " << ((StreamInfo*)iost.pword(0))->stream_id() << "\n"; 00065 #endif 00066 } 00067 return *(StreamInfo*)iost.pword(0); 00068 } 00069 00070 // ------------------------- GenEvent member functions ---------------- 00071 00072 std::ostream& GenEvent::write( std::ostream& os ) 00073 { 00075 00076 // 00077 StreamInfo & info = get_stream_info(os); 00078 // 00079 // if this is the first event, set precision 00080 if ( !info.finished_first_event() ) { 00081 // precision 16 (# digits following decimal point) is the minimum that 00082 // will capture the full information stored in a double 00083 // However, we let the user set precision, since that is the expected functionality 00084 // we use decimal to store integers, because it is smaller than hex! 00085 os.setf(std::ios::dec,std::ios::basefield); 00086 os.setf(std::ios::scientific,std::ios::floatfield); 00087 // 00088 info.set_finished_first_event(true); 00089 } 00090 // 00091 // output the event data including the number of primary vertices 00092 // and the total number of vertices 00093 //std::vector<long> random_states = random_states(); 00094 os << 'E'; 00095 detail::output( os, event_number() ); 00096 detail::output( os, mpi() ); 00097 detail::output( os, event_scale() ); 00098 detail::output( os, alphaQCD() ); 00099 detail::output( os, alphaQED() ); 00100 detail::output( os, signal_process_id() ); 00101 detail::output( os, ( signal_process_vertex() ? 00102 signal_process_vertex()->barcode() : 0 ) ); 00103 detail::output( os, vertices_size() ); // total number of vertices. 00104 write_beam_particles( os, beam_particles() ); 00105 // random state 00106 detail::output( os, (int)m_random_states.size() ); 00107 for ( std::vector<long>::iterator rs = m_random_states.begin(); 00108 rs != m_random_states.end(); ++rs ) { 00109 detail::output( os, *rs ); 00110 } 00111 // weights 00112 os << ' ' << (int)weights().size() ; 00113 for ( WeightContainer::const_iterator w = weights().begin(); 00114 w != weights().end(); ++w ) { 00115 detail::output( os, *w ); 00116 } 00117 detail::output( os,'\n'); 00118 // 00119 // Units 00120 os << "U " << name(momentum_unit()); 00121 os << " " << name(length_unit()); 00122 detail::output( os,'\n'); 00123 // 00124 // write GenCrossSection if it has been set 00125 if( m_cross_section ) m_cross_section->write(os); 00126 // 00127 os << heavy_ion() ; 00128 os << pdf_info() ; 00129 // 00130 // Output all of the vertices - note there is no real order. 00131 for ( GenEvent::vertex_const_iterator v = vertices_begin(); 00132 v != vertices_end(); ++v ) { 00133 write_vertex(os, *v); 00134 } 00135 return os; 00136 } 00137 00138 std::istream& GenEvent::read( std::istream& is ) 00139 { 00141 // 00142 StreamInfo & info = get_stream_info(is); 00143 clear(); 00144 // 00145 // search for event listing key before first event only. 00146 if ( !info.finished_first_event() ) { 00147 // 00148 find_file_type(is); 00149 info.set_finished_first_event(true); 00150 } 00151 // 00152 // make sure the stream is good 00153 if ( !is ) { 00154 std::cerr << "streaming input: end of stream found " 00155 << "setting badbit." << std::endl; 00156 is.clear(std::ios::badbit); 00157 return is; 00158 } 00159 00160 // 00161 // test to be sure the next entry is of type "E" then ignore it 00162 if ( is.peek()!='E' ) { 00163 // if the E is not the next entry, then check to see if it is 00164 // the end event listing key - if yes, search for another start key 00165 int ioendtype; 00166 find_end_key(is,ioendtype); 00167 if ( ioendtype == info.io_type() ) { 00168 find_file_type(is); 00169 // are we at the end of the file? 00170 if( !is ) return is; 00171 } else if ( ioendtype > 0 ) { 00172 std::cerr << "streaming input: end key does not match start key " 00173 << "setting badbit." << std::endl; 00174 is.clear(std::ios::badbit); 00175 return is; 00176 } else if ( !info.has_key() ) { 00177 find_file_type(is); 00178 // are we at the end of the file? 00179 if( !is ) return is; 00180 } else { 00181 std::cerr << "streaming input: end key not found " 00182 << "setting badbit." << std::endl; 00183 is.clear(std::ios::badbit); 00184 return is; 00185 } 00186 } 00187 // get the event line 00188 std::string line; 00189 std::getline(is,line); 00190 std::istringstream iline(line); 00191 std::string firstc; 00192 iline >> firstc; 00193 // 00194 // read values into temp variables, then fill GenEvent 00195 int event_number = 0, signal_process_id = 0, signal_process_vertex = 0, 00196 num_vertices = 0, random_states_size = 0, weights_size = 0, 00197 nmpi = -1, bp1 = 0, bp2 = 0; 00198 double eventScale = 0, alpha_qcd = 0, alpha_qed = 0; 00199 iline >> event_number; 00200 if(!iline) detail::find_event_end( is ); 00201 if( info.io_type() == gen || info.io_type() == extascii ) { 00202 iline >> nmpi; 00203 if(!iline) detail::find_event_end( is ); 00204 set_mpi( nmpi ); 00205 } 00206 iline >> eventScale ; 00207 if(!iline) detail::find_event_end( is ); 00208 iline >> alpha_qcd ; 00209 if(!iline) detail::find_event_end( is ); 00210 iline >> alpha_qed; 00211 if(!iline) detail::find_event_end( is ); 00212 iline >> signal_process_id ; 00213 if(!iline) detail::find_event_end( is ); 00214 iline >> signal_process_vertex; 00215 if(!iline) detail::find_event_end( is ); 00216 iline >> num_vertices; 00217 if(!iline) detail::find_event_end( is ); 00218 if( info.io_type() == gen || info.io_type() == extascii ) { 00219 iline >> bp1 ; 00220 if(!iline) detail::find_event_end( is ); 00221 iline >> bp2; 00222 if(!iline) detail::find_event_end( is ); 00223 } 00224 iline >> random_states_size; 00225 if(!iline) detail::find_event_end( is ); 00226 std::vector<long> random_states(random_states_size); 00227 for ( int i = 0; i < random_states_size; ++i ) { 00228 iline >> random_states[i]; 00229 if(!iline) detail::find_event_end( is ); 00230 } 00231 iline >> weights_size; 00232 if(!iline) detail::find_event_end( is ); 00233 WeightContainer weights(weights_size); 00234 for ( int ii = 0; ii < weights_size; ++ii ) { 00235 iline >> weights[ii]; 00236 if(!iline) detail::find_event_end( is ); 00237 } 00238 // 00239 // fill signal_process_id, event_number, weights, random_states, etc. 00240 set_signal_process_id( signal_process_id ); 00241 set_event_number( event_number ); 00242 m_weights = weights; 00243 set_random_states( random_states ); 00244 set_event_scale( eventScale ); 00245 set_alphaQCD( alpha_qcd ); 00246 set_alphaQED( alpha_qed ); 00247 if( info.io_type() == gen ) { 00248 // get unit information if it exists 00249 read_units( is ); 00250 } 00251 // check to see if we have a GenCrossSection line 00252 if ( is.peek()=='C' ) { 00253 // create cross section 00254 GenCrossSection* xs = new GenCrossSection(); 00255 // check for invalid data 00256 try { 00257 // read the line 00258 xs->read(is); 00259 } 00260 catch (IO_Exception& e) { 00261 detail::find_event_end( is ); 00262 } 00263 if(xs->is_set()) { 00264 set_cross_section( *xs ); 00265 } else { 00266 delete xs; 00267 xs = 0; 00268 } 00269 } 00270 if( info.io_type() == gen || info.io_type() == extascii ) { 00271 // get HeavyIon and PdfInfo 00272 HeavyIon* ion = new HeavyIon(); 00273 // check for invalid data 00274 try { 00275 is >> ion; 00276 } 00277 catch (IO_Exception& e) { 00278 detail::find_event_end( is ); 00279 } 00280 if(ion->is_valid()) { 00281 set_heavy_ion( *ion ); 00282 } else { 00283 delete ion; 00284 ion = 0; 00285 } 00286 PdfInfo* pdf = new PdfInfo(); 00287 // check for invalid data 00288 try { 00289 is >> pdf; 00290 } 00291 catch (IO_Exception& e) { 00292 detail::find_event_end( is ); 00293 } 00294 if(pdf->is_valid()) { 00295 set_pdf_info( *pdf ); 00296 } else { 00297 delete pdf; 00298 pdf = 0; 00299 } 00300 } 00301 // 00302 // the end vertices of the particles are not connected until 00303 // after the event is read --- we store the values in a map until then 00304 TempParticleMap particle_to_end_vertex; 00305 // 00306 // read in the vertices 00307 for ( int iii = 1; iii <= num_vertices; ++iii ) { 00308 GenVertex* v = new GenVertex(); 00309 detail::read_vertex(is,particle_to_end_vertex,v); 00310 add_vertex( v ); 00311 } 00312 // set the signal process vertex 00313 if ( signal_process_vertex ) { 00314 set_signal_process_vertex( 00315 barcode_to_vertex(signal_process_vertex) ); 00316 } 00317 // 00318 // last connect particles to their end vertices 00319 GenParticle* beam1(0); 00320 GenParticle* beam2(0); 00321 for ( std::map<int,GenParticle*>::iterator pmap 00322 = particle_to_end_vertex.order_begin(); 00323 pmap != particle_to_end_vertex.order_end(); ++pmap ) { 00324 GenParticle* p = pmap->second; 00325 int vtx = particle_to_end_vertex.end_vertex( p ); 00326 GenVertex* itsDecayVtx = barcode_to_vertex(vtx); 00327 if ( itsDecayVtx ) itsDecayVtx->add_particle_in( p ); 00328 else { 00329 std::cerr << "read_io_genevent: ERROR particle points" 00330 << " to null end vertex. " <<std::endl; 00331 } 00332 // also look for the beam particles 00333 if( p->barcode() == bp1 ) beam1 = p; 00334 if( p->barcode() == bp2 ) beam2 = p; 00335 } 00336 set_beam_particles(beam1,beam2); 00337 return is; 00338 } 00339 00340 // ------------------------- operator << and operator >> ---------------- 00341 00342 std::ostream & operator << (std::ostream & os, GenEvent & evt) 00343 { 00345 evt.write(os); 00346 return os; 00347 } 00348 00349 std::istream & operator >> (std::istream & is, GenEvent & evt) 00350 { 00351 evt.read(is); 00352 return is; 00353 } 00354 00355 // ------------------------- set units ---------------- 00356 00357 std::istream & set_input_units(std::istream & is, 00358 Units::MomentumUnit mom, 00359 Units::LengthUnit len ) 00360 { 00361 // 00362 StreamInfo & info = get_stream_info(is); 00363 info.use_input_units( mom, len ); 00364 return is; 00365 } 00366 00367 // ------------------------- begin and end block lines ---------------- 00368 00369 std::ostream & write_HepMC_IO_block_begin(std::ostream & os ) 00370 { 00371 // 00372 StreamInfo & info = get_stream_info(os); 00373 00374 if( !info.finished_first_event() ) { 00375 os << "\n" << "HepMC::Version " << versionName(); 00376 os << "\n"; 00377 os << info.IO_GenEvent_Key() << "\n"; 00378 } 00379 return os; 00380 } 00381 00382 std::ostream & write_HepMC_IO_block_end(std::ostream & os ) 00383 { 00384 // 00385 StreamInfo & info = get_stream_info(os); 00386 00387 if( info.finished_first_event() ) { 00388 os << info.IO_GenEvent_End() << "\n"; 00389 os << std::flush; 00390 } 00391 return os; 00392 } 00393 00394 std::istream & GenEvent::read_units( std::istream & is ) 00395 { 00396 // 00397 if ( !is ) { 00398 std::cerr << "StreamHelpers read_units setting badbit." << std::endl; 00399 is.clear(std::ios::badbit); 00400 return is; 00401 } 00402 // 00403 StreamInfo & info = get_stream_info(is); 00404 // test to be sure the next entry is of type "U" then ignore it 00405 // if we have no units, this is not an error 00406 // releases prior to 2.04.00 did not write unit information 00407 if ( is.peek() !='U') { 00408 use_units( info.io_momentum_unit(), 00409 info.io_position_unit() ); 00410 return is; 00411 } 00412 is.ignore(); // ignore the first character in the line 00413 std::string mom, pos; 00414 is >> mom >> pos; 00415 is.ignore(1); // eat the extra whitespace 00416 use_units(mom,pos); 00417 // 00418 return is; 00419 } 00420 00421 std::istream & GenEvent::find_file_type( std::istream & istr ) 00422 { 00423 // 00424 // make sure the stream is good 00425 if ( !istr ) return istr; 00426 00427 // 00428 StreamInfo & info = get_stream_info(istr); 00429 00430 // if there is no input block line, then we assume this stream 00431 // is in the IO_GenEvent format 00432 if ( istr.peek()=='E' ) { 00433 info.set_io_type( gen ); 00434 info.set_has_key(false); 00435 return istr; 00436 } 00437 00438 std::string line; 00439 while ( std::getline(istr,line) ) { 00440 // 00441 // search for event listing key before first event only. 00442 // 00443 if( line == info.IO_GenEvent_Key() ) { 00444 info.set_io_type( gen ); 00445 info.set_has_key(true); 00446 return istr; 00447 } else if( line == info.IO_Ascii_Key() ) { 00448 info.set_io_type( ascii ); 00449 info.set_has_key(true); 00450 return istr; 00451 } else if( line == info.IO_ExtendedAscii_Key() ) { 00452 info.set_io_type( extascii ); 00453 info.set_has_key(true); 00454 return istr; 00455 } else if( line == info.IO_Ascii_PDT_Key() ) { 00456 info.set_io_type( ascii_pdt ); 00457 info.set_has_key(true); 00458 return istr; 00459 } else if( line == info.IO_ExtendedAscii_PDT_Key() ) { 00460 info.set_io_type( extascii_pdt ); 00461 info.set_has_key(true); 00462 return istr; 00463 } 00464 } 00465 info.set_io_type( 0 ); 00466 info.set_has_key(false); 00467 return istr; 00468 } 00469 00470 std::istream & GenEvent::find_end_key( std::istream & istr, int & iotype ) 00471 { 00472 iotype = 0; 00473 // peek at the first character before proceeding 00474 if( istr.peek()!='H' ) return istr; 00475 // 00476 // we only check the next line 00477 std::string line; 00478 std::getline(istr,line); 00479 // 00480 StreamInfo & info = get_stream_info(istr); 00481 // 00482 // check to see if this is an end key 00483 if( line == info.IO_GenEvent_End() ) { 00484 iotype = gen; 00485 } else if( line == info.IO_Ascii_End() ) { 00486 iotype = ascii; 00487 } else if( line == info.IO_ExtendedAscii_End() ) { 00488 iotype = extascii; 00489 } else if( line == info.IO_Ascii_PDT_End() ) { 00490 iotype = ascii_pdt; 00491 } else if( line == info.IO_ExtendedAscii_PDT_End() ) { 00492 iotype = extascii_pdt; 00493 } 00494 if( iotype != 0 && info.io_type() != iotype ) { 00495 std::cerr << "GenEvent::find_end_key: iotype keys have changed" << std::endl; 00496 } else { 00497 return istr; 00498 } 00499 // 00500 // if we get here, then something has gotten badly confused 00501 std::cerr << "GenEvent::find_end_key: MALFORMED INPUT" << std::endl; 00502 istr.clear(std::ios::badbit); 00503 return istr; 00504 } 00505 00506 std::ostream & establish_output_stream_info( std::ostream & os ) 00507 { 00508 StreamInfo & info = get_stream_info(os); 00509 if ( !info.finished_first_event() ) { 00510 // precision 16 (# digits following decimal point) is the minimum that 00511 // will capture the full information stored in a double 00512 os.precision(16); 00513 // we use decimal to store integers, because it is smaller than hex! 00514 os.setf(std::ios::dec,std::ios::basefield); 00515 os.setf(std::ios::scientific,std::ios::floatfield); 00516 } 00517 return os; 00518 } 00519 00520 std::istream & establish_input_stream_info( std::istream & is ) 00521 { 00522 StreamInfo & info = get_stream_info(is); 00523 if ( !info.finished_first_event() ) { 00524 // precision 16 (# digits following decimal point) is the minimum that 00525 // will capture the full information stored in a double 00526 is.precision(16); 00527 // we use decimal to store integers, because it is smaller than hex! 00528 is.setf(std::ios::dec,std::ios::basefield); 00529 is.setf(std::ios::scientific,std::ios::floatfield); 00530 } 00531 return is; 00532 } 00533 00534 00535 // ------------------------- helper functions ---------------- 00536 00537 namespace detail { 00538 00539 // The functions defined here need to use get_stream_info 00540 00541 std::istream & read_particle( std::istream & is, 00542 TempParticleMap & particle_to_end_vertex, 00543 GenParticle * p ) 00544 { 00545 // get the next line 00546 std::string line; 00547 std::getline(is,line); 00548 std::istringstream iline(line); 00549 std::string firstc; 00550 iline >> firstc; 00551 if( firstc != "P" ) { 00552 std::cerr << "StreamHelpers::detail::read_particle invalid line type: " 00553 << firstc << std::endl; 00554 std::cerr << "StreamHelpers::detail::read_particle setting badbit." 00555 << std::endl; 00556 is.clear(std::ios::badbit); 00557 return is; 00558 } 00559 // 00560 StreamInfo & info = get_stream_info(is); 00561 // 00562 // declare variables to be read in to, and read everything except flow 00563 double px = 0., py = 0., pz = 0., e = 0., m = 0., theta = 0., phi = 0.; 00564 int bar_code = 0, id = 0, status = 0, end_vtx_code = 0, flow_size = 0; 00565 // check that the input stream is still OK after reading item 00566 iline >> bar_code ; 00567 if(!iline) detail::find_event_end( is ); 00568 iline >> id ; 00569 if(!iline) detail::find_event_end( is ); 00570 iline >> px ; 00571 if(!iline) detail::find_event_end( is ); 00572 iline >> py ; 00573 if(!iline) detail::find_event_end( is ); 00574 iline >> pz ; 00575 if(!iline) detail::find_event_end( is ); 00576 iline >> e ; 00577 if(!iline) detail::find_event_end( is ); 00578 if( info.io_type() != ascii ) { 00579 iline >> m ; 00580 if(!iline) detail::find_event_end( is ); 00581 } 00582 iline >> status ; 00583 if(!iline) detail::find_event_end( is ); 00584 iline >> theta ; 00585 if(!iline) detail::find_event_end( is ); 00586 iline >> phi ; 00587 if(!iline) detail::find_event_end( is ); 00588 iline >> end_vtx_code ; 00589 if(!iline) detail::find_event_end( is ); 00590 iline >> flow_size; 00591 if(!iline) detail::find_event_end( is ); 00592 // 00593 // read flow patterns if any exist 00594 Flow flow; 00595 int code_index, code; 00596 for ( int i = 1; i <= flow_size; ++i ) { 00597 iline >> code_index >> code; 00598 if(!iline) detail::find_event_end( is ); 00599 flow.set_icode( code_index,code); 00600 } 00601 p->set_momentum( FourVector(px,py,pz,e) ); 00602 p->set_pdg_id( id ); 00603 p->set_status( status ); 00604 p->set_flow( flow ); 00605 p->set_polarization( Polarization(theta,phi) ); 00606 if( info.io_type() == ascii ) { 00607 p->set_generated_mass( p->momentum().m() ); 00608 } else { 00609 p->set_generated_mass( m ); 00610 } 00611 p->suggest_barcode( bar_code ); 00612 // 00613 // all particles are connected to their end vertex separately 00614 // after all particles and vertices have been created - so we keep 00615 // a map of all particles that have end vertices 00616 if ( end_vtx_code != 0 ) { 00617 particle_to_end_vertex.addEndParticle(p,end_vtx_code); 00618 } 00619 return is; 00620 } 00621 00622 std::istream & read_units( std::istream & is, GenEvent & evt ) 00623 { 00624 // 00625 if ( !is ) { 00626 std::cerr << "StreamHelpers read_units setting badbit." << std::endl; 00627 is.clear(std::ios::badbit); 00628 return is; 00629 } 00630 // 00631 StreamInfo & info = get_stream_info(is); 00632 // test to be sure the next entry is of type "U" then ignore it 00633 // if we have no units, this is not an error 00634 // releases prior to 2.04.00 did not write unit information 00635 if ( is.peek() !='U') { 00636 evt.use_units( info.io_momentum_unit(), 00637 info.io_position_unit() ); 00638 return is; 00639 } 00640 is.ignore(); // ignore the first character in the line 00641 std::string mom, pos; 00642 is >> mom >> pos; 00643 is.ignore(1); // eat the extra whitespace 00644 evt.use_units(mom,pos); 00645 // 00646 return is; 00647 } 00648 00649 std::ostream & establish_output_stream_info( std::ostream & os ) 00650 { 00651 StreamInfo & info = get_stream_info(os); 00652 if ( !info.finished_first_event() ) { 00653 // precision 16 (# digits following decimal point) is the minimum that 00654 // will capture the full information stored in a double 00655 os.precision(16); 00656 // we use decimal to store integers, because it is smaller than hex! 00657 os.setf(std::ios::dec,std::ios::basefield); 00658 os.setf(std::ios::scientific,std::ios::floatfield); 00659 } 00660 return os; 00661 } 00662 00663 std::istream & establish_input_stream_info( std::istream & is ) 00664 { 00665 StreamInfo & info = get_stream_info(is); 00666 if ( !info.finished_first_event() ) { 00667 // precision 16 (# digits following decimal point) is the minimum that 00668 // will capture the full information stored in a double 00669 is.precision(16); 00670 // we use decimal to store integers, because it is smaller than hex! 00671 is.setf(std::ios::dec,std::ios::basefield); 00672 is.setf(std::ios::scientific,std::ios::floatfield); 00673 } 00674 return is; 00675 } 00676 00677 } // detail 00678 00679 } // HepMC