ParticlePropertySvc.cpp
Go to the documentation of this file.
1 // ============================================================================
2 // Include files
3 // ============================================================================
4 // STD&STL
5 // ============================================================================
6 #include <cctype>
7 #include <fstream>
8 #include "boost/algorithm/string/split.hpp"
9 #include "boost/algorithm/string/trim.hpp"
10 #include "boost/algorithm/string/classification.hpp"
11 namespace ba = boost::algorithm;
12 // ============================================================================
13 // GaudiKernel
14 // ============================================================================
16 #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  //@FIXME/@TODO remove once we can assume C++14...
30  template <typename T, class... Args>
31  std::unique_ptr<T> make_unique_(Args&&... args) {
32  return std::unique_ptr<T>(new T(std::forward<Args>(args)...));
33  }
34 }
35 namespace Gaudi {
39 DECLARE_COMPONENT(ParticlePropertySvc)
40 // ============================================================================
52 // ============================================================================
53 ParticlePropertySvc::ParticlePropertySvc
54 ( const std::string& name ,
55  ISvcLocator* svc )
56  : base_class( name, svc )
57 {
59  // Redefine the default name:
60  if( System::getEnv("PARAMFILESROOT", m_filename) )
61  {
62  m_filename += "/data/ParticleTable.txt";
63  }
64  //
65  declareProperty ( "ParticlePropertiesFile" , m_filename ) ;
66  declareProperty ( "OtherFiles" , m_other ) ;
67  declareProperty ( "Particles" , m_particles ) ;
68 }
69 // ============================================================================
71 // ============================================================================
73 {
75  if ( sc.isFailure() ) { return sc ; }
76 
77 
78  sc = setProperties();
79  if ( sc.isFailure() )
80  {
81  error() << " Could not set the properties " << endmsg ;
82  return sc ;
83  }
84 
85  m_fileAccess = service("VFSSvc");
86  if ( !m_fileAccess )
87  {
88  error() << " Cannot retrieve the VFS service " << endmsg ;
89  return StatusCode::FAILURE ;
90  }
91 
92  sc = parse();
93  if ( sc.isFailure() )
94  {
95  error() << " Could not parse the file " << endmsg ;
96  return sc ;
97  }
98  if ( !m_particles.empty() )
99  {
100  sc = addParticles () ;
101  if ( sc.isFailure() )
102  {
103  error() << " Could not treat particles! " << endmsg ;
104  return sc ;
105  }
106  }
107  debug() << "ParticleProperties parsed successfully" << endmsg;
108 
109  debug() << "Access properties" << endmsg;
110  // For debugging purposes print out the size of the internal maps
111  // particle name as key: all particles in database are present here
112  debug() << "NameMap size =" << m_namemap.size() << endmsg;
113  // Geant3 ID as key: all particles in database are present here
114  debug() << "GeantID Map size =" << m_idmap.size() << endmsg;
115  // StdHep ID as key: some particles have no valid StdHep ID
116  debug() << "StdHepID Map size =" << m_stdhepidmap.size()
117  << endmsg;
118  // Pythia ID as key: some particles are not defined in Pythia
119  debug() << "PythiaID Map size =" << m_pythiaidmap.size()
120  << endmsg;
121 
122  if ( !m_replaced.empty() )
123  {
124  info()
125  << "Properties have been redefined for "
126  << m_replaced.size() << " particles : "
128  << endmsg ;
129  }
130 
131  return StatusCode::SUCCESS ;
132 }
133 // =============================================================================
135 // =============================================================================
137 {
138  if ( !m_other.empty() )
139  {
140  info() << "Additional Properties have been read from files: "
142  << endmsg ;
143  }
144 
145  if ( !m_replaced.empty() )
146  {
147  always() << "Properties have been redefined for "
148  << m_replaced.size() << " particles : "
150  << endmsg ;
151  }
152 
154 
156  return Service::finalize () ;
157 }
158 // =============================================================================
160 // =============================================================================
162 ( const std::string& particle ,
163  int geantId ,
164  int jetsetId ,
165  double charge ,
166  double mass ,
167  double tlife ,
168  const std::string& evtName ,
169  int pythiaId ,
170  double maxWidth )
171 {
172  //
173  auto i = m_owned.insert(
174  make_unique_<ParticleProperty>( particle , geantId , jetsetId ,
175  charge , mass , tlife ,
176  evtName , pythiaId , maxWidth )
177  ) ;
178  //
179  return i.second ? push_back( i.first->get() ) : StatusCode::FAILURE;
180 }
181 // =============================================================================
183 // =============================================================================
185 {
186  if ( !pp ) { return StatusCode::FAILURE ; }
187  //
188  { // try to add into Geant(3)ID map
189  const int ID = pp->geantID() ;
190  // is this already in the map?
191  auto ifind = m_idmap.find( ID ) ;
192  if ( m_idmap.end() != ifind && 0 != m_idmap[ ID ])
193  {
194  diff ( ifind->second , pp ) ;
195  m_replaced.insert( m_idmap[ ID ]->particle() ) ;
196  }
197  // put it into the map
198  m_idmap[ ID ] = pp ;
199  }
200  //
201  { // try to add into Name map
202  const std::string& particle = pp->particle() ;
203  // is this already in the map?
204  auto ifind = m_namemap.find( particle ) ;
205  if ( ifind != m_namemap.end() && ifind->second )
206  {
207  diff ( ifind->second , pp ) ;
208  m_replaced.insert( ifind->second->particle() ) ;
209  }
210  // put it into the map
211  m_namemap[ particle ] = pp ;
212  }
213  //
214  // add to StdHep map only if StdHep ID different from zero and if
215  // not Cerenkov (StdHep ID = gamma)
216  if ( 0 != pp->jetsetID() && "Tcherenkov" != pp->particle() )
217  { // try to add into StdHepID map
218  const int ID = pp->jetsetID() ;
219  // is this already in the map?
220  auto ifind = m_stdhepidmap.find( ID ) ;
221  if ( m_stdhepidmap.end() != ifind && ifind->second )
222  {
223  diff ( ifind->second , pp ) ;
224  m_replaced.insert( ifind->second->particle() ) ;
225  }
226  // put it into the map
227  m_stdhepidmap[ ID ] = pp ;
228  }
229  //
230  // add to Pythia map only if Pythia ID is different from
231  // zero ( StdHep id is always different from zero in this case )
232  if ( 0 != pp->pythiaID() &&
233  0 != pp->jetsetID() &&
234  "Tcherenkov" != pp->particle() )
235  { // try to add into PythiaID map
236  const int ID = pp->pythiaID() ;
237  // is this already in the map?
238  auto ifind = m_pythiaidmap.find( ID ) ;
239  if ( m_pythiaidmap.end() != ifind && ifind->second )
240  {
241  diff ( ifind->second , pp ) ;
242  m_replaced.insert( ifind->second ->particle() ) ;
243  }
244  // put it into the map
245  m_pythiaidmap[ ID ] = pp ;
246  }
247  //
248  return rebuild() ;
249 }
250 // =============================================================================
252 // =============================================================================
253 namespace
254 {
255  template <class MAP>
256  void _remove_ ( MAP& m , const ParticleProperty* pp )
257  {
258  auto i = std::find_if( m.begin(), m.end(),
259  [&](typename MAP::const_reference i) { return i.second == pp; } );
260  if ( i != m.end() ) { m.erase ( i ) ; }
261  }
262 }
263 // ============================================================================
265 {
266  if ( !pp ) { return StatusCode::FAILURE ; }
267 
268  _remove_ ( m_idmap , pp ) ;
269  _remove_ ( m_namemap , pp ) ;
270  _remove_ ( m_stdhepidmap , pp ) ;
271  _remove_ ( m_pythiaidmap , pp ) ;
272  //
273  return rebuild() ;
274 }
275 // ============================================================================
277 // ============================================================================
279 {
280 
281  // parse "the main" file
282  StatusCode sc = parse ( m_filename ) ;
283  if ( sc.isFailure() ) { return sc ; }
284 
285  // parse "other" files
286  for ( auto& file : m_other )
287  {
288  sc = parse ( file ) ;
289  if ( sc.isFailure() ) { return sc ; }
290  }
291 
292  // Now check that the file format was consistent with what parser
293  // expected
294  if ( m_namemap.empty() )
295  {
296  error()
297  << "Format of input file inconsistent with what expected"
298  << " - Check you are using ParticleData.txt" << endmsg;
299  return StatusCode::FAILURE;
300  }
301 
302  return sc;
303 }
304 // ============================================================================
306 {
307  auto infile = ( m_fileAccess ? m_fileAccess->open(file) : nullptr );
308  if ( !infile )
309  {
310  error() << "Unable to open properties file : " << file
311  << endmsg;
312  return StatusCode::FAILURE ;
313  }
314 
316  info() << "Opened particle properties file : " << file << endmsg;
317 
318  std::vector<std::string> tokens; tokens.reserve(9);
320  while( std::getline( *infile, line ) )
321  {
322  // parse each line of the file (comment lines begin with # in the cdf
323  // file,
324  if ( line.front() == '#' ) continue;
325 
326  tokens.clear();
327  ba::trim_left_if( line, ba::is_space() );
328  ba::split( tokens, line, ba::is_space() , boost::token_compress_on );
329  if (tokens.size()!=9) continue;
330 
331  auto gid = std::stoi( tokens[1] );
332  auto jid = std::stoi( tokens[2] );
333  // Change the particles that do not correspond to a pdg number
334  if ( jid == 0 ) jid = 10000000*gid;
335 
336  // add a particle property
337  sc = push_back( tokens[0], gid, jid,
338  std::stod( tokens[3] ),
339  std::stod( tokens[4] ) * Gaudi::Units::GeV,
340  std::stod( tokens[5] ) * Gaudi::Units::s,
341  tokens[6],
342  std::stoi( tokens[7] ),
343  std::stod( tokens[8] ) * Gaudi::Units::GeV ) ;
344 
345  if ( sc.isFailure() )
346  {
347  error()
348  << "Error from ParticlePropertySvc::push_back for particle='"
349  << tokens[0] << "'" << endmsg ;
350  }
351  }
352  return StatusCode::SUCCESS ;
353 }
354 // ============================================================================
360 // ============================================================================
361 const ParticleProperty*
363 {
364  if ( !pp ) { return nullptr ; }
365  const int ID = pp->pdgID() ;
366  const int antiID = -1 * ID ;
367  for ( const auto& ap : m_vectpp )
368  {
369  if ( ap && antiID == ap->pdgID() ) { return ap ; } // RETURN
370  };
371  //
372  return pp ; // RETURN
373 }
374 // ============================================================================
379 // ============================================================================
381 {
382  // initialize particle<-->antiParticle relations
383  for ( auto& pp : m_vectpp )
384  {
385  if ( !pp ) { continue ; } // CONTINUE
386  const ParticleProperty* ap = anti ( pp ) ;
387  if ( ap ) { pp->setAntiParticle( ap ) ; }
388  }
389  return StatusCode::SUCCESS ;
390 }
391 // ============================================================================
393 // ============================================================================
394 namespace
395 {
397  template <typename MAP, typename SET>
398  void _load_ ( MAP& m , SET& result )
399  {
400  for ( auto i = m.begin() ; m.end() != i ; ++i )
401  { result.insert ( i->second ); }
402  }
403 }
404 // ============================================================================
406 {
407  std::set<mapped_type> local ;
408  m_vectpp.clear() ;
409  m_vectpp.reserve ( m_idmap.size() + 100 ) ;
410  // load information from maps into the set
411  _load_ ( m_idmap , local ) ;
412  _load_ ( m_namemap , local ) ;
413  _load_ ( m_stdhepidmap , local ) ;
414  _load_ ( m_pythiaidmap , local ) ;
415  // load information from set to the linear container vector
417  return setAntiParticles() ;
418 }
419 // ============================================================================
420 // treat additional particles
421 // ============================================================================
423 {
424  // loop over all "explicit" particles
425  for ( const auto& item : m_particles )
426  {
427  std::istringstream input( item ) ;
428  // get the name
429  std::string p_name ;
430  int p_geant ;
431  int p_jetset ;
432  double p_charge ;
433  double p_mass ;
434  double p_ltime ;
435  std::string p_evtgen ;
436  int p_pythia ;
437  double p_maxwid ;
438  if ( input
439  >> p_name
440  >> p_geant
441  >> p_jetset
442  >> p_charge
443  >> p_mass
444  >> p_ltime
445  >> p_evtgen
446  >> p_pythia
447  >> p_maxwid )
448  {
449  always()
450  << " Add/Modify the particle: "
451  << " name='" << p_name << "'"
452  << " geant=" << p_geant
453  << " jetset=" << p_jetset
454  << " charge=" << p_charge
455  << " mass=" << p_mass
456  << " ltime=" << p_ltime
457  << " evtgen='" << p_evtgen << "'"
458  << " pythia=" << p_pythia
459  << " maxwid=" << p_maxwid << endmsg ;
460  //
462  ( p_name ,
463  p_geant ,
464  p_jetset ,
465  p_charge ,
466  p_mass * Gaudi::Units::GeV ,
467  p_ltime * Gaudi::Units::s ,
468  p_evtgen ,
469  p_pythia ,
470  p_maxwid * Gaudi::Units::GeV ) ;
471  if ( sc.isFailure() ) { return sc ; } // RETURN
472  }
473  else
474  {
475  error()
476  << " could not parse '" << item << "'" << endmsg ;
477  return StatusCode::FAILURE ; // RETURN
478  }
479  }
480  //
481  return StatusCode::SUCCESS ;
482 }
483 // ============================================================================
484 #ifdef __ICC
485 // disable icc remark #1572: floating-point equality and inequality comparisons are unreliable
486 // The comparison are meant
487 #pragma warning(push)
488 #pragma warning(disable:1572)
489 #endif
491 ( const ParticleProperty* o ,
492  const ParticleProperty* n ,
493  const MSG::Level l ) const
494 {
495  //
496  if ( o == n ) { return false ; }
497  //
498  auto& log = msgStream();
499  log << l ;
500  if ( !o || !n )
501  {
502  log << MSG::WARNING << " ParticleProperty* point to NULL" << endmsg ;
503  return true ; // RETURN
504  }
505  //
506  bool result = false ;
507  if ( o -> particle () != n -> particle () )
508  {
509  result = true ;
510  log << " Name:'" << o -> particle () << "'/'" << n -> particle () << "'" ;
511  }
512  if ( o -> geantID () != n -> geantID () )
513  {
514  result = true ;
515  log << " G3ID:" << o -> geantID () << "/" << n -> geantID () << "'" ;
516  }
517  if ( o -> pdgID () != n -> pdgID () )
518  {
519  result = true ;
520  log << " PDGID:" << o -> pdgID () << "/" << n -> pdgID () << "'" ;
521  }
522  if ( o -> pythiaID () != n -> pythiaID () )
523  {
524  result = true ;
525  log << " PYID:" << o -> pythiaID () << "/" << n -> pythiaID () << "'" ;
526  }
527  if ( o -> charge () != n -> charge () )
528  {
529  result = true ;
530  log << " Q:" << o -> charge () << "/" << n -> charge () << "'" ;
531  }
532  if ( o -> mass () != n -> mass () )
533  {
534  result = true ;
535  log << " M:" << o -> mass () << "/" << n -> mass () << "'" ;
536  }
537  if ( o -> lifetime () != n -> lifetime () )
538  {
539  result = true ;
540  log << " T:" << o -> lifetime () << "/" << n -> lifetime () << "'" ;
541  }
542  if ( o -> evtGenName () != n -> evtGenName () )
543  {
544  result = true ;
545  log << " EvtGen:" << o -> evtGenName () << "/" << n -> evtGenName () << "'" ;
546  }
547  if ( o -> maxWidth () != n -> maxWidth () )
548  {
549  result = true ;
550  log << " WMAX:" << o -> maxWidth () << "/" << n -> maxWidth () << "'" ;
551  }
552  if ( result ) { log << endmsg ; }
553  //
554  return result ;
555 }
556 
557 }
558 #ifdef __ICC
559 // re-enable icc remark #1572
560 #pragma warning(pop)
561 #endif
562 // ============================================================================
563 // The END
564 // ============================================================================
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:617
StatusCode rebuild()
rebuild "the linear container" from the map
StatusCode initialize() override
Definition: Service.cpp:68
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:193
MsgStream & info() const
shortcut for the method msgStream(MSG::INFO)
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:371
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)
Files m_other
additional file names
#define SET(x)
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:36
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:26
constexpr double m
Definition: SystemOfUnits.h:93
std::string m_filename
Filename of the particle properties file.
T clear(T...args)
list file
Definition: ana.py:160
StatusCode setProperties()
Method for setting declared properties to the values specified for the job.
Definition: Service.cpp:363
MapStdHepID m_stdhepidmap
Map for StdHep Ids.
dictionary l
Definition: gaudirun.py:421
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.
list args
Definition: gaudirun.py:290
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)
tuple item
print s1,s2
Definition: ana.py:146
MapID m_idmap
Map for geant IDs.
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:144
void setAntiParticle(const ParticleProperty *p)
set the pointer to the antiparticle
constexpr double GeV
void reset(TYPE *ptr=nullptr)
Set the internal pointer to the passed one disposing of the old one.
Definition: SmartIF.h:88
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)
list i
Definition: ana.py:128
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:244
MapPythiaID m_pythiaidmap
Map for Pythia Ids.
T reserve(T...args)