Gaudi Framework, version v20r4

Generated: 8 Jan 2009

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

Generated at Thu Jan 8 17:44:24 2009 for Gaudi Framework, version v20r4 by Doxygen version 1.5.6 written by Dimitri van Heesch, © 1997-2004