Gaudi Framework, version v20r2

Generated: 18 Jul 2008

ParticlePropertySvc.cpp

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

Generated at Fri Jul 18 11:59:25 2008 for Gaudi Framework, version v20r2 by Doxygen version 1.5.1 written by Dimitri van Heesch, © 1997-2004