Gaudi Framework, version v22r4

Home   Generated: Fri Sep 2 2011

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 #include "GaudiKernel/System.h"
00022 // ============================================================================
00023 //#include "GaudiKernel/ToStream.h"
00024 // ============================================================================
00025 // Local
00026 // ============================================================================
00027 #include "ParticlePropertySvc.h"
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 {
00066   // Redefine the default name:
00067   if( System::getEnv("PARAMFILESROOT", m_filename) )
00068   {
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 
00362 #ifdef WIN32
00363 // Disable warning
00364 //   C4996: 'strtok': This function or variable may be unsafe.
00365 #pragma warning(disable:4996)
00366 #endif
00367     std::string par, gid, jid, chg, mas, lif, evt, pyt, mwi ;
00368     char* token = strtok( line, " " );
00369     if ( token ) { par = token; token = strtok( NULL, " " );} else continue;
00370     if ( token ) { gid = token; token = strtok( NULL, " " );} else continue;
00371     if ( token ) { jid = token; token = strtok( NULL, " " );} else continue;
00372     if ( token ) { chg = token; token = strtok( NULL, " " );} else continue;
00373     if ( token ) { mas = token; token = strtok( NULL, " " );} else continue;
00374     if ( token ) { lif = token; token = strtok( NULL, " " );} else continue;
00375     if ( token ) { evt = token; token = strtok( NULL, " " );} else continue;
00376     if ( token ) { pyt = token; token = strtok( NULL, " " );} else continue;
00377     if ( token ) { mwi = token; token = strtok( NULL, " " );} else continue;
00378     if ( token != NULL ) continue;
00379 
00380     // In SICb cdf file mass and lifetime units are GeV and sec, specify it so
00381     // that they are converted to Gaudi units (MeV and ns)
00382     double mass = atof( mas.c_str() ) * Gaudi::Units::GeV;
00383     double tlife = atof( lif.c_str() ) * Gaudi::Units::s;
00384     long   ljid = atoi( jid.c_str() );
00385     long   lgid = atoi( gid.c_str() );
00386     long   lpyt = atoi( pyt.c_str() ) ;
00387     double mW = atof( mwi.c_str() ) * Gaudi::Units::GeV ;
00388 
00389     // Change the particles that do not correspond to a pdg number
00390     if ( ljid == 0 ) {
00391       ljid = 10000000*lgid;
00392     }
00393 
00394     // add a particle property
00395     sc = push_back( par, lgid, ljid,
00396                     atof( chg.c_str() ), mass, tlife, evt, lpyt, mW ) ;
00397     if ( sc.isFailure() )
00398     {
00399       log << MSG::ERROR
00400           << "Error from ParticlePropertySvc::push_back for particle='"
00401           << par << "'" << endmsg ;
00402     }
00403 
00404   }
00405 
00406   //infile.close();
00407 
00408   return StatusCode::SUCCESS ;
00409 }
00410 // ============================================================================
00416 // ============================================================================
00417 const ParticleProperty*
00418 ParticlePropertySvc::anti ( const ParticleProperty* pp ) const
00419 {
00420   if ( 0 == pp ) { return 0 ; }
00421   const int     ID = pp->pdgID() ;
00422   const int antiID = -1 * ID     ;
00423   for ( const_iterator it = m_vectpp.begin() ; m_vectpp.end() != it ; ++it )
00424   {
00425     const ParticleProperty* ap = *it ;
00426     if ( 0 == ap               ) { continue  ; }                // CONTINUE
00427     if ( antiID == ap->pdgID() ) { return ap ; }                // RETURN
00428   };
00429   //
00430   return pp ;                                                   // RETURN
00431 }
00432 // ============================================================================
00437 // ============================================================================
00438 StatusCode ParticlePropertySvc::setAntiParticles()
00439 {
00440   // initialize particle<-->antiParticle relations
00441   for ( iterator ip = m_vectpp.begin() ; m_vectpp.end() != ip ; ++ip )
00442   {
00443     ParticleProperty* pp = *ip ;
00444     if ( 0 == pp                    ) { continue ; }   // CONTINUE
00445     const ParticleProperty* ap = anti ( pp ) ;
00446     if ( 0 != ap                    ) { pp->setAntiParticle( ap ) ; }
00447   }
00448   return StatusCode::SUCCESS ;
00449 }
00450 // ============================================================================
00452 // ============================================================================
00453 namespace
00454 {
00456   template <class MAP>
00457   void _load_ ( MAP& m , ParticlePropertySvc::Set& result )
00458   {
00459     for ( typename MAP::iterator i = m.begin() ; m.end() != i ; ++i )
00460     { result.insert ( i->second ); }
00461   }
00462 }
00463 // ============================================================================
00464 StatusCode ParticlePropertySvc::rebuild()
00465 {
00466   Set local ;
00467   m_vectpp.clear() ;
00468   m_vectpp.reserve ( m_idmap.size() + 100 ) ;
00469   // load information from maps into the set
00470   _load_ ( m_idmap       , local ) ;
00471   _load_ ( m_namemap     , local ) ;
00472   _load_ ( m_stdhepidmap , local ) ;
00473   _load_ ( m_pythiaidmap , local ) ;
00474   // load information from set to the linear container vector
00475   for ( Set::iterator i = local.begin() ; local.end() != i ; ++i )
00476   { m_vectpp.push_back ( *i ) ; }
00477   return setAntiParticles() ;
00478 }
00479 // ============================================================================
00480 // treat additional particles
00481 // ============================================================================
00482 StatusCode ParticlePropertySvc::addParticles()
00483 {
00484 
00485   MsgStream log ( msgSvc() , name() ) ;
00486   // loop over all "explicit" particles
00487   for ( Particles::const_iterator ip = m_particles.begin() ;
00488         m_particles.end() != ip ; ++ip )
00489   {
00490     const std::string item = *ip ;
00491     std::istringstream input( item ) ;
00492     // get the name
00493     std::string p_name   ;
00494     int         p_geant  ;
00495     int         p_jetset ;
00496     double      p_charge ;
00497     double      p_mass   ;
00498     double      p_ltime  ;
00499     std::string p_evtgen ;
00500     int         p_pythia ;
00501     double      p_maxwid ;
00502     if ( input
00503          >> p_name
00504          >> p_geant
00505          >> p_jetset
00506          >> p_charge
00507          >> p_mass
00508          >> p_ltime
00509          >> p_evtgen
00510          >> p_pythia
00511          >> p_maxwid )
00512     {
00513       log << MSG::ALWAYS
00514           << " Add/Modify the particle: "
00515           << " name='"   << p_name   << "'"
00516           << " geant="   << p_geant
00517           << " jetset="  << p_jetset
00518           << " charge="  << p_charge
00519           << " mass="    << p_mass
00520           << " ltime="   << p_ltime
00521           << " evtgen='" << p_evtgen << "'"
00522           << " pythia="  << p_pythia
00523           << " maxwid="  << p_maxwid << endmsg ;
00524       //
00525       StatusCode sc = push_back
00526         ( p_name                        ,
00527           p_geant                       ,
00528           p_jetset                      ,
00529           p_charge                      ,
00530           p_mass    * Gaudi::Units::GeV ,
00531           p_ltime   * Gaudi::Units::s   ,
00532           p_evtgen                      ,
00533           p_pythia                      ,
00534           p_maxwid  * Gaudi::Units::GeV ) ;
00535       if ( sc.isFailure() ) { return sc ; }                        // RETURN
00536     }
00537     else
00538     {
00539       log << MSG::ERROR
00540           << " could not parse '" << item << "'" << endmsg ;
00541       return StatusCode::FAILURE ;                                 // RETURN
00542     }
00543   }
00544   //
00545   return StatusCode::SUCCESS ;
00546 }
00547 // ============================================================================
00548 #ifdef __ICC
00549 // disable icc remark #1572: floating-point equality and inequality comparisons are unreliable
00550 //   The comparison are meant
00551 #pragma warning(push)
00552 #pragma warning(disable:1572)
00553 #endif
00554 bool ParticlePropertySvc::diff
00555 ( const ParticleProperty* o ,
00556   const ParticleProperty* n ,
00557   const MSG::Level        l ) const
00558 {
00559   //
00560   if ( o == n ) { return false ; }
00561   //
00562   MsgStream log ( msgSvc() , name() ) ;
00563   log << l ;
00564   if ( 0 == o || 0 == n  )
00565   {
00566     log << MSG::WARNING << " ParticleProperty* point to NULL" << endmsg ;
00567     return true ;                                                    // RETURN
00568   }
00569   //
00570   bool result = false ;
00571   if ( o -> particle () != n -> particle () )
00572   {
00573     result = true ;
00574     log << " Name:'"  << o -> particle () << "'/'" << n -> particle () << "'" ;
00575   }
00576   if ( o -> geantID  () != n -> geantID  () )
00577   {
00578     result = true ;
00579     log << " G3ID:"   << o -> geantID  () << "/"   << n -> geantID  () << "'" ;
00580   }
00581   if ( o -> pdgID    () != n -> pdgID    () )
00582   {
00583     result = true ;
00584     log << " PDGID:"  << o -> pdgID    () << "/"   << n -> pdgID    () << "'" ;
00585   }
00586   if ( o -> pythiaID () != n -> pythiaID () )
00587   {
00588     result = true ;
00589     log << " PYID:"   << o -> pythiaID () << "/"   << n -> pythiaID () << "'" ;
00590   }
00591   if ( o -> charge   () != n -> charge   () )
00592   {
00593     result = true ;
00594     log << " Q:"      << o -> charge   () << "/"   << n -> charge   () << "'" ;
00595   }
00596   if ( o -> mass     () != n -> mass     () )
00597   {
00598     result = true ;
00599     log << " M:"      << o -> mass     () << "/"   << n -> mass     () << "'" ;
00600   }
00601   if ( o -> lifetime () != n -> lifetime () )
00602   {
00603     result = true ;
00604     log << " T:"      << o -> lifetime () << "/"   << n -> lifetime () << "'" ;
00605   }
00606   if ( o -> evtGenName () != n -> evtGenName () )
00607   {
00608     result = true ;
00609     log << " EvtGen:" << o -> evtGenName () << "/"   << n -> evtGenName () << "'" ;
00610   }
00611   if ( o -> maxWidth () != n -> maxWidth () )
00612   {
00613     result = true ;
00614     log << " WMAX:"   << o -> maxWidth () << "/"   << n -> maxWidth () << "'" ;
00615   }
00616   if ( result ) { log << endmsg ; }
00617   //
00618   return result ;
00619 }
00620 #ifdef __ICC
00621 // re-enable icc remark #1572
00622 #pragma warning(pop)
00623 #endif
00624 // ============================================================================
00625 // The END
00626 // ============================================================================
00627 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Defines

Generated at Fri Sep 2 2011 16:25:00 for Gaudi Framework, version v22r4 by Doxygen version 1.7.2 written by Dimitri van Heesch, © 1997-2004