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