ATLAS Offline Software
HepMcParticleLink.cxx
Go to the documentation of this file.
1 /*
2  Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
3 */
4 
5 
6 
7 // Don't use the StoreGateSvc interface here, so that this code
8 // will work in root too.
9 
13 #include "AtlasHepMC/GenParticle.h"
14 #include "AtlasHepMC/GenEvent.h"
16 #include "GaudiKernel/MsgStream.h"
18 #include "SGTools/DataProxy.h"
19 #include <sstream>
20 #include <cassert>
21 
22 
23 namespace {
24 
25 
29 constexpr int NKEYS = 5;
30 const
31 std::string s_keys[NKEYS] = {"TruthEvent","G4Truth","GEN_AOD","GEN_EVENT","Bkg_TruthEvent"};
32 
33 
41 std::atomic<unsigned> s_hint = NKEYS;
42 
43 
44 const unsigned short CPTRMAXMSGCOUNT = 100;
45 
46 
47 } // anonymous namespace
48 
49 
50 //**************************************************************************
51 // ExtendedBarCode
52 //
53 
54 
58 char
60 {
61  static const char codes[EBC_NSUPP] = {'a', 'b'};
62  assert (suppEnum < EBC_NSUPP);
63  return codes[suppEnum];
64 }
65 
66 
72 {
73  switch (suppChar) {
74  case 'a': return EBC_UNSUPPRESSED;
75  case 'b': return EBC_PU_SUPPRESSED;
76  default:
77  // Should not reach this
78  MsgStream log (Athena::getMessageSvc(), "HepMcParticleLink");
79  log << MSG::ERROR << " Wrong truth Suppression Char (" << std::string(&suppChar,1) << ") set in HepMcParticleLink ExtendedBarCode object !!!" << endmsg;
80  }
81  return EBC_UNSUPPRESSED;
82 }
83 
84 
89 {
90  os << "Event index " ;
91  index_type event_number, position;
92  eventIndex (event_number, position);
93  if (position != UNDEFINED) {
94  os << position << " (position in collection) ";
95  }
96  else {
97  os << event_number << " (event number) ";
98  }
99  os << ", Unique ID " ;
100  barcode_type particle_id, particle_barcode;
101  uniqueID (particle_id, particle_barcode);
102  if (particle_barcode == 0 && particle_id == 0) {
103  os << " 0 (id/barcode) ";
104  }
105  else if (particle_barcode != UNDEFINEDBC) {
106  os << particle_barcode << " (barcode) ";
107  }
108  else {
109  os << particle_id << " (id) ";
110  }
111  os << ", McEventCollection "
113 }
114 
115 
120 {
121  std::ostringstream ss;
122  print (ss);
123  os << ss.str();
124 }
125 
126 
127 //**************************************************************************
128 // HepMcParticleLink
129 //
130 
131 
145  PositionFlag positionFlag /*= IS_EVENTNUM*/,
146  IProxyDict* sg /*= SG::CurrentEventStore::store()*/)
147  : m_store (sg),
148  m_ptr (part),
149  m_extBarcode((nullptr != part) ? HepMC::uniqueID(part) : 0, eventIndex, positionFlag, IS_ID)
150 {
151  assert(part);
152 
153  if (part != nullptr && positionFlag == IS_POSITION) {
154  if (const McEventCollection* pEvtColl = retrieveMcEventCollection(sg)) {
155  const HepMC::GenEvent *pEvt = pEvtColl->at (eventIndex);
156  m_extBarcode.makeIndex (pEvt->event_number(), eventIndex);
157  }
158  else {
159  MsgStream log (Athena::getMessageSvc(), "HepMcParticleLink");
160  log << MSG::WARNING << "cptr: McEventCollection not found" << endmsg;
161  }
162  }
163 }
164 
165 
170  return m_extBarcode.linkIsNull();
171 }
172 
173 
178 {
179  // dummy link
180  const bool is_valid = m_ptr.isValid();
181  if (!is_valid && !m_store) {
182  return nullptr;
183  }
184  if (is_valid) {
185  return *m_ptr.ptr();
186  }
187  if (m_extBarcode.linkIsNull()) {
188  #if 0
189  MsgStream log (Athena::getMessageSvc(), "HepMcParticleLink");
190  log << MSG::DEBUG
191  << "cptr: no truth particle associated with this hit (barcode==0)."
192  << " Probably this is a noise hit" << endmsg;
193  #endif
194  return nullptr;
195  }
196  IProxyDict* sg = m_store;
197  if (!sg) {
199  }
200  if (const McEventCollection* pEvtColl = retrieveMcEventCollection(sg)) {
201  const HepMC::GenEvent *pEvt = nullptr;
202  index_type event_number, position;
203  m_extBarcode.eventIndex (event_number, position);
204  if (event_number == 0) {
205  pEvt = pEvtColl->at(0);
206  }
207  else if (position != ExtendedBarCode::UNDEFINED) {
208  if (position < pEvtColl->size()) {
209  pEvt = pEvtColl->at (position);
210  }
211  else {
212  #if 0
213  MsgStream log (Athena::getMessageSvc(), "HepMcParticleLink");
214  log << MSG::WARNING << "cptr: position = " << position << ", McEventCollection size = "<< pEvtColl->size() << endmsg;
215  #endif
216  return nullptr;
217  }
218  }
219  else {
220  pEvt = pEvtColl->find (event_number);
221  }
222 
223  if (nullptr != pEvt) {
224  // Be sure to update m_extBarcode before m_ptrs;
225  // otherwise, the logic in eventIndex() won't work correctly.
226  if (position != ExtendedBarCode::UNDEFINED) {
227  m_extBarcode.makeIndex (pEvt->event_number(), position);
228  }
229  if (event_number == 0) {
230  m_extBarcode.makeIndex (pEvt->event_number(), position);
231  }
232  if ( !m_extBarcode.linkIsNull() ) { // Check that either the ID or Barcode is non-zero or undefined
233  barcode_type particle_id, particle_barcode;
234  m_extBarcode.uniqueID (particle_id, particle_barcode);
235  if (particle_id == ExtendedBarCode::UNDEFINEDBC) {
236  // barcode to GenParticle
237  const HepMC::ConstGenParticlePtr p = HepMC::barcode_to_particle(pEvt,int(particle_barcode));
238  if (p) {
239  int genParticleID = HepMC::uniqueID(p);
240  if (genParticleID > -1) {
241  particle_id = static_cast<barcode_type>(genParticleID);
242  m_extBarcode.makeID (particle_id, particle_barcode);
243  }
244  m_ptr.set (p);
245  return p;
246  }
247  }
248  else {
249  // id to GenParticle
250 #ifdef HEPMC3
251  const auto &particles = pEvt->particles();
252  if (particle_id-1 < particles.size()) {
253  const HepMC::ConstGenParticlePtr p = particles[particle_id-1];
254  if (p) {
255  m_ptr.set (p);
256  return p;
257  }
258  }
259 #else
260  const HepMC::ConstGenParticlePtr p = HepMC::barcode_to_particle(pEvt,int(particle_id)); // For HepMC2 "id" == barcode
261  if (p) {
262  m_ptr.set (p);
263  return p;
264  }
265 #endif
266  }
267  }
268  } else {
269  MsgStream log (Athena::getMessageSvc(), "HepMcParticleLink");
270  if (position != ExtendedBarCode::UNDEFINED) {
271  log << MSG::WARNING
272  << "cptr: Mc Truth not stored for event at " << position
273  << endmsg;
274  } else {
275  log << MSG::WARNING
276  << "cptr: Mc Truth not stored for event with event number " << event_number
277  << endmsg;
278  }
279  }
280  } else {
281  MsgStream log (Athena::getMessageSvc(), "HepMcParticleLink");
282  log << MSG::WARNING << "cptr: McEventCollection not found" << endmsg;
283  }
284  return nullptr;
285 }
286 
287 
292 {
293  // if m_BC is zero (delta rays), then just return that same for barcode and id
294  if (m_extBarcode.uid()) {
295  // dummy link
296  if (!m_ptr.isValid() && !m_store) {
297  return 0; // TODO Decide if this is a good default - constant from MagicNumbers.h instead?
298  }
299 
300  barcode_type particle_id, particle_barcode;
301  m_extBarcode.uniqueID (particle_id, particle_barcode);
302  if (particle_id == ExtendedBarCode::UNDEFINEDBC) {
303  (void) cptr(); // FIXME be careful to avoid an infinite loop of calls here
304  m_extBarcode.uniqueID (particle_id, particle_barcode);
305  }
306  if (particle_id != ExtendedBarCode::UNDEFINEDBC) {
307  return particle_id;
308  }
309  }
310  return 0;
311 }
312 
313 
319 {
320  // if m_BC is zero (delta rays), then just return that same for barcode and id
321  if (m_extBarcode.uid()) {
322  barcode_type particle_id, particle_barcode;
323  m_extBarcode.uniqueID (particle_id, particle_barcode);
324  if (particle_barcode != ExtendedBarCode::UNDEFINEDBC) {
325  return int(particle_barcode);
326  }
327  // dummy link
328  if (!m_ptr.isValid() && !m_store) {
329  return 0; // TODO Decide if this is a good default - constant from MagicNumbers.h instead?
330  }
331  // we will need to look up the barcode from the GenParticle
332  (void) eventIndex(); // FIXME be careful to avoid an infinite loop of calls here
333  if (cptr()) {
334  return HepMC::barcode(cptr());
335  }
336  }
337  return 0;
338 }
339 
340 
346 {
347  // dummy link
348  if (!m_ptr.isValid() && !m_store) {
350  }
351 
352  index_type event_number, event_position;
353  m_extBarcode.eventIndex (event_number, event_position);
354  if (event_number == ExtendedBarCode::UNDEFINED) {
355  const HepMC::GenEvent* pEvt{};
357  if (event_position < coll->size()) {
358  pEvt = coll->at (event_position);
359  }
360  if (pEvt) {
361  const int genEventNumber = pEvt->event_number();
362  // Be sure to update m_extBarcode before m_ptr.
363  // Otherwise, if two threads run this method simultaneously,
364  // one thread could see event_number == UNDEFINED, but where m_ptr
365  // is already updated so we get nullptr back for sg.
366  if (genEventNumber > -1) {
367  event_number = static_cast<index_type>(genEventNumber);
368  m_extBarcode.makeIndex (event_number, event_position);
369  return event_number;
370  }
371  if (barcode() != 0) {
373  if (pp) {
374  m_ptr.set (pp);
375  }
376  }
377  }
378  }
379  }
380  // Don't trip the assertion for a null link.
381  if ( m_extBarcode.linkIsNull() )
382  {
383  return (event_number != ExtendedBarCode::UNDEFINED) ? event_number : 0;
384  }
385  // Attempt to find the GenParticle
386  cptr();
387  // Check if event_number is valid once more
388  m_extBarcode.eventIndex (event_number, event_position);
389  assert (event_number != ExtendedBarCode::UNDEFINED);
390  return event_number;
391 }
392 
393 
400 {
401  index_type event_number, position;
402  m_extBarcode.eventIndex (event_number, position);
403  if (position != ExtendedBarCode::UNDEFINED) {
404  return position;
405  }
406  if (event_number == 0) {
407  return 0;
408  }
409 
410  std::vector<index_type> positions = getEventPositionInCollection(event_number, sg);
411  return positions[0];
412 }
413 
414 
419 std::vector<HepMcParticleLink::index_type>
421 {
422  std::vector<index_type> positions; positions.reserve(1);
423  const int int_event_number = static_cast<int>(event_number);
424  if (const McEventCollection* coll = retrieveMcEventCollection (sg)) {
425  size_t sz = coll->size();
426  for (size_t i = 0; i < sz; i++) {
427  if ((*coll)[i]->event_number() == int_event_number) {
428  positions.push_back(i);
429  }
430  }
431  }
432  if (positions.empty() ) {
433  positions.push_back(ExtendedBarCode::UNDEFINED);
434  }
435  return positions;
436 }
437 
438 
444 {
445  if (const McEventCollection* coll = retrieveMcEventCollection (sg)) {
446  if (position < coll->size()) {
447  return coll->at (position)->event_number();
448  }
449  }
450 #if 0
451  MsgStream log (Athena::getMessageSvc(), "HepMcParticleLink");
452  log << MSG::WARNING << "getEventNumberAtPosition: position = " << position << ", McEventCollection size = "<< coll->size() << endmsg;
453 #endif
454  return -999;
455 }
456 
457 
466 {
467  const HepMcParticleLink::PositionFlag idxFlag =
469  // Support reading in legacy barcode-based persistent EDM for now
470  const int uniqueID =
471  (particleLink.barcode() != 0) ? particleLink.barcode() : particleLink.id();
472  const HepMcParticleLink::UniqueIDFlag uidFlag =
474  HepMcParticleLink redirectedLink(uniqueID, eventIndex, idxFlag, uidFlag, ctx);
475  redirectedLink.setTruthSuppressionType(particleLink.getTruthSuppressionType());
476  return redirectedLink;
477 }
478 
479 
484 {
485  m_extBarcode = extBarcode;
487  m_ptr.reset();
488 }
489 
490 
496 const McEventCollection*
498 {
499  const McEventCollection* pEvtColl = nullptr;
501  if (proxy) {
502  pEvtColl = SG::DataProxy_cast<McEventCollection> (proxy);
503  if (!pEvtColl) {
504  MsgStream log (Athena::getMessageSvc(), "HepMcParticleLink");
505  log << MSG::WARNING << "cptr: McEventCollection not found" << endmsg;
506  }
507  }
508  return pEvtColl;
509 }
510 
517 {
519  unsigned int hint_orig = s_hint;
520  if (hint_orig >= NKEYS) hint_orig = 0;
521  unsigned int hint = hint_orig;
522  do {
523  SG::DataProxy* proxy = sg->proxy (clid, s_keys[hint]);
524  if (proxy) {
525  if (hint != s_hint) {
526  s_hint = hint;
527  }
528  static std::atomic<unsigned> findCount {0};
529  if(++findCount == 1) {
530  MsgStream log (Athena::getMessageSvc(), "HepMcParticleLink");
531  log << MSG::INFO << "find_proxy: Using " << s_keys[hint]
532  <<" as McEventCollection key for this job " << endmsg;
533  }
534  return proxy;
535  }
536  ++hint;
537  if (hint >= NKEYS) hint = 0;
538  } while (hint != hint_orig);
539 
540  MsgStream log (Athena::getMessageSvc(), "HepMcParticleLink");
541  static std::atomic<unsigned long> msgCount {0};
542  unsigned int count = ++msgCount;
543  if (count <= CPTRMAXMSGCOUNT) {
544  log << MSG::WARNING << "find_proxy: No Valid MC event Collection found "
545  << endmsg;
546  }
547  if (count == CPTRMAXMSGCOUNT) {
548  log << MSG::WARNING <<"find_proxy: suppressing further messages about valid MC event Collection. Use \n"
549  << " msgSvc.setVerbose += [HepMcParticleLink]\n"
550  << "to see all messages" << endmsg;
551  }
552  if (count > CPTRMAXMSGCOUNT) {
553  log << MSG::VERBOSE << "find_proxy: No Valid MC event Collection found "
554  << endmsg;
555  }
556  return nullptr;
557 }
558 
559 
564 {
565  static const std::string unset = "CollectionNotSet";
566  unsigned idx = s_hint;
567  if (idx < NKEYS) {
568  return s_keys[idx];
569  }
570  return unset;
571 }
572 
573 
579 std::ostream&
580 operator<< (std::ostream& os, const HepMcParticleLink& link)
581 {
582  link.m_extBarcode.print(os);
583  return os;
584 }
585 
586 
592 MsgStream&
593 operator<< (MsgStream& os, const HepMcParticleLink& link)
594 {
595  link.m_extBarcode.print(os);
596  return os;
597 }
LArG4FSStartPointFilter.part
part
Definition: LArG4FSStartPointFilter.py:21
EBC_SUPPRESSED_TRUTH
EBC_SUPPRESSED_TRUTH
Definition: MagicNumbers.h:27
CurrentEventStore.h
Hold a pointer to the current event store.
CxxUtils::CachedValue::reset
void reset()
Reset the value to invalid.
GenEvent.h
CxxUtils::CachedValue::ptr
const T * ptr() const
Return a pointer to the cached value.
fitman.sz
sz
Definition: fitman.py:527
IProxyDict::proxy
virtual SG::DataProxy * proxy(const CLID &id, const std::string &key) const =0
Get proxy with given id and key.
StateLessPT_NewConfig.proxy
proxy
Definition: StateLessPT_NewConfig.py:392
PowhegControl_ttHplus_NLO.ss
ss
Definition: PowhegControl_ttHplus_NLO.py:83
getMessageSvc.h
singleton-like access to IMessageSvc via open function and helper
CaloCellPos2Ntuple.int
int
Definition: CaloCellPos2Ntuple.py:24
xAOD::uint32_t
setEventNumber uint32_t
Definition: EventInfo_v1.cxx:127
EBC_NSUPP
@ EBC_NSUPP
Definition: MagicNumbers.h:30
CxxUtils::CachedValue::isValid
bool isValid() const
Test to see if the value is valid.
SG::CurrentEventStore::store
static IProxyDict * store()
Fetch the current store.
IProxyDict
A proxy dictionary.
Definition: AthenaKernel/AthenaKernel/IProxyDict.h:47
GenParticle.h
Athena::getMessageSvc
IMessageSvc * getMessageSvc(bool quiet=false)
Definition: getMessageSvc.cxx:20
XMLtoHeader.count
count
Definition: XMLtoHeader.py:85
python.setupRTTAlg.size
int size
Definition: setupRTTAlg.py:39
ClassID_traits::ID
static const CLID & ID()
the CLID of T
Definition: Control/AthenaKernel/AthenaKernel/ClassID_traits.h:50
python.ExitCodes.codes
dictionary codes
helper to get a human-readable string
Definition: ExitCodes.py:49
python.utils.AtlRunQueryDQUtils.p
p
Definition: AtlRunQueryDQUtils.py:210
UNDEFINED
@ UNDEFINED
Definition: sTGCenumeration.h:18
HepMC::barcode_to_particle
GenParticle * barcode_to_particle(const GenEvent *e, int id)
Definition: GenEvent.h:628
McEventCollection.h
lumiFormat.i
int i
Definition: lumiFormat.py:85
endmsg
#define endmsg
Definition: AnalysisConfig_Ntuple.cxx:63
HepMC::barcode
int barcode(const T *p)
Definition: Barcode.h:16
HepMC::uniqueID
int uniqueID(const T &p)
Definition: MagicNumbers.h:109
McEventCollection
This defines the McEventCollection, which is really just an ObjectVector of McEvent objects.
Definition: McEventCollection.h:33
CLID
uint32_t CLID
The Class ID type.
Definition: Event/xAOD/xAODCore/xAODCore/ClassID_traits.h:47
ReadFromCoolCompare.os
os
Definition: ReadFromCoolCompare.py:231
HepMC::ConstGenParticlePtr
const GenParticle * ConstGenParticlePtr
Definition: GenParticle.h:38
MagicNumbers.h
CxxUtils::CachedValue::set
void set(const T &val) const
Set the value, assuming it is currently invalid.
HepMC
Definition: Barcode.h:14
DEBUG
#define DEBUG
Definition: page_access.h:11
python.CaloCondTools.log
log
Definition: CaloCondTools.py:20
LArG4FSStartPointFilter.particles
list particles
Definition: LArG4FSStartPointFilter.py:84
LArNewCalib_DelayDump_OFC_Cali.idx
idx
Definition: LArNewCalib_DelayDump_OFC_Cali.py:69
EBC_PU_SUPPRESSED
@ EBC_PU_SUPPRESSED
Definition: MagicNumbers.h:29
dbg::print
void print(std::FILE *stream, std::format_string< Args... > fmt, Args &&... args)
Definition: SGImplSvc.cxx:70
python.Constants.VERBOSE
int VERBOSE
Definition: Control/AthenaCommon/python/Constants.py:14
EBC_UNSUPPRESSED
@ EBC_UNSUPPRESSED
Definition: MagicNumbers.h:28
SG::DataProxy
Definition: DataProxy.h:44
DataProxy.h
EventInfoCnvParams::eventIndex
thread_local event_number_t eventIndex
Definition: IEvtIdModifierSvc.h:34