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