HepMC Reference Documentation

HepMC

IO_Ascii.cc

Go to the documentation of this file.
00001 //--------------------------------------------------------------------------
00002 
00004 // Matt.Dobbs@Cern.CH, January 2000
00005 // event input/output in ascii format for machine reading
00007 
00008 #include "HepMC/IO_Ascii.h"
00009 #include "HepMC/GenEvent.h"
00010 #include "HepMC/ParticleDataTable.h"
00011 #include "HepMC/Version.h"
00012 
00013 namespace HepMC {
00014 
00015     IO_Ascii::IO_Ascii( const char* filename, std::ios::openmode mode ) 
00016         : m_mode(mode), m_file(filename, mode), m_finished_first_event_io(0) 
00017     {
00018         if ( (m_mode&std::ios::out && m_mode&std::ios::in) ||
00019              (m_mode&std::ios::app && m_mode&std::ios::in) ) {
00020             std::cerr << "IO_Ascii::IO_Ascii Error, open of file requested "
00021                       << "of input AND output type. Not allowed. Closing file."
00022                       << std::endl;
00023             m_file.close();
00024             return;
00025         }
00026         // precision 16 (# digits following decimal point) is the minimum that
00027         //  will capture the full information stored in a double
00028         m_file.precision(16);
00029         // we use decimal to store integers, because it is smaller than hex!
00030         m_file.setf(std::ios::dec,std::ios::basefield);
00031         m_file.setf(std::ios::scientific,std::ios::floatfield);
00032     }
00033 
00034     IO_Ascii::~IO_Ascii() {
00035         write_end_listing();
00036         m_file.close();
00037     }
00038 
00039     void IO_Ascii::print( std::ostream& ostr ) const { 
00040         ostr << "IO_Ascii: unformated ascii file IO for machine reading.\n" 
00041              << "\tFile openmode: " << m_mode 
00042              << " file state: " << m_file.rdstate()
00043              << " bad:" << (m_file.rdstate()&std::ios::badbit)
00044              << " eof:" << (m_file.rdstate()&std::ios::eofbit)
00045              << " fail:" << (m_file.rdstate()&std::ios::failbit)
00046              << " good:" << (m_file.rdstate()&std::ios::goodbit) << std::endl;
00047     }
00048 
00049     void IO_Ascii::write_event( const GenEvent* evt ) {
00051         //
00052         // check the state of m_file is good, and that it is in output mode
00053         if ( !evt || !m_file ) return;
00054         if ( !m_mode&std::ios::out ) {
00055             std::cerr << "HepMC::IO_Ascii::write_event "
00056                       << " attempt to write to input file." << std::endl;
00057             return;
00058         }
00059         //
00060         // write event listing key before first event only.
00061         if ( !m_finished_first_event_io ) {
00062             m_finished_first_event_io = 1;
00063             m_file << "\n" << "HepMC::Version " << versionName();
00064             m_file << "\n" << "HepMC::IO_Ascii-START_EVENT_LISTING\n";
00065         }
00066         //
00067         // output the event data including the number of primary vertices
00068         //  and the total number of vertices
00069         std::vector<long int> random_states = evt->random_states();
00070         m_file << 'E';
00071         output( evt->event_number() );
00072         output( evt->event_scale() );
00073         output( evt->alphaQCD() );
00074         output( evt->alphaQED() );
00075         output( evt->signal_process_id() );
00076         output(   ( evt->signal_process_vertex() ?
00077                     evt->signal_process_vertex()->barcode() : 0 )   );
00078         output( evt->vertices_size() ); // total number of vertices.
00079         output( (int)random_states.size() );
00080         for ( std::vector<long int>::iterator rs = random_states.begin(); 
00081               rs != random_states.end(); ++rs ) {
00082             output( *rs );
00083         }
00084         output( (int)evt->weights().size() );
00085         for ( WeightContainer::const_iterator w = evt->weights().begin(); 
00086               w != evt->weights().end(); ++w ) {
00087             output( *w );
00088         }
00089         output('\n');
00090         //
00091         // Output all of the vertices - note there is no real order.
00092         for ( GenEvent::vertex_const_iterator v = evt->vertices_begin();
00093               v != evt->vertices_end(); ++v ) {
00094             write_vertex( *v );
00095         }
00096     }
00097 
00098     bool IO_Ascii::fill_next_event( GenEvent* evt ){
00099         //
00100         //
00101         // test that evt pointer is not null
00102         if ( !evt ) {
00103             std::cerr 
00104                 << "IO_Ascii::fill_next_event error - passed null event." 
00105                 << std::endl;
00106             return 0;
00107         }
00108         // check the state of m_file is good, and that it is in input mode
00109         if ( !m_file ) return 0;
00110         if ( !(m_mode&std::ios::in) ) {
00111             std::cerr << "HepMC::IO_Ascii::fill_next_event "
00112                       << " attempt to read from output file." << std::endl;
00113             return 0;
00114         }
00115         //
00116         // search for event listing key before first event only.
00117         //
00118         // skip through the file just after first occurence of the start_key
00119         if ( !m_finished_first_event_io ) {
00120             m_file.seekg( 0 ); // go to position zero in the file.
00121             if (!search_for_key_end( m_file,
00122                                      "HepMC::IO_Ascii-START_EVENT_LISTING\n")){
00123                 std::cerr << "IO_Ascii::fill_next_event start key not found "
00124                           << "setting badbit." << std::endl;
00125                 m_file.clear(std::ios::badbit); 
00126                 return 0;
00127             }
00128             m_finished_first_event_io = 1;
00129         }
00130         //
00131         // test to be sure the next entry is of type "E" then ignore it
00132         if ( !m_file || m_file.peek()!='E' ) { 
00133             // if the E is not the next entry, then check to see if it is
00134             // the end event listing key - if yes, search for another start key
00135             if ( eat_key(m_file, "HepMC::IO_Ascii-END_EVENT_LISTING\n") ) {
00136                 bool search_result = search_for_key_end(m_file,
00137                                       "HepMC::IO_Ascii-START_EVENT_LISTING\n");
00138                 if ( !search_result ) {
00139                     // this is the only case where we set an EOF state
00140                     m_file.clear(std::ios::eofbit);
00141                     return 0;
00142                 }
00143             } else {
00144                 std::cerr << "IO_Ascii::fill_next_event end key not found "
00145                           << "setting badbit." << std::endl;
00146                 m_file.clear(std::ios::badbit); 
00147                 return 0;
00148             }
00149         } 
00150         m_file.ignore();
00151         // read values into temp variables, then create a new GenEvent
00152         int event_number = 0, signal_process_id = 0, signal_process_vertex = 0,
00153             num_vertices = 0, random_states_size = 0, weights_size = 0;
00154         double eventScale = 0, alpha_qcd = 0, alpha_qed = 0;
00155         m_file >> event_number >> eventScale >> alpha_qcd >> alpha_qed
00156                >> signal_process_id >> signal_process_vertex
00157                >> num_vertices >> random_states_size;
00158         std::vector<long int> random_states(random_states_size);
00159         for ( int i = 0; i < random_states_size; ++i ) {
00160             m_file >> random_states[i];
00161         }
00162         m_file >> weights_size;
00163         WeightContainer weights(weights_size);
00164         for ( int ii = 0; ii < weights_size; ++ii ) m_file >> weights[ii];
00165         m_file.ignore(2,'\n');
00166         // 
00167         // fill signal_process_id, event_number, weights, random_states
00168         evt->set_signal_process_id( signal_process_id );
00169         evt->set_event_number( event_number );
00170         evt->weights() = weights;
00171         evt->set_random_states( random_states );
00172         //
00173         // the end vertices of the particles are not connected until
00174         //  after the event is read --- we store the values in a map until then
00175         TempParticleMap particle_to_end_vertex;
00176         //
00177         // read in the vertices
00178         for ( int iii = 1; iii <= num_vertices; ++iii ) {
00179             GenVertex* v = read_vertex(particle_to_end_vertex);
00180             evt->add_vertex( v );
00181         }
00182         // set the signal process vertex
00183         if ( signal_process_vertex ) {
00184             evt->set_signal_process_vertex( 
00185                 evt->barcode_to_vertex(signal_process_vertex) );
00186         }
00187         //
00188         // last connect particles to their end vertices
00189         for ( std::map<int,GenParticle*>::iterator pmap 
00190                   = particle_to_end_vertex.order_begin(); 
00191               pmap != particle_to_end_vertex.order_end(); ++pmap ) {
00192             GenParticle* p =  pmap->second;
00193             int vtx = particle_to_end_vertex.end_vertex( p );
00194             GenVertex* itsDecayVtx = evt->barcode_to_vertex(vtx);
00195             if ( itsDecayVtx ) itsDecayVtx->add_particle_in( p );
00196             else {
00197                 std::cerr << "IO_Ascii::fill_next_event ERROR particle points"
00198                           << "\n to null end vertex. " <<std::endl;
00199             }
00200         }
00201         return 1;
00202     }
00203 
00204     void IO_Ascii::write_comment( const std::string comment ) {
00205         // check the state of m_file is good, and that it is in output mode
00206         if ( !m_file ) return;
00207         if ( !m_mode&std::ios::out ) {
00208             std::cerr << "HepMC::IO_Ascii::write_particle_data_table "
00209                       << " attempt to write to input file." << std::endl;
00210             return;
00211         }
00212         // write end of event listing key if events have already been written
00213         write_end_listing();
00214         // insert the comment key before the comment
00215         m_file << "\n" << "HepMC::IO_Ascii-COMMENT\n";
00216         m_file << comment << std::endl;
00217     }
00218 
00219     void IO_Ascii::write_particle_data_table( const ParticleDataTable* pdt) {
00220         //
00221         // check the state of m_file is good, and that it is in output mode
00222         if ( !m_file ) return;
00223         if ( !m_mode&std::ios::out ) {
00224             std::cerr << "HepMC::IO_Ascii::write_particle_data_table "
00225                       << " attempt to write to input file." << std::endl;
00226             return;
00227         }
00228         // write end of event listing key if events have already been written
00229         write_end_listing();
00230         //
00231         m_file << "\n" << "HepMC::IO_Ascii-START_PARTICLE_DATA\n";
00232         for ( ParticleDataTable::const_iterator pd = pdt->begin(); 
00233               pd != pdt->end(); pd++ ) {
00234             write_particle_data( pd->second );
00235         }
00236         m_file << "HepMC::IO_Ascii-END_PARTICLE_DATA\n" << std::flush;
00237     }
00238 
00239     bool IO_Ascii::fill_particle_data_table( ParticleDataTable* pdt ) {
00240         //
00241         // test that pdt pointer is not null
00242         if ( !pdt ) {
00243             std::cerr 
00244                 << "IO_Ascii::fill_particle_data_table - passed null table." 
00245                 << std::endl;
00246             return 0;
00247         }
00248         //
00249         // check the state of m_file is good, and that it is in input mode
00250         if ( !m_file ) return 0;
00251         if ( !m_mode&std::ios::in ) {
00252             std::cerr << "HepMC::IO_Ascii::fill_particle_data_table "
00253                       << " attempt to read from output file." << std::endl;
00254             return 0;
00255         }
00256         // position to beginning of file
00257         int initial_file_position = m_file.tellg();
00258         std::ios::iostate initial_state = m_file.rdstate();
00259         m_file.seekg( 0 );
00260         // skip through the file just after first occurence of the start_key
00261         if (!search_for_key_end( m_file,
00262                                  "HepMC::IO_Ascii-START_PARTICLE_DATA\n")) {
00263             m_file.seekg( initial_file_position );
00264             std::cerr << "IO_Ascii::fill_particle_data_table start key not  "
00265                       << "found setting badbit." << std::endl;
00266             m_file.clear(std::ios::badbit); 
00267             return 0;
00268         }
00269         //
00270         pdt->set_description("Read with IO_Ascii");
00271         // 
00272         // read Individual GenParticle data entries
00273         while ( read_particle_data( pdt ) );
00274         //
00275         // eat end_key
00276         if ( !eat_key(m_file,"HepMC::IO_Ascii-END_PARTICLE_DATA\n") ){
00277             std::cerr << "IO_Ascii::fill_particle_data_table end key not  "
00278                       << "found setting badbit." << std::endl;
00279             m_file.clear(std::ios::badbit);
00280         }
00281         // put the file back into its original state and position
00282         m_file.clear( initial_state );
00283         m_file.seekg( initial_file_position );
00284         return 1;
00285     }
00286 
00287     void IO_Ascii::write_vertex( GenVertex* v ) {
00288         // assumes mode has already been checked
00289         if ( !v || !m_file ) {
00290             std::cerr << "IO_Ascii::write_vertex !v||!m_file, "
00291                       << "v="<< v << " setting badbit" << std::endl;
00292             m_file.clear(std::ios::badbit); 
00293             return;
00294         }
00295         // First collect info we need
00296         // count the number of orphan particles going into v
00297         int num_orphans_in = 0;
00298         for ( GenVertex::particles_in_const_iterator p1
00299                   = v->particles_in_const_begin();
00300               p1 != v->particles_in_const_end(); ++p1 ) {
00301             if ( !(*p1)->production_vertex() ) ++num_orphans_in;
00302         }
00303         //
00304         m_file << 'V';
00305         output( v->barcode() ); // v's unique identifier
00306         output( v->id() );
00307         output( v->position().x() );
00308         output( v->position().y() );
00309         output( v->position().z() );
00310         output( v->position().t() );
00311         output( num_orphans_in );
00312         output( (int)v->particles_out_size() );
00313         output( (int)v->weights().size() );
00314         for ( WeightContainer::iterator w = v->weights().begin(); 
00315               w != v->weights().end(); ++w ) {
00316             output( *w );
00317         }
00318         output('\n');
00319         for ( GenVertex::particles_in_const_iterator p2 
00320                   = v->particles_in_const_begin();
00321               p2 != v->particles_in_const_end(); ++p2 ) {
00322             if ( !(*p2)->production_vertex() ) {
00323                 write_particle( *p2 );
00324             }
00325         }
00326         for ( GenVertex::particles_out_const_iterator p3 
00327                   = v->particles_out_const_begin();
00328               p3 != v->particles_out_const_end(); ++p3 ) {
00329             write_particle( *p3 );
00330         }
00331     }
00332 
00333     void IO_Ascii::write_particle( GenParticle* p ) {
00334         // assumes mode has already been checked
00335         if ( !p || !m_file ) {
00336             std::cerr << "IO_Ascii::write_vertex !p||!m_file, "
00337                       << "v="<< p << " setting badbit" << std::endl;
00338             m_file.clear(std::ios::badbit); 
00339             return;
00340         }
00341         m_file << 'P';
00342         output( p->barcode() );
00343         output( p->pdg_id() );
00344         output( p->momentum().px() );
00345         output( p->momentum().py() );
00346         output( p->momentum().pz() );
00347         output( p->momentum().e() );
00348         output( p->status() );
00349         output( p->polarization().theta() );
00350         output( p->polarization().phi() );
00351         // since end_vertex is oftentimes null, this CREATES a null vertex
00352         // in the map
00353         output(   ( p->end_vertex() ? p->end_vertex()->barcode() : 0 )  );
00354         m_file << ' ' << p->flow() << "\n";
00355     }
00356 
00357     void IO_Ascii::write_particle_data( const ParticleData* pdata ) {
00358         // assumes mode has already been checked
00359         if ( !pdata || !m_file ) {
00360             std::cerr << "IO_Ascii::write_vertex !pdata||!m_file, "
00361                       << "pdata="<< pdata << " setting badbit" << std::endl;
00362             m_file.clear(std::ios::badbit); 
00363             return;
00364         }
00365         m_file << 'D';
00366         output( pdata->pdg_id() );
00367         output( pdata->charge() );
00368         output( pdata->mass() );
00369         output( pdata->clifetime() );
00370         output( (int)(pdata->spin()*2.+.1) );
00371         // writes the first 21 characters starting with 0
00372         m_file << " " << pdata->name().substr(0,21) << "\n";
00373     }
00374 
00375     GenVertex* IO_Ascii::read_vertex
00376     ( TempParticleMap& particle_to_end_vertex )
00377     {
00378         // assumes mode has already been checked
00379         //
00380         // test to be sure the next entry is of type "V" then ignore it
00381         if ( !m_file || m_file.peek()!='V' ) {
00382             std::cerr << "IO_Ascii::read_vertex setting badbit." << std::endl;
00383             m_file.clear(std::ios::badbit); 
00384             return 0;
00385         } 
00386         m_file.ignore();
00387         // read values into temp variables, then create a new GenVertex object
00388         int identifier =0, id =0, num_orphans_in =0, 
00389             num_particles_out = 0, weights_size = 0;
00390         double x = 0., y = 0., z = 0., t = 0.; 
00391         m_file >> identifier >> id >> x >> y >> z >> t
00392                >> num_orphans_in >> num_particles_out >> weights_size;
00393         WeightContainer weights(weights_size);
00394         for ( int i1 = 0; i1 < weights_size; ++i1 ) m_file >> weights[i1];
00395         m_file.ignore(2,'\n');
00396         GenVertex* v = new GenVertex( FourVector(x,y,z,t),
00397                                 id, weights);
00398         v->suggest_barcode( identifier );
00399         //
00400         // read and create the associated particles. outgoing particles are
00401         //  added to their production vertices immediately, while incoming
00402         //  particles are added to a map and handles later.
00403         // use a map of barcodes to outgoing particles
00404         for ( int i2 = 1; i2 <= num_orphans_in; ++i2 ) {
00405             read_particle(particle_to_end_vertex);
00406         }
00407         for ( int i3 = 1; i3 <= num_particles_out; ++i3 ) {
00408             v->add_particle_out( read_particle(particle_to_end_vertex) );
00409         }
00410         return v;
00411     }
00412 
00413     GenParticle* IO_Ascii::read_particle(
00414         TempParticleMap& particle_to_end_vertex ){
00415         // assumes mode has already been checked
00416         //
00417         // test to be sure the next entry is of type "P" then ignore it
00418         if ( !m_file || m_file.peek()!='P' ) { 
00419             std::cerr << "IO_Ascii::read_particle setting badbit." 
00420                       << std::endl;
00421             m_file.clear(std::ios::badbit); 
00422             return 0;
00423         } 
00424         m_file.ignore();
00425         //
00426         // declare variables to be read in to, and read everything except flow
00427         double px = 0., py = 0., pz = 0., e = 0., theta = 0., phi = 0.;
00428         int bar_code = 0, id = 0, status = 0, end_vtx_code = 0, flow_size = 0;
00429         m_file >> bar_code >> id >> px >> py >> pz >> e >> status 
00430                >> theta >> phi >> end_vtx_code >> flow_size;
00431         //
00432         // read flow patterns if any exist
00433         Flow flow;
00434         int code_index, code;
00435         for ( int i = 1; i <= flow_size; ++i ) {
00436             m_file >> code_index >> code;
00437             flow.set_icode( code_index,code);
00438         }
00439         m_file.ignore(2,'\n'); // '\n' at end of entry
00440         GenParticle* p = new GenParticle( FourVector(px,py,pz,e), 
00441                                     id, status, flow, 
00442                                     Polarization(theta,phi) );
00443         p->suggest_barcode( bar_code );
00444         //
00445         // all particles are connected to their end vertex separately 
00446         // after all particles and vertices have been created - so we keep
00447         // a map of all particles that have end vertices
00448         if ( end_vtx_code != 0 ) {
00449             particle_to_end_vertex.addEndParticle(p,end_vtx_code);
00450         }
00451         return p;
00452     }
00453 
00454     ParticleData* IO_Ascii::read_particle_data( ParticleDataTable* pdt ) {
00455         // assumes mode has already been checked
00456         //
00457         // test to be sure the next entry is of type "D" then ignore it
00458         if ( !m_file || m_file.peek()!='D' ) return 0;
00459         m_file.ignore();
00460         //
00461         // read values into temp variables then create new ParticleData object
00462         char its_name[22];
00463         int its_id = 0, its_spin = 0;  
00464         double its_charge = 0, its_mass = 0, its_clifetime = 0;
00465         m_file >> its_id >> its_charge >> its_mass 
00466                >> its_clifetime >> its_spin;
00467         m_file.ignore(1); // eat the " "
00468         m_file.getline( its_name, 22, '\n' );
00469         ParticleData* pdata = new ParticleData( its_name, its_id, its_charge, 
00470                                                 its_mass, its_clifetime, 
00471                                                 double(its_spin)/2.);
00472         pdt->insert(pdata);
00473         return pdata;
00474     }
00475 
00476     bool IO_Ascii::write_end_listing() {
00477         if ( m_finished_first_event_io && m_mode&std::ios::out ) {
00478             m_file << "HepMC::IO_Ascii-END_EVENT_LISTING\n" << std::flush;
00479             m_finished_first_event_io = 0;
00480             return 1;
00481         }
00482         return 0;
00483     }
00484 
00485     bool IO_Ascii::search_for_key_end( std::istream& in, const char* key ) {
00489         // 
00490         char c[1];
00491         unsigned int index = 0;
00492         while ( in.get(c[0]) ) {
00493             if ( c[0] == key[index] ) { 
00494                 ++index;
00495             } else { index = 0; }
00496             if ( index == strlen(key) ) return 1;
00497         }
00498         return 0;
00499     }
00500 
00501     bool IO_Ascii::search_for_key_beginning( std::istream& in,
00502                                              const char* key ) {
00504         if ( search_for_key_end( in, key) ) {
00505             int i = strlen(key);
00506             while ( i>=0 ) in.putback(key[i--]); 
00507             return 1; 
00508         } else {
00509             in.putback(EOF);
00510             in.clear();
00511             return 0;
00512         }
00513     }
00514 
00515     bool IO_Ascii::eat_key( std::iostream& in, const char* key ) {
00520         int key_length = strlen(key);
00521         // below is the only way I know of to get a variable length string
00522         //  conforming to ansi standard.
00523         char* c = new char[key_length +1];
00524         int i=0;
00525         // read the stream until get fails (because of EOF), a character
00526         //  doesn't match a character in the string, or all characters in
00527         //  the string have been checked and match.
00528         while ( in.get(c[i]) && c[i]==key[i] && i<key_length ) {
00529             ++i;
00530         }
00531         if ( i == key_length ) {
00532             delete [] c;
00533             return 1;
00534         }
00535         //
00536         // if we get here, then we have eaten the wrong this and we must put it
00537         // back
00538         //---------> non standard code --- probably does not work
00539         while ( i>=0 ) in.putback(c[i--]); 
00540         delete c;
00541         return 0;
00542     }
00543 
00544     int IO_Ascii::find_in_map( const std::map<GenVertex*,int>& m, 
00545                                GenVertex* v ) const {
00546         std::map<GenVertex*,int>::const_iterator iter = m.find(v);
00547         if ( iter == m.end() ) return 0;
00548         return iter->second;
00549     }
00550         
00551 } // HepMC
00552 
00553 
00554 
00555 
00556 
00557 

Generated on Tue Feb 5 13:25:44 2008 for HepMC by  doxygen 1.5.1-3