The Gaudi Framework  v37r1 (a7f61348)
ParticlePropertySvc.cpp
Go to the documentation of this file.
1 /***********************************************************************************\
2 * (c) Copyright 1998-2019 CERN for the benefit of the LHCb and ATLAS collaborations *
3 * *
4 * This software is distributed under the terms of the Apache version 2 licence, *
5 * copied verbatim in the file "LICENSE". *
6 * *
7 * In applying this licence, CERN does not waive the privileges and immunities *
8 * granted to it by virtue of its status as an Intergovernmental Organization *
9 * or submit itself to any jurisdiction. *
10 \***********************************************************************************/
11 #include "boost/algorithm/string/classification.hpp"
12 #include "boost/algorithm/string/split.hpp"
13 #include "boost/algorithm/string/trim.hpp"
14 #include <cctype>
15 #include <fstream>
16 namespace ba = boost::algorithm;
17 
20 #include "GaudiKernel/MsgStream.h"
23 #include "GaudiKernel/System.h"
24 
25 #include "ParticlePropertySvc.h"
26 
27 namespace {
28  // idea coming from The art of computer programming by Knuth
29  constexpr bool essentiallyEqual( double const a, double const b ) {
30  return std::abs( a - b ) <= std::min( std::abs( a ), std::abs( b ) ) * std::numeric_limits<double>::epsilon();
31  }
32 } // namespace
33 
34 namespace Gaudi {
38  DECLARE_COMPONENT( ParticlePropertySvc )
39  // ============================================================================
51  // ============================================================================
54  // Redefine the default name:
55  if ( System::getEnv( "PARAMFILESROOT", m_filename.value() ) ) { m_filename.value() += "/data/ParticleTable.txt"; }
56  }
57  // ============================================================================
59  // ============================================================================
62  if ( sc.isFailure() ) { return sc; }
63 
64  m_fileAccess = service( "VFSSvc" );
65  if ( !m_fileAccess ) {
66  error() << " Cannot retrieve the VFS service " << endmsg;
67  return StatusCode::FAILURE;
68  }
69 
70  sc = parse();
71  if ( sc.isFailure() ) {
72  error() << " Could not parse the file " << endmsg;
73  return sc;
74  }
75  if ( !m_particles.empty() ) {
76  sc = addParticles();
77  if ( sc.isFailure() ) {
78  error() << " Could not treat particles! " << endmsg;
79  return sc;
80  }
81  }
82  debug() << "ParticleProperties parsed successfully" << endmsg;
83 
84  debug() << "Access properties" << endmsg;
85  // For debugging purposes print out the size of the internal maps
86  // particle name as key: all particles in database are present here
87  debug() << "NameMap size =" << m_namemap.size() << endmsg;
88  // Geant3 ID as key: all particles in database are present here
89  debug() << "GeantID Map size =" << m_idmap.size() << endmsg;
90  // StdHep ID as key: some particles have no valid StdHep ID
91  debug() << "StdHepID Map size =" << m_stdhepidmap.size() << endmsg;
92  // Pythia ID as key: some particles are not defined in Pythia
93  debug() << "PythiaID Map size =" << m_pythiaidmap.size() << endmsg;
94 
95  if ( !m_replaced.empty() ) {
96  info() << "Properties have been redefined for " << m_replaced.size()
97  << " particles : " << Gaudi::Utils::toString( m_replaced ) << endmsg;
98  }
99 
100  return StatusCode::SUCCESS;
101  }
102  // =============================================================================
104  // =============================================================================
106  if ( !m_other.empty() ) {
107  info() << "Additional Properties have been read from files: " << Gaudi::Utils::toString( m_other ) << endmsg;
108  }
109 
110  if ( !m_replaced.empty() ) {
111  always() << "Properties have been redefined for " << m_replaced.size()
112  << " particles : " << Gaudi::Utils::toString( m_replaced ) << endmsg;
113  }
114 
116 
118  return Service::finalize();
119  }
120  // =============================================================================
122  // =============================================================================
123  StatusCode ParticlePropertySvc::push_back( const std::string& particle, int geantId, int jetsetId, double charge,
124  double mass, double tlife, const std::string& evtName, int pythiaId,
125  double maxWidth ) {
126  //
127  auto& pp = m_owned.emplace_back( particle, geantId, jetsetId, charge, mass, tlife, evtName, pythiaId, maxWidth );
128  return push_back( &pp );
129  }
130  // =============================================================================
132  // =============================================================================
134  if ( !pp ) { return StatusCode::FAILURE; }
135  //
136  { // try to add into Geant(3)ID map
137  const int ID = pp->geantID();
138  // is this already in the map?
139  auto ifind = m_idmap.find( ID );
140  if ( m_idmap.end() != ifind && 0 != m_idmap[ID] ) {
141  diff( ifind->second, pp );
142  m_replaced.insert( m_idmap[ID]->particle() );
143  }
144  // put it into the map
145  m_idmap[ID] = pp;
146  }
147  //
148  { // try to add into Name map
149  const std::string& particle = pp->particle();
150  // is this already in the map?
151  auto ifind = m_namemap.find( particle );
152  if ( ifind != m_namemap.end() && ifind->second ) {
153  diff( ifind->second, pp );
154  m_replaced.insert( ifind->second->particle() );
155  }
156  // put it into the map
157  m_namemap[particle] = pp;
158  }
159  //
160  // add to StdHep map only if StdHep ID different from zero and if
161  // not Cerenkov (StdHep ID = gamma)
162  if ( 0 != pp->jetsetID() && "Tcherenkov" != pp->particle() ) { // try to add into StdHepID map
163  const int ID = pp->jetsetID();
164  // is this already in the map?
165  auto ifind = m_stdhepidmap.find( ID );
166  if ( m_stdhepidmap.end() != ifind && ifind->second ) {
167  diff( ifind->second, pp );
168  m_replaced.insert( ifind->second->particle() );
169  }
170  // put it into the map
171  m_stdhepidmap[ID] = pp;
172  }
173  //
174  // add to Pythia map only if Pythia ID is different from
175  // zero ( StdHep id is always different from zero in this case )
176  if ( 0 != pp->pythiaID() && 0 != pp->jetsetID() && "Tcherenkov" != pp->particle() ) { // try to add into PythiaID
177  // map
178  const int ID = pp->pythiaID();
179  // is this already in the map?
180  auto ifind = m_pythiaidmap.find( ID );
181  if ( m_pythiaidmap.end() != ifind && ifind->second ) {
182  diff( ifind->second, pp );
183  m_replaced.insert( ifind->second->particle() );
184  }
185  // put it into the map
186  m_pythiaidmap[ID] = pp;
187  }
188  //
189  return rebuild();
190  }
191  // =============================================================================
193  // =============================================================================
194  namespace {
195  template <class MAP>
196  void _remove_( MAP& m, const ParticleProperty* pp ) {
197  auto i = std::find_if( m.begin(), m.end(), [&]( typename MAP::const_reference i ) { return i.second == pp; } );
198  if ( i != m.end() ) { m.erase( i ); }
199  }
200  } // namespace
201  // ============================================================================
203  if ( !pp ) { return StatusCode::FAILURE; }
204 
205  _remove_( m_idmap, pp );
206  _remove_( m_namemap, pp );
207  _remove_( m_stdhepidmap, pp );
208  _remove_( m_pythiaidmap, pp );
209  //
210  return rebuild();
211  }
212  // ============================================================================
214  // ============================================================================
216 
217  // parse "the main" file
218  StatusCode sc = parse( m_filename );
219  if ( sc.isFailure() ) { return sc; }
220 
221  // parse "other" files
222  for ( auto& file : m_other ) {
223  sc = parse( file );
224  if ( sc.isFailure() ) { return sc; }
225  }
226 
227  // Now check that the file format was consistent with what parser
228  // expected
229  if ( m_namemap.empty() ) {
230  error() << "Format of input file inconsistent with what expected"
231  << " - Check you are using ParticleData.txt" << endmsg;
232  return StatusCode::FAILURE;
233  }
234 
235  return sc;
236  }
237  // ============================================================================
239  auto infile = ( m_fileAccess ? m_fileAccess->open( file ) : nullptr );
240  if ( !infile ) {
241  error() << "Unable to open properties file : " << file << endmsg;
242  return StatusCode::FAILURE;
243  }
244 
246  info() << "Opened particle properties file : " << file << endmsg;
247 
249  tokens.reserve( 9 );
251  while ( std::getline( *infile, line ) ) {
252  // parse each line of the file (comment lines begin with # in the cdf
253  // file,
254  if ( line.front() == '#' ) continue;
255 
256  tokens.clear();
257  ba::trim_left_if( line, ba::is_space() );
258  ba::split( tokens, line, ba::is_space(), boost::token_compress_on );
259  if ( tokens.size() != 9 ) continue;
260 
261  auto gid = std::stoi( tokens[1] );
262  auto jid = std::stoi( tokens[2] );
263  // Change the particles that do not correspond to a pdg number
264  if ( jid == 0 ) jid = 10000000 * gid;
265 
266  // add a particle property
267  sc = push_back( tokens[0], gid, jid, std::stod( tokens[3] ), std::stod( tokens[4] ) * Gaudi::Units::GeV,
268  std::stod( tokens[5] ) * Gaudi::Units::s, tokens[6], std::stoi( tokens[7] ),
269  std::stod( tokens[8] ) * Gaudi::Units::GeV );
270 
271  if ( sc.isFailure() ) {
272  error() << "Error from ParticlePropertySvc::push_back for particle='" << tokens[0] << "'" << endmsg;
273  }
274  }
275  return StatusCode::SUCCESS;
276  }
277  // ============================================================================
283  // ============================================================================
285  if ( !pp ) { return nullptr; }
286  const int ID = pp->pdgID();
287  const int antiID = -1 * ID;
288  for ( const auto& ap : m_vectpp ) {
289  if ( ap && antiID == ap->pdgID() ) { return ap; } // RETURN
290  };
291  //
292  return pp; // RETURN
293  }
294  // ============================================================================
299  // ============================================================================
301  // initialize particle<-->antiParticle relations
302  for ( auto& pp : m_vectpp ) {
303  if ( !pp ) { continue; } // CONTINUE
304  const ParticleProperty* ap = anti( pp );
305  if ( ap ) { pp->setAntiParticle( ap ); }
306  }
307  return StatusCode::SUCCESS;
308  }
309  // ============================================================================
311  // ============================================================================
312  namespace {
314  template <typename MAP, typename SET>
315  void _load_( MAP& m, SET& result ) {
316  for ( auto i = m.begin(); m.end() != i; ++i ) { result.insert( i->second ); }
317  }
318  } // namespace
319  // ============================================================================
321  std::set<mapped_type> local;
322  m_vectpp.clear();
323  m_vectpp.reserve( m_idmap.size() + 100 );
324  // load information from maps into the set
325  _load_( m_idmap, local );
326  _load_( m_namemap, local );
327  _load_( m_stdhepidmap, local );
328  _load_( m_pythiaidmap, local );
329  // load information from set to the linear container vector
330  std::copy( std::begin( local ), std::end( local ), std::back_inserter( m_vectpp ) );
331  return setAntiParticles();
332  }
333  // ============================================================================
334  // treat additional particles
335  // ============================================================================
337  // loop over all "explicit" particles
338  for ( const auto& item : m_particles ) {
339  std::istringstream input( item );
340  // get the name
341  std::string p_name;
342  int p_geant;
343  int p_jetset;
344  double p_charge;
345  double p_mass;
346  double p_ltime;
347  std::string p_evtgen;
348  int p_pythia;
349  double p_maxwid;
350  if ( input >> p_name >> p_geant >> p_jetset >> p_charge >> p_mass >> p_ltime >> p_evtgen >> p_pythia >>
351  p_maxwid ) {
352  always() << " Add/Modify the particle: "
353  << " name='" << p_name << "'"
354  << " geant=" << p_geant << " jetset=" << p_jetset << " charge=" << p_charge << " mass=" << p_mass
355  << " ltime=" << p_ltime << " evtgen='" << p_evtgen << "'"
356  << " pythia=" << p_pythia << " maxwid=" << p_maxwid << endmsg;
357  //
358  StatusCode sc = push_back( p_name, p_geant, p_jetset, p_charge, p_mass * Gaudi::Units::GeV,
359  p_ltime * Gaudi::Units::s, p_evtgen, p_pythia, p_maxwid * Gaudi::Units::GeV );
360  if ( sc.isFailure() ) { return sc; } // RETURN
361  } else {
362  error() << " could not parse '" << item << "'" << endmsg;
363  return StatusCode::FAILURE; // RETURN
364  }
365  }
366  //
367  return StatusCode::SUCCESS;
368  }
369  // ============================================================================
371  //
372  if ( o == n ) { return false; }
373  //
374  auto& log = msgStream();
375  log << l;
376  if ( !o || !n ) {
377  log << MSG::WARNING << " ParticleProperty* point to NULL" << endmsg;
378  return true; // RETURN
379  }
380  //
381  bool result = false;
382  if ( o->particle() != n->particle() ) {
383  result = true;
384  log << " Name:'" << o->particle() << "'/'" << n->particle() << "'";
385  }
386  if ( o->geantID() != n->geantID() ) {
387  result = true;
388  log << " G3ID:" << o->geantID() << "/" << n->geantID() << "'";
389  }
390  if ( o->pdgID() != n->pdgID() ) {
391  result = true;
392  log << " PDGID:" << o->pdgID() << "/" << n->pdgID() << "'";
393  }
394  if ( o->pythiaID() != n->pythiaID() ) {
395  result = true;
396  log << " PYID:" << o->pythiaID() << "/" << n->pythiaID() << "'";
397  }
398  if ( essentiallyEqual( o->charge(), n->charge() ) ) {
399  result = true;
400  log << " Q:" << o->charge() << "/" << n->charge() << "'";
401  }
402  if ( essentiallyEqual( o->mass(), n->mass() ) ) {
403  result = true;
404  log << " M:" << o->mass() << "/" << n->mass() << "'";
405  }
406  if ( essentiallyEqual( o->lifetime(), n->lifetime() ) ) {
407  result = true;
408  log << " T:" << o->lifetime() << "/" << n->lifetime() << "'";
409  }
410  if ( o->evtGenName() != n->evtGenName() ) {
411  result = true;
412  log << " EvtGen:" << o->evtGenName() << "/" << n->evtGenName() << "'";
413  }
414  if ( essentiallyEqual( o->maxWidth(), n->maxWidth() ) ) {
415  result = true;
416  log << " WMAX:" << o->maxWidth() << "/" << n->maxWidth() << "'";
417  }
418  if ( result ) { log << endmsg; }
419  //
420  return result;
421  }
422 } // namespace Gaudi
423 // ============================================================================
424 // The END
425 // ============================================================================
ParticleProperty::charge
double charge() const
Get the particle charge.
Definition: ParticleProperty.h:73
Service::initialize
StatusCode initialize() override
Definition: Service.cpp:118
Gaudi::ParticlePropertySvc::setAntiParticles
StatusCode setAntiParticles()
helper (protected) function to set the valid particle<-->antiparticle relations
Definition: ParticlePropertySvc.cpp:300
std::string
STL class.
Gaudi.Configuration.log
log
Definition: Configuration.py:30
bug_34121.name
name
Definition: bug_34121.py:20
Gaudi::ParticlePropertySvc::m_fileAccess
SmartIF< IFileAccess > m_fileAccess
Definition: ParticlePropertySvc.h:187
System.h
Gaudi::ParticlePropertySvc::m_idmap
MapID m_idmap
Map for geant IDs.
Definition: ParticlePropertySvc.h:178
Gaudi::ParticlePropertySvc::m_stdhepidmap
MapStdHepID m_stdhepidmap
Map for StdHep Ids.
Definition: ParticlePropertySvc.h:180
std::vector::reserve
T reserve(T... args)
Gaudi::ParticlePropertySvc::erase
StatusCode erase(int geantId) override
Erase a property by geant3 id.
Definition: ParticlePropertySvc.h:134
ParticleProperty::evtGenName
const std::string & evtGenName() const
Get the EvtGen name.
Definition: ParticleProperty.h:91
System::getEnv
GAUDI_API std::string getEnv(const char *var)
get a particular environment variable (returning "UNKNOWN" if not set)
Definition: System.cpp:388
std::vector< std::string >
SmartIF::reset
void reset(TYPE *ptr=nullptr)
Set the internal pointer to the passed one disposing of the old one.
Definition: SmartIF.h:96
std::map::find
T find(T... args)
std::map::size
T size(T... args)
Gaudi::ParticlePropertySvc::parse
StatusCode parse()
Parses the file and fill all the maps.
Definition: ParticlePropertySvc.cpp:215
Gaudi::Units::GeV
constexpr double GeV
Definition: SystemOfUnits.h:179
ISvcLocator
Definition: ISvcLocator.h:46
std::back_inserter
T back_inserter(T... args)
Gaudi::ParticlePropertySvc::m_namemap
MapName m_namemap
Map for particle names.
Definition: ParticlePropertySvc.h:179
std::istringstream
STL class.
MSG::WARNING
@ WARNING
Definition: IMessageSvc.h:25
Gaudi::ParticlePropertySvc::m_filename
Gaudi::Property< std::string > m_filename
Definition: ParticlePropertySvc.h:171
PhysicalConstants.h
ParticleProperty::pythiaID
int pythiaID() const
Get the Pythia ID.
Definition: ParticleProperty.h:97
Gaudi::ParticlePropertySvc::finalize
StatusCode finalize() override
Finalise the service.
Definition: ParticlePropertySvc.cpp:105
Service::finalize
StatusCode finalize() override
Definition: Service.cpp:222
ParticleProperty::particle
const std::string & particle() const
Get the particle name.
Definition: ParticleProperty.h:49
IFileAccess.h
std::vector::clear
T clear(T... args)
Gaudi::ParticlePropertySvc::m_pythiaidmap
MapPythiaID m_pythiaidmap
Map for Pythia Ids.
Definition: ParticlePropertySvc.h:181
Gaudi::ParticlePropertySvc::anti
const ParticleProperty * anti(const ParticleProperty *pp) const
helper (protected) function to find an antiparticle for the given particle ID (StdHepID)
Definition: ParticlePropertySvc.cpp:284
std::stoi
T stoi(T... args)
Gaudi::ParticlePropertySvc::rebuild
StatusCode rebuild()
rebuild "the linear container" from the map
Definition: ParticlePropertySvc.cpp:320
ParticleProperty::pdgID
int pdgID() const
Get the PDG (= JETSET) ID.
Definition: ParticleProperty.h:61
ParticleProperty
Definition: ParticleProperty.h:28
StatusCode
Definition: StatusCode.h:65
Gaudi::ParticlePropertySvc::diff
bool diff(const ParticleProperty *o, const ParticleProperty *n, const MSG::Level l=MSG::DEBUG) const
Definition: ParticlePropertySvc.cpp:370
ParticleProperty::mass
double mass() const
Get the particle mass.
Definition: ParticleProperty.h:79
Gaudi::Units::m
constexpr double m
Definition: SystemOfUnits.h:108
Gaudi::ParticlePropertySvc::m_particles
Gaudi::Property< std::vector< std::string > > m_particles
Definition: ParticlePropertySvc.h:174
CommonMessaging
Definition: CommonMessaging.h:66
ParticleProperty::maxWidth
double maxWidth() const
Get the max width deviation.
Definition: ParticleProperty.h:103
GaudiPython.Bindings.nullptr
nullptr
Definition: Bindings.py:88
std::copy
T copy(T... args)
ParticleProperty::lifetime
double lifetime() const
Get the particle lifetime.
Definition: ParticleProperty.h:85
Gaudi::ParticlePropertySvc
Definition: ParticlePropertySvc.h:82
endmsg
MsgStream & endmsg(MsgStream &s)
MsgStream Modifier: endmsg. Calls the output method of the MsgStream.
Definition: MsgStream.h:203
Gaudi
Header file for std:chrono::duration-based Counters.
Definition: __init__.py:1
ParticleProperty::geantID
int geantID() const
Get the GEANT3 ID.
Definition: ParticleProperty.h:55
Gaudi::ParticlePropertySvc::addParticles
StatusCode addParticles()
Definition: ParticlePropertySvc.cpp:336
GaudiPluginService.cpluginsvc.n
n
Definition: cpluginsvc.py:235
std::numeric_limits::epsilon
T epsilon(T... args)
Gaudi::ParticlePropertySvc::push_back
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.
Definition: ParticlePropertySvc.cpp:123
std::min
T min(T... args)
Gaudi::Units::s
constexpr double s
Definition: SystemOfUnits.h:153
StatusCode::isFailure
bool isFailure() const
Definition: StatusCode.h:129
Gaudi::Utils::toString
std::string toString(const TYPE &obj)
the generic implementation of the type conversion to the string
Definition: ToStream.h:353
Gaudi::ParticlePropertySvc::m_owned
std::deque< ParticleProperty > m_owned
Definition: ParticlePropertySvc.h:184
MSG::Level
Level
Definition: IMessageSvc.h:25
std::deque::emplace_back
T emplace_back(T... args)
std::stod
T stod(T... args)
Gaudi::ParticlePropertySvc::m_other
Gaudi::Property< std::vector< std::string > > m_other
Definition: ParticlePropertySvc.h:173
StatusCode::SUCCESS
constexpr static const auto SUCCESS
Definition: StatusCode.h:100
gaudirun.l
dictionary l
Definition: gaudirun.py:582
std::begin
T begin(T... args)
std::getline
T getline(T... args)
std
STL namespace.
DECLARE_COMPONENT
#define DECLARE_COMPONENT(type)
Definition: PluginServiceV1.h:46
std::set::insert
T insert(T... args)
std::set::empty
T empty(T... args)
plotSpeedupsPyRoot.line
line
Definition: plotSpeedupsPyRoot.py:198
Gaudi::ParticlePropertySvc::initialize
StatusCode initialize() override
Initialise the service.
Definition: ParticlePropertySvc.cpp:60
ParticlePropertySvc.h
Gaudi::ParticlePropertySvc::m_replaced
std::set< std::string > m_replaced
Definition: ParticlePropertySvc.h:185
Gaudi::ParticlePropertySvc::m_vectpp
VectPP m_vectpp
Vector of all particle properties.
Definition: ParticlePropertySvc.h:177
std::map::end
T end(T... args)
StatusCode::FAILURE
constexpr static const auto FAILURE
Definition: StatusCode.h:101
ISvcLocator.h
compareOutputFiles.pp
pp
Definition: compareOutputFiles.py:507
Service::service
StatusCode service(const std::string &name, const T *&psvc, bool createIf=true) const
Access a service by name, creating it if it doesn't already exist.
Definition: Service.h:88
ParticleProperty.h
std::set
STL class.
SET
#define SET(x)
MsgStream.h