HepMC Reference Documentation

HepMC

GenEventStreamIO.cc

Go to the documentation of this file.
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

Generated on Thu Jan 7 13:10:15 2010 for HepMC by  doxygen 1.4.7