The Gaudi Framework  v33r0 (d5ea422b)
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 // ============================================================================
12 // Include files
13 // ============================================================================
14 // STD&STL
15 // ============================================================================
16 #include "boost/algorithm/string/classification.hpp"
17 #include "boost/algorithm/string/split.hpp"
18 #include "boost/algorithm/string/trim.hpp"
19 #include <cctype>
20 #include <fstream>
21 namespace ba = boost::algorithm;
22 // ============================================================================
23 // GaudiKernel
24 // ============================================================================
27 #include "GaudiKernel/MsgStream.h"
30 #include "GaudiKernel/System.h"
31 // ============================================================================
32 //#include "GaudiKernel/ToStream.h"
33 // ============================================================================
34 // Local
35 // ============================================================================
36 #include "ParticlePropertySvc.h"
37 // ============================================================================
38 namespace Gaudi {
42  DECLARE_COMPONENT( ParticlePropertySvc )
43  // ============================================================================
55  // ============================================================================
58  // Redefine the default name:
59  if ( System::getEnv( "PARAMFILESROOT", m_filename.value() ) ) { m_filename.value() += "/data/ParticleTable.txt"; }
60  }
61  // ============================================================================
63  // ============================================================================
66  if ( sc.isFailure() ) { return sc; }
67 
68  sc = setProperties();
69  if ( sc.isFailure() ) {
70  error() << " Could not set the properties " << endmsg;
71  return sc;
72  }
73 
74  m_fileAccess = service( "VFSSvc" );
75  if ( !m_fileAccess ) {
76  error() << " Cannot retrieve the VFS service " << endmsg;
77  return StatusCode::FAILURE;
78  }
79 
80  sc = parse();
81  if ( sc.isFailure() ) {
82  error() << " Could not parse the file " << endmsg;
83  return sc;
84  }
85  if ( !m_particles.empty() ) {
86  sc = addParticles();
87  if ( sc.isFailure() ) {
88  error() << " Could not treat particles! " << endmsg;
89  return sc;
90  }
91  }
92  debug() << "ParticleProperties parsed successfully" << endmsg;
93 
94  debug() << "Access properties" << endmsg;
95  // For debugging purposes print out the size of the internal maps
96  // particle name as key: all particles in database are present here
97  debug() << "NameMap size =" << m_namemap.size() << endmsg;
98  // Geant3 ID as key: all particles in database are present here
99  debug() << "GeantID Map size =" << m_idmap.size() << endmsg;
100  // StdHep ID as key: some particles have no valid StdHep ID
101  debug() << "StdHepID Map size =" << m_stdhepidmap.size() << endmsg;
102  // Pythia ID as key: some particles are not defined in Pythia
103  debug() << "PythiaID Map size =" << m_pythiaidmap.size() << endmsg;
104 
105  if ( !m_replaced.empty() ) {
106  info() << "Properties have been redefined for " << m_replaced.size()
107  << " particles : " << Gaudi::Utils::toString( m_replaced ) << endmsg;
108  }
109 
110  return StatusCode::SUCCESS;
111  }
112  // =============================================================================
114  // =============================================================================
116  if ( !m_other.empty() ) {
117  info() << "Additional Properties have been read from files: " << Gaudi::Utils::toString( m_other ) << endmsg;
118  }
119 
120  if ( !m_replaced.empty() ) {
121  always() << "Properties have been redefined for " << m_replaced.size()
122  << " particles : " << Gaudi::Utils::toString( m_replaced ) << endmsg;
123  }
124 
126 
128  return Service::finalize();
129  }
130  // =============================================================================
132  // =============================================================================
133  StatusCode ParticlePropertySvc::push_back( const std::string& particle, int geantId, int jetsetId, double charge,
134  double mass, double tlife, const std::string& evtName, int pythiaId,
135  double maxWidth ) {
136  //
137  auto i = m_owned.insert( std::make_unique<ParticleProperty>( particle, geantId, jetsetId, charge, mass, tlife,
138  evtName, pythiaId, maxWidth ) );
139  //
140  return i.second ? push_back( i.first->get() ) : StatusCode::FAILURE;
141  }
142  // =============================================================================
144  // =============================================================================
146  if ( !pp ) { return StatusCode::FAILURE; }
147  //
148  { // try to add into Geant(3)ID map
149  const int ID = pp->geantID();
150  // is this already in the map?
151  auto ifind = m_idmap.find( ID );
152  if ( m_idmap.end() != ifind && 0 != m_idmap[ID] ) {
153  diff( ifind->second, pp );
154  m_replaced.insert( m_idmap[ID]->particle() );
155  }
156  // put it into the map
157  m_idmap[ID] = pp;
158  }
159  //
160  { // try to add into Name map
161  const std::string& particle = pp->particle();
162  // is this already in the map?
163  auto ifind = m_namemap.find( particle );
164  if ( ifind != m_namemap.end() && ifind->second ) {
165  diff( ifind->second, pp );
166  m_replaced.insert( ifind->second->particle() );
167  }
168  // put it into the map
169  m_namemap[particle] = pp;
170  }
171  //
172  // add to StdHep map only if StdHep ID different from zero and if
173  // not Cerenkov (StdHep ID = gamma)
174  if ( 0 != pp->jetsetID() && "Tcherenkov" != pp->particle() ) { // try to add into StdHepID map
175  const int ID = pp->jetsetID();
176  // is this already in the map?
177  auto ifind = m_stdhepidmap.find( ID );
178  if ( m_stdhepidmap.end() != ifind && ifind->second ) {
179  diff( ifind->second, pp );
180  m_replaced.insert( ifind->second->particle() );
181  }
182  // put it into the map
183  m_stdhepidmap[ID] = pp;
184  }
185  //
186  // add to Pythia map only if Pythia ID is different from
187  // zero ( StdHep id is always different from zero in this case )
188  if ( 0 != pp->pythiaID() && 0 != pp->jetsetID() && "Tcherenkov" != pp->particle() ) { // try to add into PythiaID
189  // map
190  const int ID = pp->pythiaID();
191  // is this already in the map?
192  auto ifind = m_pythiaidmap.find( ID );
193  if ( m_pythiaidmap.end() != ifind && ifind->second ) {
194  diff( ifind->second, pp );
195  m_replaced.insert( ifind->second->particle() );
196  }
197  // put it into the map
198  m_pythiaidmap[ID] = pp;
199  }
200  //
201  return rebuild();
202  }
203  // =============================================================================
205  // =============================================================================
206  namespace {
207  template <class MAP>
208  void _remove_( MAP& m, const ParticleProperty* pp ) {
209  auto i = std::find_if( m.begin(), m.end(), [&]( typename MAP::const_reference i ) { return i.second == pp; } );
210  if ( i != m.end() ) { m.erase( i ); }
211  }
212  } // namespace
213  // ============================================================================
215  if ( !pp ) { return StatusCode::FAILURE; }
216 
217  _remove_( m_idmap, pp );
218  _remove_( m_namemap, pp );
219  _remove_( m_stdhepidmap, pp );
220  _remove_( m_pythiaidmap, pp );
221  //
222  return rebuild();
223  }
224  // ============================================================================
226  // ============================================================================
228 
229  // parse "the main" file
230  StatusCode sc = parse( m_filename );
231  if ( sc.isFailure() ) { return sc; }
232 
233  // parse "other" files
234  for ( auto& file : m_other ) {
235  sc = parse( file );
236  if ( sc.isFailure() ) { return sc; }
237  }
238 
239  // Now check that the file format was consistent with what parser
240  // expected
241  if ( m_namemap.empty() ) {
242  error() << "Format of input file inconsistent with what expected"
243  << " - Check you are using ParticleData.txt" << endmsg;
244  return StatusCode::FAILURE;
245  }
246 
247  return sc;
248  }
249  // ============================================================================
251  auto infile = ( m_fileAccess ? m_fileAccess->open( file ) : nullptr );
252  if ( !infile ) {
253  error() << "Unable to open properties file : " << file << endmsg;
254  return StatusCode::FAILURE;
255  }
256 
258  info() << "Opened particle properties file : " << file << endmsg;
259 
261  tokens.reserve( 9 );
263  while ( std::getline( *infile, line ) ) {
264  // parse each line of the file (comment lines begin with # in the cdf
265  // file,
266  if ( line.front() == '#' ) continue;
267 
268  tokens.clear();
269  ba::trim_left_if( line, ba::is_space() );
270  ba::split( tokens, line, ba::is_space(), boost::token_compress_on );
271  if ( tokens.size() != 9 ) continue;
272 
273  auto gid = std::stoi( tokens[1] );
274  auto jid = std::stoi( tokens[2] );
275  // Change the particles that do not correspond to a pdg number
276  if ( jid == 0 ) jid = 10000000 * gid;
277 
278  // add a particle property
279  sc = push_back( tokens[0], gid, jid, std::stod( tokens[3] ), std::stod( tokens[4] ) * Gaudi::Units::GeV,
280  std::stod( tokens[5] ) * Gaudi::Units::s, tokens[6], std::stoi( tokens[7] ),
281  std::stod( tokens[8] ) * Gaudi::Units::GeV );
282 
283  if ( sc.isFailure() ) {
284  error() << "Error from ParticlePropertySvc::push_back for particle='" << tokens[0] << "'" << endmsg;
285  }
286  }
287  return StatusCode::SUCCESS;
288  }
289  // ============================================================================
295  // ============================================================================
297  if ( !pp ) { return nullptr; }
298  const int ID = pp->pdgID();
299  const int antiID = -1 * ID;
300  for ( const auto& ap : m_vectpp ) {
301  if ( ap && antiID == ap->pdgID() ) { return ap; } // RETURN
302  };
303  //
304  return pp; // RETURN
305  }
306  // ============================================================================
311  // ============================================================================
313  // initialize particle<-->antiParticle relations
314  for ( auto& pp : m_vectpp ) {
315  if ( !pp ) { continue; } // CONTINUE
316  const ParticleProperty* ap = anti( pp );
317  if ( ap ) { pp->setAntiParticle( ap ); }
318  }
319  return StatusCode::SUCCESS;
320  }
321  // ============================================================================
323  // ============================================================================
324  namespace {
326  template <typename MAP, typename SET>
327  void _load_( MAP& m, SET& result ) {
328  for ( auto i = m.begin(); m.end() != i; ++i ) { result.insert( i->second ); }
329  }
330  } // namespace
331  // ============================================================================
333  std::set<mapped_type> local;
334  m_vectpp.clear();
335  m_vectpp.reserve( m_idmap.size() + 100 );
336  // load information from maps into the set
337  _load_( m_idmap, local );
338  _load_( m_namemap, local );
339  _load_( m_stdhepidmap, local );
340  _load_( m_pythiaidmap, local );
341  // load information from set to the linear container vector
342  std::copy( std::begin( local ), std::end( local ), std::back_inserter( m_vectpp ) );
343  return setAntiParticles();
344  }
345  // ============================================================================
346  // treat additional particles
347  // ============================================================================
349  // loop over all "explicit" particles
350  for ( const auto& item : m_particles ) {
351  std::istringstream input( item );
352  // get the name
353  std::string p_name;
354  int p_geant;
355  int p_jetset;
356  double p_charge;
357  double p_mass;
358  double p_ltime;
359  std::string p_evtgen;
360  int p_pythia;
361  double p_maxwid;
362  if ( input >> p_name >> p_geant >> p_jetset >> p_charge >> p_mass >> p_ltime >> p_evtgen >> p_pythia >>
363  p_maxwid ) {
364  always() << " Add/Modify the particle: "
365  << " name='" << p_name << "'"
366  << " geant=" << p_geant << " jetset=" << p_jetset << " charge=" << p_charge << " mass=" << p_mass
367  << " ltime=" << p_ltime << " evtgen='" << p_evtgen << "'"
368  << " pythia=" << p_pythia << " maxwid=" << p_maxwid << endmsg;
369  //
370  StatusCode sc = push_back( p_name, p_geant, p_jetset, p_charge, p_mass * Gaudi::Units::GeV,
371  p_ltime * Gaudi::Units::s, p_evtgen, p_pythia, p_maxwid * Gaudi::Units::GeV );
372  if ( sc.isFailure() ) { return sc; } // RETURN
373  } else {
374  error() << " could not parse '" << item << "'" << endmsg;
375  return StatusCode::FAILURE; // RETURN
376  }
377  }
378  //
379  return StatusCode::SUCCESS;
380  }
381 // ============================================================================
382 #ifdef __ICC
383 // disable icc remark #1572: floating-point equality and inequality comparisons are unreliable
384 // The comparison are meant
385 # pragma warning( push )
386 # pragma warning( disable : 1572 )
387 #endif
389  //
390  if ( o == n ) { return false; }
391  //
392  auto& log = msgStream();
393  log << l;
394  if ( !o || !n ) {
395  log << MSG::WARNING << " ParticleProperty* point to NULL" << endmsg;
396  return true; // RETURN
397  }
398  //
399  bool result = false;
400  if ( o->particle() != n->particle() ) {
401  result = true;
402  log << " Name:'" << o->particle() << "'/'" << n->particle() << "'";
403  }
404  if ( o->geantID() != n->geantID() ) {
405  result = true;
406  log << " G3ID:" << o->geantID() << "/" << n->geantID() << "'";
407  }
408  if ( o->pdgID() != n->pdgID() ) {
409  result = true;
410  log << " PDGID:" << o->pdgID() << "/" << n->pdgID() << "'";
411  }
412  if ( o->pythiaID() != n->pythiaID() ) {
413  result = true;
414  log << " PYID:" << o->pythiaID() << "/" << n->pythiaID() << "'";
415  }
416  if ( o->charge() != n->charge() ) {
417  result = true;
418  log << " Q:" << o->charge() << "/" << n->charge() << "'";
419  }
420  if ( o->mass() != n->mass() ) {
421  result = true;
422  log << " M:" << o->mass() << "/" << n->mass() << "'";
423  }
424  if ( o->lifetime() != n->lifetime() ) {
425  result = true;
426  log << " T:" << o->lifetime() << "/" << n->lifetime() << "'";
427  }
428  if ( o->evtGenName() != n->evtGenName() ) {
429  result = true;
430  log << " EvtGen:" << o->evtGenName() << "/" << n->evtGenName() << "'";
431  }
432  if ( o->maxWidth() != n->maxWidth() ) {
433  result = true;
434  log << " WMAX:" << o->maxWidth() << "/" << n->maxWidth() << "'";
435  }
436  if ( result ) { log << endmsg; }
437  //
438  return result;
439  }
440 } // namespace Gaudi
441 #ifdef __ICC
442 // re-enable icc remark #1572
443 # pragma warning( pop )
444 #endif
445 // ============================================================================
446 // The END
447 // ============================================================================
GAUDI_API std::string getEnv(const char *var)
get a particular environment variable (returning "UNKNOWN" if not set)
Definition: System.cpp:379
bool diff(const ParticleProperty *o, const ParticleProperty *n, const MSG::Level l=MSG::DEBUG) const
StatusCode rebuild()
rebuild "the linear container" from the map
StatusCode initialize() override
Definition: Service.cpp:70
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:35
constexpr double s
StatusCode finalize() override
Definition: Service.cpp:174
This service provides access to particle properties.
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:341
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.
constexpr static const auto SUCCESS
Definition: StatusCode.h:96
StatusCode initialize() override
Initialise the service.
STL namespace.
int pythiaID() const
Get the Pythia ID.
MapName m_namemap
Map for particle names.
StatusCode parse()
Parses the file and fill all the maps.
T end(T... args)
MsgStream & always() const
shortcut for the method msgStream(MSG::ALWAYS)
MsgStream & info() const
shortcut for the method msgStream(MSG::INFO)
#define SET(x)
SmartIF< IFileAccess > m_fileAccess
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.
#define DECLARE_COMPONENT(type)
MsgStream & error() const
shortcut for the method msgStream(MSG::ERROR)
std::set< std::string > m_replaced
double maxWidth() const
Get the max width deviation.
const ParticleProperty * anti(const ParticleProperty *pp) const
helper (protected) function to find an antiparticle for the given particle ID (StdHepID)
This class is used for returning status codes from appropriate routines.
Definition: StatusCode.h:61
constexpr double m
int pdgID() const
Get the PDG (= JETSET) ID.
MsgStream & debug() const
shortcut for the method msgStream(MSG::DEBUG)
T clear(T... args)
MsgStream & msgStream() const
Return an uninitialized MsgStream.
StatusCode setProperties()
Method for setting declared properties to the values specified for the job.
Definition: Service.cpp:290
MapStdHepID m_stdhepidmap
Map for StdHep Ids.
dictionary l
Definition: gaudirun.py:543
T insert(T... args)
T find(T... args)
T size(T... args)
STL class.
const std::string & evtGenName() const
Get the EvtGen name.
T begin(T... args)
T back_inserter(T... args)
Gaudi::Property< std::vector< std::string > > m_other
constexpr static const auto FAILURE
Definition: StatusCode.h:97
int geantID() const
Get the GEANT3 ID.
std::set< std::unique_ptr< ParticleProperty > > m_owned
MapID m_idmap
Map for geant IDs.
Gaudi::Property< std::string > m_filename
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:93
Gaudi::Property< std::vector< std::string > > m_particles
constexpr double GeV
void reset(TYPE *ptr=nullptr)
Set the internal pointer to the passed one disposing of the old one.
Definition: SmartIF.h:96
bool isFailure() const
Definition: StatusCode.h:141
const std::string & particle() const
Get the particle name.
StatusCode setAntiParticles()
helper (protected) function to set the valid particle<-->antiparticle relations
VectPP m_vectpp
Vector of all particle properties.
T stoi(T... args)
double mass() const
Get the particle mass.
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...
Header file for std:chrono::duration-based Counters.
Definition: __init__.py:1
MsgStream & endmsg(MsgStream &s)
MsgStream Modifier: endmsg. Calls the output method of the MsgStream.
Definition: MsgStream.h:202
double lifetime() const
Get the particle lifetime.
MapPythiaID m_pythiaidmap
Map for Pythia Ids.
double charge() const
Get the particle charge.
T reserve(T... args)