The Gaudi Framework  v29r0 (ff2e7097)
ParticlePropertySvc.cpp
Go to the documentation of this file.
1 // ============================================================================
2 // Include files
3 // ============================================================================
4 // STD&STL
5 // ============================================================================
6 #include "boost/algorithm/string/classification.hpp"
7 #include "boost/algorithm/string/split.hpp"
8 #include "boost/algorithm/string/trim.hpp"
9 #include <cctype>
10 #include <fstream>
11 namespace ba = boost::algorithm;
12 // ============================================================================
13 // GaudiKernel
14 // ============================================================================
17 #include "GaudiKernel/MsgStream.h"
20 #include "GaudiKernel/System.h"
21 // ============================================================================
22 //#include "GaudiKernel/ToStream.h"
23 // ============================================================================
24 // Local
25 // ============================================================================
26 #include "ParticlePropertySvc.h"
27 // ============================================================================
28 namespace
29 {
30  //@FIXME/@TODO remove once we can assume C++14...
31  template <typename T, class... Args>
32  std::unique_ptr<T> make_unique_( Args&&... args )
33  {
34  return std::unique_ptr<T>( new T( std::forward<Args>( args )... ) );
35  }
36 }
37 namespace Gaudi
38 {
42  DECLARE_COMPONENT( ParticlePropertySvc )
43  // ============================================================================
55  // ============================================================================
56  ParticlePropertySvc::ParticlePropertySvc( const std::string& name, ISvcLocator* svc ) : base_class( name, svc )
57  {
59  // Redefine the default name:
60  if ( System::getEnv( "PARAMFILESROOT", m_filename.value() ) ) {
61  m_filename.value() += "/data/ParticleTable.txt";
62  }
63  }
64  // ============================================================================
66  // ============================================================================
68  {
70  if ( sc.isFailure() ) {
71  return sc;
72  }
73 
74  sc = setProperties();
75  if ( sc.isFailure() ) {
76  error() << " Could not set the properties " << endmsg;
77  return sc;
78  }
79 
80  m_fileAccess = service( "VFSSvc" );
81  if ( !m_fileAccess ) {
82  error() << " Cannot retrieve the VFS service " << endmsg;
83  return StatusCode::FAILURE;
84  }
85 
86  sc = parse();
87  if ( sc.isFailure() ) {
88  error() << " Could not parse the file " << endmsg;
89  return sc;
90  }
91  if ( !m_particles.empty() ) {
92  sc = addParticles();
93  if ( sc.isFailure() ) {
94  error() << " Could not treat particles! " << endmsg;
95  return sc;
96  }
97  }
98  debug() << "ParticleProperties parsed successfully" << endmsg;
99 
100  debug() << "Access properties" << endmsg;
101  // For debugging purposes print out the size of the internal maps
102  // particle name as key: all particles in database are present here
103  debug() << "NameMap size =" << m_namemap.size() << endmsg;
104  // Geant3 ID as key: all particles in database are present here
105  debug() << "GeantID Map size =" << m_idmap.size() << endmsg;
106  // StdHep ID as key: some particles have no valid StdHep ID
107  debug() << "StdHepID Map size =" << m_stdhepidmap.size() << endmsg;
108  // Pythia ID as key: some particles are not defined in Pythia
109  debug() << "PythiaID Map size =" << m_pythiaidmap.size() << endmsg;
110 
111  if ( !m_replaced.empty() ) {
112  info() << "Properties have been redefined for " << m_replaced.size()
113  << " particles : " << Gaudi::Utils::toString( m_replaced ) << endmsg;
114  }
115 
116  return StatusCode::SUCCESS;
117  }
118  // =============================================================================
120  // =============================================================================
122  {
123  if ( !m_other.empty() ) {
124  info() << "Additional Properties have been read from files: " << Gaudi::Utils::toString( m_other ) << endmsg;
125  }
126 
127  if ( !m_replaced.empty() ) {
128  always() << "Properties have been redefined for " << m_replaced.size()
129  << " particles : " << Gaudi::Utils::toString( m_replaced ) << endmsg;
130  }
131 
133 
135  return Service::finalize();
136  }
137  // =============================================================================
139  // =============================================================================
140  StatusCode ParticlePropertySvc::push_back( const std::string& particle, int geantId, int jetsetId, double charge,
141  double mass, double tlife, const std::string& evtName, int pythiaId,
142  double maxWidth )
143  {
144  //
145  auto i = m_owned.insert( make_unique_<ParticleProperty>( particle, geantId, jetsetId, charge, mass, tlife, evtName,
146  pythiaId, maxWidth ) );
147  //
148  return i.second ? push_back( i.first->get() ) : StatusCode::FAILURE;
149  }
150  // =============================================================================
152  // =============================================================================
154  {
155  if ( !pp ) {
156  return StatusCode::FAILURE;
157  }
158  //
159  { // try to add into Geant(3)ID map
160  const int ID = pp->geantID();
161  // is this already in the map?
162  auto ifind = m_idmap.find( ID );
163  if ( m_idmap.end() != ifind && 0 != m_idmap[ID] ) {
164  diff( ifind->second, pp );
165  m_replaced.insert( m_idmap[ID]->particle() );
166  }
167  // put it into the map
168  m_idmap[ID] = pp;
169  }
170  //
171  { // try to add into Name map
172  const std::string& particle = pp->particle();
173  // is this already in the map?
174  auto ifind = m_namemap.find( particle );
175  if ( ifind != m_namemap.end() && ifind->second ) {
176  diff( ifind->second, pp );
177  m_replaced.insert( ifind->second->particle() );
178  }
179  // put it into the map
180  m_namemap[particle] = pp;
181  }
182  //
183  // add to StdHep map only if StdHep ID different from zero and if
184  // not Cerenkov (StdHep ID = gamma)
185  if ( 0 != pp->jetsetID() && "Tcherenkov" != pp->particle() ) { // try to add into StdHepID map
186  const int ID = pp->jetsetID();
187  // is this already in the map?
188  auto ifind = m_stdhepidmap.find( ID );
189  if ( m_stdhepidmap.end() != ifind && ifind->second ) {
190  diff( ifind->second, pp );
191  m_replaced.insert( ifind->second->particle() );
192  }
193  // put it into the map
194  m_stdhepidmap[ID] = pp;
195  }
196  //
197  // add to Pythia map only if Pythia ID is different from
198  // zero ( StdHep id is always different from zero in this case )
199  if ( 0 != pp->pythiaID() && 0 != pp->jetsetID() &&
200  "Tcherenkov" != pp->particle() ) { // try to add into PythiaID map
201  const int ID = pp->pythiaID();
202  // is this already in the map?
203  auto ifind = m_pythiaidmap.find( ID );
204  if ( m_pythiaidmap.end() != ifind && ifind->second ) {
205  diff( ifind->second, pp );
206  m_replaced.insert( ifind->second->particle() );
207  }
208  // put it into the map
209  m_pythiaidmap[ID] = pp;
210  }
211  //
212  return rebuild();
213  }
214  // =============================================================================
216  // =============================================================================
217  namespace
218  {
219  template <class MAP>
220  void _remove_( MAP& m, const ParticleProperty* pp )
221  {
222  auto i = std::find_if( m.begin(), m.end(), [&]( typename MAP::const_reference i ) { return i.second == pp; } );
223  if ( i != m.end() ) {
224  m.erase( i );
225  }
226  }
227  }
228  // ============================================================================
230  {
231  if ( !pp ) {
232  return StatusCode::FAILURE;
233  }
234 
235  _remove_( m_idmap, pp );
236  _remove_( m_namemap, pp );
237  _remove_( m_stdhepidmap, pp );
238  _remove_( m_pythiaidmap, pp );
239  //
240  return rebuild();
241  }
242  // ============================================================================
244  // ============================================================================
246  {
247 
248  // parse "the main" file
249  StatusCode sc = parse( m_filename );
250  if ( sc.isFailure() ) {
251  return sc;
252  }
253 
254  // parse "other" files
255  for ( auto& file : m_other ) {
256  sc = parse( file );
257  if ( sc.isFailure() ) {
258  return sc;
259  }
260  }
261 
262  // Now check that the file format was consistent with what parser
263  // expected
264  if ( m_namemap.empty() ) {
265  error() << "Format of input file inconsistent with what expected"
266  << " - Check you are using ParticleData.txt" << endmsg;
267  return StatusCode::FAILURE;
268  }
269 
270  return sc;
271  }
272  // ============================================================================
274  {
275  auto infile = ( m_fileAccess ? m_fileAccess->open( file ) : nullptr );
276  if ( !infile ) {
277  error() << "Unable to open properties file : " << file << endmsg;
278  return StatusCode::FAILURE;
279  }
280 
282  info() << "Opened particle properties file : " << file << endmsg;
283 
285  tokens.reserve( 9 );
287  while ( std::getline( *infile, line ) ) {
288  // parse each line of the file (comment lines begin with # in the cdf
289  // file,
290  if ( line.front() == '#' ) continue;
291 
292  tokens.clear();
293  ba::trim_left_if( line, ba::is_space() );
294  ba::split( tokens, line, ba::is_space(), boost::token_compress_on );
295  if ( tokens.size() != 9 ) continue;
296 
297  auto gid = std::stoi( tokens[1] );
298  auto jid = std::stoi( tokens[2] );
299  // Change the particles that do not correspond to a pdg number
300  if ( jid == 0 ) jid = 10000000 * gid;
301 
302  // add a particle property
303  sc = push_back( tokens[0], gid, jid, std::stod( tokens[3] ), std::stod( tokens[4] ) * Gaudi::Units::GeV,
304  std::stod( tokens[5] ) * Gaudi::Units::s, tokens[6], std::stoi( tokens[7] ),
305  std::stod( tokens[8] ) * Gaudi::Units::GeV );
306 
307  if ( sc.isFailure() ) {
308  error() << "Error from ParticlePropertySvc::push_back for particle='" << tokens[0] << "'" << endmsg;
309  }
310  }
311  return StatusCode::SUCCESS;
312  }
313  // ============================================================================
319  // ============================================================================
321  {
322  if ( !pp ) {
323  return nullptr;
324  }
325  const int ID = pp->pdgID();
326  const int antiID = -1 * ID;
327  for ( const auto& ap : m_vectpp ) {
328  if ( ap && antiID == ap->pdgID() ) {
329  return ap;
330  } // RETURN
331  };
332  //
333  return pp; // RETURN
334  }
335  // ============================================================================
340  // ============================================================================
342  {
343  // initialize particle<-->antiParticle relations
344  for ( auto& pp : m_vectpp ) {
345  if ( !pp ) {
346  continue;
347  } // CONTINUE
348  const ParticleProperty* ap = anti( pp );
349  if ( ap ) {
350  pp->setAntiParticle( ap );
351  }
352  }
353  return StatusCode::SUCCESS;
354  }
355  // ============================================================================
357  // ============================================================================
358  namespace
359  {
361  template <typename MAP, typename SET>
362  void _load_( MAP& m, SET& result )
363  {
364  for ( auto i = m.begin(); m.end() != i; ++i ) {
365  result.insert( i->second );
366  }
367  }
368  }
369  // ============================================================================
371  {
372  std::set<mapped_type> local;
373  m_vectpp.clear();
374  m_vectpp.reserve( m_idmap.size() + 100 );
375  // load information from maps into the set
376  _load_( m_idmap, local );
377  _load_( m_namemap, local );
378  _load_( m_stdhepidmap, local );
379  _load_( m_pythiaidmap, local );
380  // load information from set to the linear container vector
381  std::copy( std::begin( local ), std::end( local ), std::back_inserter( m_vectpp ) );
382  return setAntiParticles();
383  }
384  // ============================================================================
385  // treat additional particles
386  // ============================================================================
388  {
389  // loop over all "explicit" particles
390  for ( const auto& item : m_particles ) {
391  std::istringstream input( item );
392  // get the name
393  std::string p_name;
394  int p_geant;
395  int p_jetset;
396  double p_charge;
397  double p_mass;
398  double p_ltime;
399  std::string p_evtgen;
400  int p_pythia;
401  double p_maxwid;
402  if ( input >> p_name >> p_geant >> p_jetset >> p_charge >> p_mass >> p_ltime >> p_evtgen >> p_pythia >>
403  p_maxwid ) {
404  always() << " Add/Modify the particle: "
405  << " name='" << p_name << "'"
406  << " geant=" << p_geant << " jetset=" << p_jetset << " charge=" << p_charge << " mass=" << p_mass
407  << " ltime=" << p_ltime << " evtgen='" << p_evtgen << "'"
408  << " pythia=" << p_pythia << " maxwid=" << p_maxwid << endmsg;
409  //
410  StatusCode sc = push_back( p_name, p_geant, p_jetset, p_charge, p_mass * Gaudi::Units::GeV,
411  p_ltime * Gaudi::Units::s, p_evtgen, p_pythia, p_maxwid * Gaudi::Units::GeV );
412  if ( sc.isFailure() ) {
413  return sc;
414  } // RETURN
415  } else {
416  error() << " could not parse '" << item << "'" << endmsg;
417  return StatusCode::FAILURE; // RETURN
418  }
419  }
420  //
421  return StatusCode::SUCCESS;
422  }
423 // ============================================================================
424 #ifdef __ICC
425 // disable icc remark #1572: floating-point equality and inequality comparisons are unreliable
426 // The comparison are meant
427 #pragma warning( push )
428 #pragma warning( disable : 1572 )
429 #endif
431  {
432  //
433  if ( o == n ) {
434  return false;
435  }
436  //
437  auto& log = msgStream();
438  log << l;
439  if ( !o || !n ) {
440  log << MSG::WARNING << " ParticleProperty* point to NULL" << endmsg;
441  return true; // RETURN
442  }
443  //
444  bool result = false;
445  if ( o->particle() != n->particle() ) {
446  result = true;
447  log << " Name:'" << o->particle() << "'/'" << n->particle() << "'";
448  }
449  if ( o->geantID() != n->geantID() ) {
450  result = true;
451  log << " G3ID:" << o->geantID() << "/" << n->geantID() << "'";
452  }
453  if ( o->pdgID() != n->pdgID() ) {
454  result = true;
455  log << " PDGID:" << o->pdgID() << "/" << n->pdgID() << "'";
456  }
457  if ( o->pythiaID() != n->pythiaID() ) {
458  result = true;
459  log << " PYID:" << o->pythiaID() << "/" << n->pythiaID() << "'";
460  }
461  if ( o->charge() != n->charge() ) {
462  result = true;
463  log << " Q:" << o->charge() << "/" << n->charge() << "'";
464  }
465  if ( o->mass() != n->mass() ) {
466  result = true;
467  log << " M:" << o->mass() << "/" << n->mass() << "'";
468  }
469  if ( o->lifetime() != n->lifetime() ) {
470  result = true;
471  log << " T:" << o->lifetime() << "/" << n->lifetime() << "'";
472  }
473  if ( o->evtGenName() != n->evtGenName() ) {
474  result = true;
475  log << " EvtGen:" << o->evtGenName() << "/" << n->evtGenName() << "'";
476  }
477  if ( o->maxWidth() != n->maxWidth() ) {
478  result = true;
479  log << " WMAX:" << o->maxWidth() << "/" << n->maxWidth() << "'";
480  }
481  if ( result ) {
482  log << endmsg;
483  }
484  //
485  return result;
486  }
487 }
488 #ifdef __ICC
489 // re-enable icc remark #1572
490 #pragma warning( pop )
491 #endif
492 // ============================================================================
493 // The END
494 // ============================================================================
int pdgID() const
Get the PDG (= JETSET) ID.
GAUDI_API std::string getEnv(const char *var)
get a particular environment variable (returning "UNKNOWN" if not set)
Definition: System.cpp:581
StatusCode rebuild()
rebuild "the linear container" from the map
StatusCode initialize() override
Definition: Service.cpp:64
T empty(T...args)
T copy(T...args)
The ISvcLocator is the interface implemented by the Service Factory in the Application Manager to loc...
Definition: ISvcLocator.h:25
constexpr double s
int geantID() const
Get the GEANT3 ID.
StatusCode finalize() override
Definition: Service.cpp:174
This service provides access to particle properties.
MsgStream & info() const
shortcut for the method msgStream(MSG::INFO)
double maxWidth() const
Get the max width deviation.
T front(T...args)
A trivial class to hold information about a single particle properties.
std::string toString(const TYPE &obj)
the generic implementation of the type conversion to the string
Definition: ToStream.h:346
StatusCode erase(int geantId) override
Erase a property by geant3 id.
T stod(T...args)
T getline(T...args)
StatusCode finalize() override
Finalise the service.
StatusCode initialize() override
Initialise the service.
STL namespace.
MapName m_namemap
Map for particle names.
StatusCode parse()
Parses the file and fill all the maps.
T end(T...args)
SmartIF< IFileAccess > m_fileAccess
bool isFailure() const
Test for a status code of FAILURE.
Definition: StatusCode.h:86
#define DECLARE_COMPONENT(type)
Definition: PluginService.h:33
StatusCode push_back(const std::string &particle, int geantId, int jetsetId, double charge, double mass, double tlife, const std::string &evtName, int pythiaId, double maxWidth) override
Create a new particle property.
STL class.
MsgStream & error() const
shortcut for the method msgStream(MSG::ERROR)
std::set< std::string > m_replaced
int jetsetID() const
Get the JETSET(StdHep) ID.
This class is used for returning status codes from appropriate routines.
Definition: StatusCode.h:28
double lifetime() const
Get the particle lifetime.
constexpr double m
Definition: SystemOfUnits.h:94
T clear(T...args)
StatusCode setProperties()
Method for setting declared properties to the values specified for the job.
Definition: Service.cpp:295
MapStdHepID m_stdhepidmap
Map for StdHep Ids.
dictionary l
Definition: gaudirun.py:440
T insert(T...args)
const ParticleProperty * anti(const ParticleProperty *pp) const
helper (protected) function to find an antiparticle for the given particle ID (StdHepID) ...
T find(T...args)
T size(T...args)
STL class.
STL class.
MsgStream & debug() const
shortcut for the method msgStream(MSG::DEBUG)
T begin(T...args)
bool diff(const ParticleProperty *o, const ParticleProperty *n, const MSG::Level l=MSG::DEBUG) const
T back_inserter(T...args)
#define SET(x)
Gaudi::Property< std::vector< std::string > > m_other
double charge() const
Get the particle charge.
MsgStream & msgStream() const
Return an uninitialized MsgStream.
std::set< std::unique_ptr< ParticleProperty > > m_owned
MapID m_idmap
Map for geant IDs.
Gaudi::Property< std::string > m_filename
Gaudi::Property< std::vector< std::string > > m_particles
StatusCode service(const std::string &name, const T *&psvc, bool createIf=true) const
Access a service by name, creating it if it doesn&#39;t already exist.
Definition: Service.h:85
constexpr double GeV
void reset(TYPE *ptr=nullptr)
Set the internal pointer to the passed one disposing of the old one.
Definition: SmartIF.h:92
StatusCode setAntiParticles()
helper (protected) function to set the valid particle<–>antiparticle relations
VectPP m_vectpp
Vector of all particle properties.
const std::string & particle() const
Get the particle name.
MsgStream & always() const
shortcut for the method msgStream(MSG::ALWAYS)
double mass() const
Get the particle mass.
int pythiaID() const
Get the Pythia ID.
T stoi(T...args)
virtual std::unique_ptr< std::istream > open(const std::string &url)=0
Find the URL and returns a unique_ptr to an input stream interface of an object that can be used to r...
Helper functions to set/get the application return code.
Definition: __init__.py:1
MsgStream & endmsg(MsgStream &s)
MsgStream Modifier: endmsg. Calls the output method of the MsgStream.
Definition: MsgStream.h:209
MapPythiaID m_pythiaidmap
Map for Pythia Ids.
T reserve(T...args)
const std::string & evtGenName() const
Get the EvtGen name.