CMS 3D CMS Logo

/afs/cern.ch/work/a/aaltunda/public/www/CMSSW_6_2_7/src/GeneratorInterface/ReggeGribovPartonMCInterface/src/IO_EPOS.cc

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