Gaudi Framework, version v21r8

Home   Generated: 17 Mar 2010

ParticlePropertySvc.cpp

Go to the documentation of this file.
00001 // $Id: ParticlePropertySvc.cpp,v 1.17 2008/10/27 16:41:33 marcocle Exp $
00002 // ============================================================================
00003 // CVS tag $Name:  $ , version $Revision: 1.17 $
00004 // ============================================================================
00005 //Include files
00006 // ============================================================================
00007 // STD&STL
00008 // ============================================================================
00009 #include <cstdlib>
00010 #include <cstring>
00011 #include <fstream>
00012 // ============================================================================
00013 // GaudiKernel
00014 // ============================================================================
00015 #include "GaudiKernel/SvcFactory.h"
00016 #include "GaudiKernel/ISvcLocator.h"
00017 #include "GaudiKernel/MsgStream.h"
00018 #include "GaudiKernel/ParticleProperty.h"
00019 #include "GaudiKernel/PhysicalConstants.h"
00020 #include "GaudiKernel/IFileAccess.h"
00021 // ============================================================================
00022 //#include "GaudiKernel/ToStream.h"
00023 // ============================================================================
00024 // Local
00025 // ============================================================================
00026 #include "ParticlePropertySvc.h"
00027 
00028 // ============================================================================
00032 DECLARE_SERVICE_FACTORY(ParticlePropertySvc)
00033 // ============================================================================
00045 // ============================================================================
00046 ParticlePropertySvc::ParticlePropertySvc
00047 ( const std::string& name ,
00048   ISvcLocator*       svc  )
00049   : base_class( name, svc )
00050   // the default name of input data file
00051   , m_filename ( "ParticleTable.txt" )
00052   , m_other ()
00053   , m_particles ()
00054   // storages :
00055   , m_vectpp  ()
00056   , m_idmap   ()
00057   , m_namemap ()
00058   , m_stdhepidmap()
00059   , m_pythiaidmap()
00060   //
00061   , m_owned ()
00062   , m_replaced ()
00063   , m_fileAccess (0)
00064 {
00065   // Redefine the default name:
00066   if( NULL != getenv("PARAMFILESROOT") )
00067   {
00068     m_filename  = getenv( "PARAMFILESROOT" ) ;
00069     m_filename += "/data/ParticleTable.txt"  ;
00070   }
00071   //
00072   declareProperty ( "ParticlePropertiesFile" , m_filename  ) ;
00073   declareProperty ( "OtherFiles"             , m_other     ) ;
00074   declareProperty ( "Particles"              , m_particles ) ;
00075 }
00076 // ============================================================================
00078 // ============================================================================
00079 ParticlePropertySvc::~ParticlePropertySvc()
00080 {
00081   for ( Set::iterator i = m_owned.begin(); i != m_owned.end() ; ++i )
00082   { if ( 0 != *i ) { delete *i ; } }
00083 }
00084 // ============================================================================
00086 // ============================================================================
00087 StatusCode ParticlePropertySvc::initialize()
00088 {
00089   StatusCode sc = Service::initialize();
00090   if ( sc.isFailure() ) { return sc ; }
00091 
00092   MsgStream log( msgSvc() , name() ) ;
00093 
00094   sc = setProperties();
00095   if ( sc.isFailure() )
00096   {
00097     log << MSG::ERROR << " Could not set the properties " << endmsg ;
00098     return sc ;
00099   }
00100 
00101 
00102   sc = service("VFSSvc",m_fileAccess);
00103   if ( sc.isFailure() )
00104   {
00105     log << MSG::ERROR << " Cannot retrieve the VFS service " << endmsg ;
00106     return sc ;
00107   }
00108 
00109   sc = parse();
00110   if ( sc.isFailure() )
00111   {
00112     log << MSG::ERROR << " Could not parse the file " << endmsg ;
00113     return sc ;
00114   }
00115   if ( !m_particles.empty() )
00116   {
00117     sc = addParticles () ;
00118     if ( sc.isFailure() )
00119     {
00120       log << MSG::ERROR << " Could not treat particles! " << endmsg ;
00121       return sc ;
00122     }
00123   }
00124   log << MSG::DEBUG << "ParticleProperties parsed successfully" << endmsg;
00125 
00126   log << MSG::DEBUG << "Access properties" << endmsg;
00127   // For debugging purposes print out the size of the internal maps
00128   // particle name as key: all particles in database are present here
00129   log << MSG::DEBUG << "NameMap size =" << m_namemap.size() << endmsg;
00130   // Geant3 ID as key: all particles in database are present here
00131   log << MSG::DEBUG << "GeantID Map size =" << m_idmap.size() << endmsg;
00132   // StdHep ID as key: some particles have no valid StdHep ID
00133   log << MSG::DEBUG << "StdHepID Map size =" << m_stdhepidmap.size()
00134       << endmsg;
00135   // Pythia ID as key: some particles are not defined in Pythia
00136   log << MSG::DEBUG << "PythiaID Map size =" << m_pythiaidmap.size()
00137       << endmsg;
00138 
00139   if ( !m_replaced.empty() )
00140   {
00141     log << MSG::INFO
00142         << "Properties have been redefined for "
00143         << m_replaced.size() << " particles : "
00144         << Gaudi::Utils::toString( m_replaced )
00145         << endmsg ;
00146   }
00147 
00148   return StatusCode::SUCCESS ;
00149 }
00150 // =============================================================================
00152 // =============================================================================
00153 StatusCode ParticlePropertySvc::finalize()
00154 {
00155   if ( !m_other.empty() )
00156   {
00157     MsgStream log( msgSvc() , name() ) ;
00158     log << MSG::INFO
00159         << "Additional Properties have been read from files: "
00160         << Gaudi::Utils::toString ( m_other )
00161         << endmsg ;
00162   }
00163 
00164   if ( !m_replaced.empty() )
00165   {
00166     MsgStream log( msgSvc() , name() ) ;
00167     log << MSG::ALWAYS
00168         << "Properties have been redefined for "
00169         << m_replaced.size() << " particles : "
00170         << Gaudi::Utils::toString( m_replaced )
00171         << endmsg ;
00172   }
00173 
00174   if (m_fileAccess) {
00175     m_fileAccess->release();
00176     m_fileAccess = 0;
00177   }
00178 
00180   return Service::finalize () ;
00181 }
00182 // =============================================================================
00184 // =============================================================================
00185 StatusCode ParticlePropertySvc::push_back
00186 ( const std::string& particle ,
00187   int                geantId  ,
00188   int                jetsetId ,
00189   double             charge   ,
00190   double             mass     ,
00191   double             tlife    ,
00192   const std::string& evtName  ,
00193   int                pythiaId ,
00194   double             maxWidth )
00195 {
00196   ParticleProperty* pp = new ParticleProperty
00197     ( particle , geantId  , jetsetId ,
00198       charge   , mass     , tlife    ,
00199       evtName  , pythiaId , maxWidth ) ;
00200   //
00201   m_owned.insert ( pp ) ;
00202   //
00203   return push_back( pp );
00204 }
00205 // =============================================================================
00207 // =============================================================================
00208 StatusCode ParticlePropertySvc::push_back ( ParticleProperty* pp )
00209 {
00210   if ( 0 == pp ) { return StatusCode::FAILURE ; }
00211   //
00212   { // try to add into Geant(3)ID map
00213     const int ID = pp->geantID() ;
00214     // is this already in the map?
00215     MapID::const_iterator ifind = m_idmap.find( ID ) ;
00216     if ( m_idmap.end() != ifind && 0 != m_idmap[ ID ])
00217     {
00218       diff ( ifind->second , pp ) ;
00219       m_replaced.insert( m_idmap[ ID ]->particle() ) ;
00220     }
00221     // put it into the map
00222     m_idmap[ ID ] = pp ;
00223   }
00224   //
00225   { // try to add into Name map
00226     const std::string& particle = pp->particle() ;
00227     // is this already in the map?
00228     MapName::const_iterator ifind = m_namemap.find( particle ) ;
00229     if ( m_namemap.end() != ifind && 0 != m_namemap[ particle ] )
00230     {
00231       diff ( ifind->second , pp ) ;
00232       m_replaced.insert( m_namemap[ particle ]->particle() ) ;
00233     }
00234     // put it into the map
00235     m_namemap[ particle ] = pp ;
00236   }
00237   //
00238   // add to StdHep map only if StdHep ID different from zero and if
00239   // not Cerenkov (StdHep ID = gamma)
00240   if ( 0 != pp->jetsetID() && "Tcherenkov" != pp->particle() )
00241   { // try to add into StdHepID map
00242     const int ID = pp->jetsetID() ;
00243     // is this already in the map?
00244     MapStdHepID::const_iterator ifind = m_stdhepidmap.find( ID ) ;
00245     if ( m_stdhepidmap.end() != ifind && 0 != m_stdhepidmap[ ID ])
00246     {
00247       diff ( ifind->second , pp ) ;
00248       m_replaced.insert( m_stdhepidmap[ ID ]->particle() ) ;
00249     }
00250     // put it into the map
00251     m_stdhepidmap[ ID ] = pp ;
00252   }
00253   //
00254   // add to Pythia map only if Pythia ID is different from
00255   // zero ( StdHep id is always different from zero in this case )
00256   if ( 0 != pp->pythiaID() &&
00257        0 != pp->jetsetID() &&
00258        "Tcherenkov" != pp->particle() )
00259   { // try to add into PythiaID map
00260     const int ID = pp->pythiaID() ;
00261     // is this already in the map?
00262     MapPythiaID::const_iterator ifind = m_pythiaidmap.find( ID ) ;
00263     if ( m_pythiaidmap.end() != ifind && 0 != m_pythiaidmap[ ID ])
00264     {
00265       diff ( ifind->second , pp ) ;
00266       m_replaced.insert( m_pythiaidmap[ ID ]->particle() ) ;
00267     }
00268     // put it into the map
00269     m_pythiaidmap[ ID ] = pp ;
00270   }
00271   //
00272   return rebuild() ;
00273 }
00274 // =============================================================================
00276 // =============================================================================
00277 namespace
00278 {
00279   template <class MAP>
00280   void _remove_ ( MAP& m , const ParticleProperty* pp )
00281   {
00282     typename MAP::iterator i = m.begin() ;
00283     for ( ; m.end() != i ; ++i ) { if ( i->second == pp ) { break ; } }
00284     if  ( m.end() != i ) { m.erase ( i ) ; }
00285   }
00286 }
00287 // ============================================================================
00288 StatusCode ParticlePropertySvc::erase( const ParticleProperty* pp )
00289 {
00290   if ( 0 == pp ) { return StatusCode::FAILURE ; }
00291 
00292   _remove_ ( m_idmap       , pp ) ;
00293   _remove_ ( m_namemap     , pp ) ;
00294   _remove_ ( m_stdhepidmap , pp ) ;
00295   _remove_ ( m_pythiaidmap , pp ) ;
00296   //
00297   return rebuild() ;
00298 }
00299 // ============================================================================
00301 // ============================================================================
00302 StatusCode ParticlePropertySvc::parse()
00303 {
00304 
00305   // parse "the main" file
00306   StatusCode sc = parse ( m_filename ) ;
00307   if ( sc.isFailure() ) { return sc ; }
00308 
00309   // parse "other" files
00310   for ( Files::const_iterator file = m_other.begin() ;
00311         m_other.end() != file ; ++file )
00312   {
00313     sc = parse ( *file ) ;
00314     if ( sc.isFailure() ) { return sc ; }
00315   }
00316 
00317   // Now check that the file format was consistent with what parser
00318   // expected
00319   if ( m_namemap.size() == 0 )
00320   {
00321     MsgStream log( msgSvc(), name() );
00322     log << MSG::ERROR
00323         << "Format of input file inconsistent with what expected"
00324         << " - Check you are using ParticleData.txt" << endmsg;
00325     return StatusCode::FAILURE;
00326   }
00327 
00328   return sc;
00329 }
00330 // ============================================================================
00331 StatusCode ParticlePropertySvc::parse( const std::string& file )
00332 {
00333   StatusCode sc = StatusCode::FAILURE;
00334 
00335   MsgStream log( msgSvc(), name() );
00336   char line[ 255 ];
00337 
00338   std::auto_ptr<std::istream> infileptr;
00339   if (m_fileAccess) infileptr = m_fileAccess->open(file);
00340 
00341   if ( infileptr.get() == 0 )
00342   {
00343     log << MSG::ERROR << "Unable to open properties file : " << file
00344         << endmsg;
00345     return StatusCode::FAILURE ;
00346   }
00347 
00348   std::istream &infile = *infileptr;
00349   sc = StatusCode::SUCCESS;
00350   log << MSG::INFO
00351       << "Opened particle properties file : " << file << endmsg;
00352 
00353   while( infile )
00354   {
00355     // parse each line of the file (comment lines begin with # in the cdf
00356     // file,
00357     infile.getline( line, 255 );
00358 
00359     if ( line[0] == '#' ) continue;
00360 
00361     std::string par, gid, jid, chg, mas, lif, evt, pyt, mwi ;
00362     char* token = strtok( line, " " );
00363     if ( token ) { par = token; token = strtok( NULL, " " );} else continue;
00364     if ( token ) { gid = token; token = strtok( NULL, " " );} else continue;
00365     if ( token ) { jid = token; token = strtok( NULL, " " );} else continue;
00366     if ( token ) { chg = token; token = strtok( NULL, " " );} else continue;
00367     if ( token ) { mas = token; token = strtok( NULL, " " );} else continue;
00368     if ( token ) { lif = token; token = strtok( NULL, " " );} else continue;
00369     if ( token ) { evt = token; token = strtok( NULL, " " );} else continue;
00370     if ( token ) { pyt = token; token = strtok( NULL, " " );} else continue;
00371     if ( token ) { mwi = token; token = strtok( NULL, " " );} else continue;
00372     if ( token != NULL ) continue;
00373 
00374     // In SICb cdf file mass and lifetime units are GeV and sec, specify it so
00375     // that they are converted to Gaudi units (MeV and ns)
00376     double mass = atof( mas.c_str() ) * Gaudi::Units::GeV;
00377     double tlife = atof( lif.c_str() ) * Gaudi::Units::s;
00378     long   ljid = atoi( jid.c_str() );
00379     long   lgid = atoi( gid.c_str() );
00380     long   lpyt = atoi( pyt.c_str() ) ;
00381     double mW = atof( mwi.c_str() ) * Gaudi::Units::GeV ;
00382 
00383     // Change the particles that do not corresopond to a pdg number
00384     if ( ljid == 0 ) {
00385       ljid = 10000000*lgid;
00386     }
00387 
00388     // add a particle property
00389     sc = push_back( par, lgid, ljid,
00390                     atof( chg.c_str() ), mass, tlife, evt, lpyt, mW ) ;
00391     if ( sc.isFailure() )
00392     {
00393       log << MSG::ERROR
00394           << "Error from ParticlePropertySvc::push_back for particle='"
00395           << par << "'" << endmsg ;
00396     }
00397 
00398   }
00399 
00400   //infile.close();
00401 
00402   return StatusCode::SUCCESS ;
00403 }
00404 // ============================================================================
00410 // ============================================================================
00411 const ParticleProperty*
00412 ParticlePropertySvc::anti ( const ParticleProperty* pp ) const
00413 {
00414   if ( 0 == pp ) { return 0 ; }
00415   const int     ID = pp->pdgID() ;
00416   const int antiID = -1 * ID     ;
00417   for ( const_iterator it = m_vectpp.begin() ; m_vectpp.end() != it ; ++it )
00418   {
00419     const ParticleProperty* ap = *it ;
00420     if ( 0 == ap               ) { continue  ; }                // CONTINUE
00421     if ( antiID == ap->pdgID() ) { return ap ; }                // RETURN
00422   };
00423   //
00424   return pp ;                                                   // RETURN
00425 }
00426 // ============================================================================
00431 // ============================================================================
00432 StatusCode ParticlePropertySvc::setAntiParticles()
00433 {
00434   // initialize particle<-->antiParticle relations
00435   for ( iterator ip = m_vectpp.begin() ; m_vectpp.end() != ip ; ++ip )
00436   {
00437     ParticleProperty* pp = *ip ;
00438     if ( 0 == pp                    ) { continue ; }   // CONTINUE
00439     const ParticleProperty* ap = anti ( pp ) ;
00440     if ( 0 != ap                    ) { pp->setAntiParticle( ap ) ; }
00441   }
00442   return StatusCode::SUCCESS ;
00443 }
00444 // ============================================================================
00446 // ============================================================================
00447 namespace
00448 {
00450   template <class MAP>
00451   void _load_ ( MAP& m , ParticlePropertySvc::Set& result )
00452   {
00453     for ( typename MAP::iterator i = m.begin() ; m.end() != i ; ++i )
00454     { result.insert ( i->second ); }
00455   }
00456 }
00457 // ============================================================================
00458 StatusCode ParticlePropertySvc::rebuild()
00459 {
00460   Set local ;
00461   m_vectpp.clear() ;
00462   m_vectpp.reserve ( m_idmap.size() + 100 ) ;
00463   // load information from maps into the set
00464   _load_ ( m_idmap       , local ) ;
00465   _load_ ( m_namemap     , local ) ;
00466   _load_ ( m_stdhepidmap , local ) ;
00467   _load_ ( m_pythiaidmap , local ) ;
00468   // load information from set to the linear container vector
00469   for ( Set::iterator i = local.begin() ; local.end() != i ; ++i )
00470   { m_vectpp.push_back ( *i ) ; }
00471   return setAntiParticles() ;
00472 }
00473 // ============================================================================
00474 // treat additional particles
00475 // ============================================================================
00476 StatusCode ParticlePropertySvc::addParticles()
00477 {
00478 
00479   MsgStream log ( msgSvc() , name() ) ;
00480   // loop over all "explicit" particles
00481   for ( Particles::const_iterator ip = m_particles.begin() ;
00482         m_particles.end() != ip ; ++ip )
00483   {
00484     const std::string item = *ip ;
00485     std::istringstream input( item ) ;
00486     // get the name
00487     std::string p_name   ;
00488     int         p_geant  ;
00489     int         p_jetset ;
00490     double      p_charge ;
00491     double      p_mass   ;
00492     double      p_ltime  ;
00493     std::string p_evtgen ;
00494     int         p_pythia ;
00495     double      p_maxwid ;
00496     if ( input
00497          >> p_name
00498          >> p_geant
00499          >> p_jetset
00500          >> p_charge
00501          >> p_mass
00502          >> p_ltime
00503          >> p_evtgen
00504          >> p_pythia
00505          >> p_maxwid )
00506     {
00507       log << MSG::ALWAYS
00508           << " Add/Modify the particle: "
00509           << " name='"   << p_name   << "'"
00510           << " geant="   << p_geant
00511           << " jetset="  << p_jetset
00512           << " charge="  << p_charge
00513           << " mass="    << p_mass
00514           << " ltime="   << p_ltime
00515           << " evtgen='" << p_evtgen << "'"
00516           << " pythia="  << p_pythia
00517           << " maxwid="  << p_maxwid << endmsg ;
00518       //
00519       StatusCode sc = push_back
00520         ( p_name                        ,
00521           p_geant                       ,
00522           p_jetset                      ,
00523           p_charge                      ,
00524           p_mass    * Gaudi::Units::GeV ,
00525           p_ltime   * Gaudi::Units::s   ,
00526           p_evtgen                      ,
00527           p_pythia                      ,
00528           p_maxwid  * Gaudi::Units::GeV ) ;
00529       if ( sc.isFailure() ) { return sc ; }                        // RETURN
00530     }
00531     else
00532     {
00533       log << MSG::ERROR
00534           << " could not parse '" << item << "'" << endmsg ;
00535       return StatusCode::FAILURE ;                                 // RETURN
00536     }
00537   }
00538   //
00539   return StatusCode::SUCCESS ;
00540 }
00541 // ============================================================================
00542 bool ParticlePropertySvc::diff
00543 ( const ParticleProperty* o ,
00544   const ParticleProperty* n ,
00545   const MSG::Level        l ) const
00546 {
00547   //
00548   if ( o == n ) { return false ; }
00549   //
00550   MsgStream log ( msgSvc() , name() ) ;
00551   log << l ;
00552   if ( 0 == o || 0 == n  )
00553   {
00554     log << MSG::WARNING << " ParticleProperty* point to NULL" << endmsg ;
00555     return true ;                                                    // RETURN
00556   }
00557   //
00558   bool result = false ;
00559   if ( o -> particle () != n -> particle () )
00560   {
00561     result = true ;
00562     log << " Name:'"  << o -> particle () << "'/'" << n -> particle () << "'" ;
00563   }
00564   if ( o -> geantID  () != n -> geantID  () )
00565   {
00566     result = true ;
00567     log << " G3ID:"   << o -> geantID  () << "/"   << n -> geantID  () << "'" ;
00568   }
00569   if ( o -> pdgID    () != n -> pdgID    () )
00570   {
00571     result = true ;
00572     log << " PDGID:"  << o -> pdgID    () << "/"   << n -> pdgID    () << "'" ;
00573   }
00574   if ( o -> pythiaID () != n -> pythiaID () )
00575   {
00576     result = true ;
00577     log << " PYID:"   << o -> pythiaID () << "/"   << n -> pythiaID () << "'" ;
00578   }
00579   if ( o -> charge   () != n -> charge   () )
00580   {
00581     result = true ;
00582     log << " Q:"      << o -> charge   () << "/"   << n -> charge   () << "'" ;
00583   }
00584   if ( o -> mass     () != n -> mass     () )
00585   {
00586     result = true ;
00587     log << " M:"      << o -> mass     () << "/"   << n -> mass     () << "'" ;
00588   }
00589   if ( o -> lifetime () != n -> lifetime () )
00590   {
00591     result = true ;
00592     log << " T:"      << o -> lifetime () << "/"   << n -> lifetime () << "'" ;
00593   }
00594   if ( o -> evtGenName () != n -> evtGenName () )
00595   {
00596     result = true ;
00597     log << " EvtGen:" << o -> evtGenName () << "/"   << n -> evtGenName () << "'" ;
00598   }
00599   if ( o -> maxWidth () != n -> maxWidth () )
00600   {
00601     result = true ;
00602     log << " WMAX:"   << o -> maxWidth () << "/"   << n -> maxWidth () << "'" ;
00603   }
00604   if ( result ) { log << endmsg ; }
00605   //
00606   return result ;
00607 }
00608 
00609 
00610 
00611 
00612 
00613 // ============================================================================
00614 // The END
00615 // ============================================================================
00616 

Generated at Wed Mar 17 18:06:48 2010 for Gaudi Framework, version v21r8 by Doxygen version 1.5.6 written by Dimitri van Heesch, © 1997-2004