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 
59 {
60  os << "Event index " ;
61  index_type event_number, position;
62  eventIndex (event_number, position);
63  if (position != UNDEFINED) {
64  os << position << " (position in collection) ";
65  }
66  else {
67  os << event_number << " (event number) ";
68  }
69  os << ", Unique ID " ;
70  barcode_type particle_id, particle_barcode;
71  uniqueID (particle_id, particle_barcode);
72  if (particle_barcode == 0 && particle_id == 0) {
73  os << " 0 (id/barcode) ";
74  }
75  else if (particle_barcode != UNDEFINEDBC) {
76  os << particle_barcode << " (barcode) ";
77  }
78  else {
79  os << particle_id << " (id) ";
80  }
81  os << ", McEventCollection "
83 }
84 
85 
90 {
91  std::ostringstream ss;
92  print (ss);
93  os << ss.str();
94 }
95 
96 
97 //**************************************************************************
98 // HepMcParticleLink
99 //
100 
101 
115  PositionFlag positionFlag /*= IS_EVENTNUM*/,
116  IProxyDict* sg /*= SG::CurrentEventStore::store()*/)
117  : m_store (sg),
118  m_ptr (part),
119  m_extBarcode((nullptr != part) ? HepMC::uniqueID(part) : 0, eventIndex, positionFlag, IS_ID)
120 {
121  assert(part);
122 
123  if (part != nullptr && positionFlag == IS_POSITION) {
124  if (const McEventCollection* pEvtColl = retrieveMcEventCollection(sg)) {
125  const HepMC::GenEvent *pEvt = pEvtColl->at (eventIndex);
126  m_extBarcode.makeIndex (pEvt->event_number(), eventIndex);
127  }
128  else {
129  MsgStream log (Athena::getMessageSvc(), "HepMcParticleLink");
130  log << MSG::WARNING << "cptr: McEventCollection not found" << endmsg;
131  }
132  }
133 }
134 
135 
140 {
141  // dummy link
142  const bool is_valid = m_ptr.isValid();
143  if (!is_valid && !m_store) {
144  return nullptr;
145  }
146  if (is_valid) {
147  return *m_ptr.ptr();
148  }
149  if (m_extBarcode.linkIsNull()) {
150  #if 0
151  MsgStream log (Athena::getMessageSvc(), "HepMcParticleLink");
152  log << MSG::DEBUG
153  << "cptr: no truth particle associated with this hit (barcode==0)."
154  << " Probably this is a noise hit" << endmsg;
155  #endif
156  return nullptr;
157  }
158  IProxyDict* sg = m_store;
159  if (!sg) {
161  }
162  if (const McEventCollection* pEvtColl = retrieveMcEventCollection(sg)) {
163  const HepMC::GenEvent *pEvt = nullptr;
164  index_type event_number, position;
165  m_extBarcode.eventIndex (event_number, position);
166  if (event_number == 0) {
167  pEvt = pEvtColl->at(0);
168  }
169  else if (position != ExtendedBarCode::UNDEFINED) {
170  if (position < pEvtColl->size()) {
171  pEvt = pEvtColl->at (position);
172  }
173  else {
174  #if 0
175  MsgStream log (Athena::getMessageSvc(), "HepMcParticleLink");
176  log << MSG::WARNING << "cptr: position = " << position << ", McEventCollection size = "<< pEvtColl->size() << endmsg;
177  #endif
178  return nullptr;
179  }
180  }
181  else {
182  pEvt = pEvtColl->find (event_number);
183  }
184 
185  if (nullptr != pEvt) {
186  // Be sure to update m_extBarcode before m_ptrs;
187  // otherwise, the logic in eventIndex() won't work correctly.
188  if (position != ExtendedBarCode::UNDEFINED) {
189  m_extBarcode.makeIndex (pEvt->event_number(), position);
190  }
191  if (event_number == 0) {
192  m_extBarcode.makeIndex (pEvt->event_number(), position);
193  }
194  if ( !m_extBarcode.linkIsNull() ) { // Check that either the ID or Barcode is non-zero or undefined
195  barcode_type particle_id, particle_barcode;
196  m_extBarcode.uniqueID (particle_id, particle_barcode);
197  if (particle_id == ExtendedBarCode::UNDEFINEDBC) {
198  // barcode to GenParticle
199  const HepMC::ConstGenParticlePtr p = HepMC::barcode_to_particle(pEvt,int(particle_barcode));
200  if (p) {
201  int genParticleID = HepMC::uniqueID(p);
202  if (genParticleID > -1) {
203  particle_id = static_cast<barcode_type>(genParticleID);
204  m_extBarcode.makeID (particle_id, particle_barcode);
205  }
206  m_ptr.set (p);
207  return p;
208  }
209  }
210  else {
211  // id to GenParticle
212 #ifdef HEPMC3
213  const auto &particles = pEvt->particles();
214  if (particle_id-1 < particles.size()) {
215  const HepMC::ConstGenParticlePtr p = particles[particle_id-1];
216  if (p) {
217  m_ptr.set (p);
218  return p;
219  }
220  }
221 #else
222  const HepMC::ConstGenParticlePtr p = HepMC::barcode_to_particle(pEvt,int(particle_id)); // For HepMC2 "id" == barcode
223  if (p) {
224  m_ptr.set (p);
225  return p;
226  }
227 #endif
228  }
229  }
230  } else {
231  MsgStream log (Athena::getMessageSvc(), "HepMcParticleLink");
232  if (position != ExtendedBarCode::UNDEFINED) {
233  log << MSG::WARNING
234  << "cptr: Mc Truth not stored for event at " << position
235  << endmsg;
236  } else {
237  log << MSG::WARNING
238  << "cptr: Mc Truth not stored for event with event number " << event_number
239  << endmsg;
240  }
241  }
242  } else {
243  MsgStream log (Athena::getMessageSvc(), "HepMcParticleLink");
244  log << MSG::WARNING << "cptr: McEventCollection not found" << endmsg;
245  }
246  return nullptr;
247 }
248 
249 
254 {
255  // if m_BC is zero (delta rays), then just return that same for barcode and id
256  if (m_extBarcode.uid()) {
257  // dummy link
258  if (!m_ptr.isValid() && !m_store) {
259  return 0; // TODO Decide if this is a good default - constant from MagicNumbers.h instead?
260  }
261 
262  barcode_type particle_id, particle_barcode;
263  m_extBarcode.uniqueID (particle_id, particle_barcode);
264  if (particle_id == ExtendedBarCode::UNDEFINEDBC) {
265  (void) cptr(); // FIXME be careful to avoid an infinite loop of calls here
266  m_extBarcode.uniqueID (particle_id, particle_barcode);
267  }
268  if (particle_id != ExtendedBarCode::UNDEFINEDBC) {
269  return particle_id;
270  }
271  }
272  return 0;
273 }
274 
275 
281 {
282  // if m_BC is zero (delta rays), then just return that same for barcode and id
283  if (m_extBarcode.uid()) {
284  barcode_type particle_id, particle_barcode;
285  m_extBarcode.uniqueID (particle_id, particle_barcode);
286  if (particle_barcode != ExtendedBarCode::UNDEFINEDBC) {
287  return int(particle_barcode);
288  }
289  // dummy link
290  if (!m_ptr.isValid() && !m_store) {
291  return 0; // TODO Decide if this is a good default - constant from MagicNumbers.h instead?
292  }
293  // we will need to look up the barcode from the GenParticle
294  (void) eventIndex(); // FIXME be careful to avoid an infinite loop of calls here
295  if (cptr()) {
296  return HepMC::barcode(cptr());
297  }
298  }
299  return 0;
300 }
301 
302 
308 {
309  // dummy link
310  if (!m_ptr.isValid() && !m_store) {
312  }
313 
314  index_type event_number, event_position;
315  m_extBarcode.eventIndex (event_number, event_position);
316  if (event_number == ExtendedBarCode::UNDEFINED) {
317  const HepMC::GenEvent* pEvt{};
319  if (event_position < coll->size()) {
320  pEvt = coll->at (event_position);
321  }
322  if (pEvt) {
323  const int genEventNumber = pEvt->event_number();
324  // Be sure to update m_extBarcode before m_ptr.
325  // Otherwise, if two threads run this method simultaneously,
326  // one thread could see event_number == UNDEFINED, but where m_ptr
327  // is already updated so we get nullptr back for sg.
328  if (genEventNumber > -1) {
329  event_number = static_cast<index_type>(genEventNumber);
330  m_extBarcode.makeIndex (event_number, event_position);
331  return event_number;
332  }
333  if (barcode() != 0) {
335  if (pp) {
336  m_ptr.set (pp);
337  }
338  }
339  }
340  }
341  }
342  // Don't trip the assertion for a null link.
343  if ( m_extBarcode.linkIsNull() )
344  {
345  return (event_number != ExtendedBarCode::UNDEFINED) ? event_number : 0;
346  }
347  // Attempt to find the GenParticle
348  cptr();
349  // Check if event_number is valid once more
350  m_extBarcode.eventIndex (event_number, event_position);
351  assert (event_number != ExtendedBarCode::UNDEFINED);
352  return event_number;
353 }
354 
355 
362 {
363  index_type event_number, position;
364  m_extBarcode.eventIndex (event_number, position);
365  if (position != ExtendedBarCode::UNDEFINED) {
366  return position;
367  }
368  if (event_number == 0) {
369  return 0;
370  }
371 
372  std::vector<index_type> positions = getEventPositionInCollection(event_number, sg);
373  return positions[0];
374 }
375 
376 
381 std::vector<HepMcParticleLink::index_type>
383 {
384  std::vector<index_type> positions; positions.reserve(1);
385  const int int_event_number = static_cast<int>(event_number);
386  if (const McEventCollection* coll = retrieveMcEventCollection (sg)) {
387  size_t sz = coll->size();
388  for (size_t i = 0; i < sz; i++) {
389  if ((*coll)[i]->event_number() == int_event_number) {
390  positions.push_back(i);
391  }
392  }
393  }
394  if (positions.empty() ) {
395  positions.push_back(ExtendedBarCode::UNDEFINED);
396  }
397  return positions;
398 }
399 
400 
406 {
407  if (const McEventCollection* coll = retrieveMcEventCollection (sg)) {
408  if (position < coll->size()) {
409  return coll->at (position)->event_number();
410  }
411  }
412 #if 0
413  MsgStream log (Athena::getMessageSvc(), "HepMcParticleLink");
414  log << MSG::WARNING << "getEventNumberAtPosition: position = " << position << ", McEventCollection size = "<< coll->size() << endmsg;
415 #endif
416  return -999;
417 }
418 
419 
428 {
429  const HepMcParticleLink::PositionFlag idxFlag =
431  // Support reading in legacy barcode-based persistent EDM for now
432  const int uniqueID =
433  (particleLink.barcode() != 0) ? particleLink.barcode() : particleLink.id();
434  const HepMcParticleLink::UniqueIDFlag uidFlag =
436  return HepMcParticleLink(uniqueID, eventIndex, idxFlag, uidFlag, ctx);
437 }
438 
439 
444 {
445  m_extBarcode = extBarcode;
447  m_ptr.reset();
448 }
449 
450 
456 const McEventCollection*
458 {
459  const McEventCollection* pEvtColl = nullptr;
461  if (proxy) {
462  pEvtColl = SG::DataProxy_cast<McEventCollection> (proxy);
463  if (!pEvtColl) {
464  MsgStream log (Athena::getMessageSvc(), "HepMcParticleLink");
465  log << MSG::WARNING << "cptr: McEventCollection not found" << endmsg;
466  }
467  }
468  return pEvtColl;
469 }
470 
477 {
479  unsigned int hint_orig = s_hint;
480  if (hint_orig >= NKEYS) hint_orig = 0;
481  unsigned int hint = hint_orig;
482  do {
483  SG::DataProxy* proxy = sg->proxy (clid, s_keys[hint]);
484  if (proxy) {
485  if (hint != s_hint) {
486  s_hint = hint;
487  }
488  static std::atomic<unsigned> findCount {0};
489  if(++findCount == 1) {
490  MsgStream log (Athena::getMessageSvc(), "HepMcParticleLink");
491  log << MSG::INFO << "find_proxy: Using " << s_keys[hint]
492  <<" as McEventCollection key for this job " << endmsg;
493  }
494  return proxy;
495  }
496  ++hint;
497  if (hint >= NKEYS) hint = 0;
498  } while (hint != hint_orig);
499 
500  MsgStream log (Athena::getMessageSvc(), "HepMcParticleLink");
501  static std::atomic<unsigned long> msgCount {0};
502  unsigned int count = ++msgCount;
503  if (count <= CPTRMAXMSGCOUNT) {
504  log << MSG::WARNING << "find_proxy: No Valid MC event Collection found "
505  << endmsg;
506  }
507  if (count == CPTRMAXMSGCOUNT) {
508  log << MSG::WARNING <<"find_proxy: suppressing further messages about valid MC event Collection. Use \n"
509  << " msgSvc.setVerbose += [HepMcParticleLink]\n"
510  << "to see all messages" << endmsg;
511  }
512  if (count > CPTRMAXMSGCOUNT) {
513  log << MSG::VERBOSE << "find_proxy: No Valid MC event Collection found "
514  << endmsg;
515  }
516  return nullptr;
517 }
518 
519 
524 {
525  static const std::string unset = "CollectionNotSet";
526  unsigned idx = s_hint;
527  if (idx < NKEYS) {
528  return s_keys[idx];
529  }
530  return unset;
531 }
532 
533 
539 std::ostream&
540 operator<< (std::ostream& os, const HepMcParticleLink& link)
541 {
542  link.m_extBarcode.print(os);
543  return os;
544 }
545 
546 
552 MsgStream&
553 operator<< (MsgStream& os, const HepMcParticleLink& link)
554 {
555  link.m_extBarcode.print(os);
556  return os;
557 }
LArG4FSStartPointFilter.part
part
Definition: LArG4FSStartPointFilter.py:21
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
python.PerfMonSerializer.p
def p
Definition: PerfMonSerializer.py:743
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
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:51
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
HepMC::barcode_to_particle
GenParticle * barcode_to_particle(const GenEvent *e, int id)
Definition: GenEvent.h:506
McEventCollection.h
lumiFormat.i
int i
Definition: lumiFormat.py:92
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:113
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
Muon::print
std::string print(const MuPatSegment &)
Definition: MuonTrackSteering.cxx:28
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
python.Constants.VERBOSE
int VERBOSE
Definition: Control/AthenaCommon/python/Constants.py:14
SG::DataProxy
Definition: DataProxy.h:44
DataProxy.h
EventInfoCnvParams::eventIndex
thread_local event_number_t eventIndex
Definition: IEvtIdModifierSvc.h:36