ATLAS Offline Software
Loading...
Searching...
No Matches
HepMcParticleLink.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2025 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
14#include "AtlasHepMC/GenEvent.h"
16#include "GaudiKernel/MsgStream.h"
18#include "SGTools/DataProxy.h"
19#include <sstream>
20#include <cassert>
21
22
23namespace {
24
25
29constexpr int NKEYS = 5;
30const
31std::string s_keys[NKEYS] = {"TruthEvent","G4Truth","GEN_AOD","GEN_EVENT","Bkg_TruthEvent"};
32
33
41std::atomic<unsigned> s_hint = NKEYS;
42
43
44const unsigned short CPTRMAXMSGCOUNT = 100;
45
46
47} // anonymous namespace
48
49
50//**************************************************************************
51// ExtendedBarCode
52//
53
54
58char
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
88void HepMcParticleLink::ExtendedBarCode::print (std::ostream& os) const
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
144 uint32_t eventIndex,
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) {
198 sg = SG::CurrentEventStore::store();
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 const auto &particles = pEvt->particles();
251 if (particle_id-1 < particles.size()) {
252 const HepMC::ConstGenParticlePtr p = particles[particle_id-1];
253 if (p) {
254 m_ptr.set (p);
255 return p;
256 }
257 }
258 }
259 }
260 } else {
261 MsgStream log (Athena::getMessageSvc(), "HepMcParticleLink");
262 if (position != ExtendedBarCode::UNDEFINED) {
263 log << MSG::WARNING
264 << "cptr: Mc Truth not stored for event at " << position
265 << endmsg;
266 } else {
267 log << MSG::WARNING
268 << "cptr: Mc Truth not stored for event with event number " << event_number
269 << endmsg;
270 }
271 }
272 } else {
273 MsgStream log (Athena::getMessageSvc(), "HepMcParticleLink");
274 log << MSG::WARNING << "cptr: McEventCollection not found" << endmsg;
275 }
276 return nullptr;
277}
278
279
284{
285 // if m_BC is zero (delta rays), then just return that same for barcode and id
286 if (m_extBarcode.uid()) {
287 // dummy link
288 if (!m_ptr.isValid() && !m_store) {
289 return 0; // TODO Decide if this is a good default - constant from MagicNumbers.h instead?
290 }
291
292 barcode_type particle_id, particle_barcode;
293 m_extBarcode.uniqueID (particle_id, particle_barcode);
294 if (particle_id == ExtendedBarCode::UNDEFINEDBC) {
295 (void) cptr(); // FIXME be careful to avoid an infinite loop of calls here
296 m_extBarcode.uniqueID (particle_id, particle_barcode);
297 }
298 if (particle_id != ExtendedBarCode::UNDEFINEDBC) {
299 return particle_id;
300 }
301 }
302 return 0;
303}
304
305
311{
312 // if m_BC is zero (delta rays), then just return that same for barcode and id
313 if (m_extBarcode.uid()) {
314 barcode_type particle_id, particle_barcode;
315 m_extBarcode.uniqueID (particle_id, particle_barcode);
316 if (particle_barcode != ExtendedBarCode::UNDEFINEDBC) {
317 return int(particle_barcode);
318 }
319 // dummy link
320 if (!m_ptr.isValid() && !m_store) {
321 return 0; // TODO Decide if this is a good default - constant from MagicNumbers.h instead?
322 }
323 // we will need to look up the barcode from the GenParticle
324 (void) eventIndex(); // FIXME be careful to avoid an infinite loop of calls here
325 if (cptr()) {
326 return HepMC::barcode(cptr());
327 }
328 }
329 return 0;
330}
331
332
338{
339 // dummy link
340 if (!m_ptr.isValid() && !m_store) {
342 }
343
344 index_type event_number, event_position;
345 m_extBarcode.eventIndex (event_number, event_position);
346 if (event_number == ExtendedBarCode::UNDEFINED) {
347 const HepMC::GenEvent* pEvt{};
349 if (event_position < coll->size()) {
350 pEvt = coll->at (event_position);
351 }
352 if (pEvt) {
353 const int genEventNumber = pEvt->event_number();
354 // Be sure to update m_extBarcode before m_ptr.
355 // Otherwise, if two threads run this method simultaneously,
356 // one thread could see event_number == UNDEFINED, but where m_ptr
357 // is already updated so we get nullptr back for sg.
358 if (genEventNumber > -1) {
359 event_number = static_cast<index_type>(genEventNumber);
360 m_extBarcode.makeIndex (event_number, event_position);
361 return event_number;
362 }
363 if (barcode() != 0) {
365 if (pp) {
366 m_ptr.set (pp);
367 }
368 }
369 }
370 }
371 }
372 // Don't trip the assertion for a null link.
373 if ( m_extBarcode.linkIsNull() )
374 {
375 return (event_number != ExtendedBarCode::UNDEFINED) ? event_number : 0;
376 }
377 // Attempt to find the GenParticle
378 cptr();
379 // Check if event_number is valid once more
380 m_extBarcode.eventIndex (event_number, event_position);
381 assert (event_number != ExtendedBarCode::UNDEFINED);
382 return event_number;
383}
384
385
392{
393 index_type event_number, position;
394 m_extBarcode.eventIndex (event_number, position);
395 if (position != ExtendedBarCode::UNDEFINED) {
396 return position;
397 }
398 if (event_number == 0) {
399 return 0;
400 }
401
402 std::vector<index_type> positions = getEventPositionInCollection(event_number, sg);
403 return positions[0];
404}
405
406
411std::vector<HepMcParticleLink::index_type>
413{
414 std::vector<index_type> positions; positions.reserve(1);
415 const int int_event_number = static_cast<int>(event_number);
416 if (const McEventCollection* coll = retrieveMcEventCollection (sg)) {
417 size_t sz = coll->size();
418 for (size_t i = 0; i < sz; i++) {
419 if ((*coll)[i]->event_number() == int_event_number) {
420 positions.push_back(i);
421 }
422 }
423 }
424 if (positions.empty() ) {
425 positions.push_back(ExtendedBarCode::UNDEFINED);
426 }
427 return positions;
428}
429
430
436{
437 if (const McEventCollection* coll = retrieveMcEventCollection (sg)) {
438 if (position < coll->size()) {
439 return coll->at (position)->event_number();
440 }
441 }
442#if 0
443 MsgStream log (Athena::getMessageSvc(), "HepMcParticleLink");
444 log << MSG::WARNING << "getEventNumberAtPosition: position = " << position << ", McEventCollection size = "<< coll->size() << endmsg;
445#endif
446 return -999;
447}
448
449
457HepMcParticleLink HepMcParticleLink::getRedirectedLink(const HepMcParticleLink& particleLink, uint32_t eventIndex, const EventContext& ctx)
458{
459 const HepMcParticleLink::PositionFlag idxFlag =
461 // Support reading in legacy barcode-based persistent EDM for now
462 const int uniqueID =
463 (particleLink.barcode() != 0) ? particleLink.barcode() : particleLink.id();
464 const HepMcParticleLink::UniqueIDFlag uidFlag =
466 HepMcParticleLink redirectedLink(uniqueID, eventIndex, idxFlag, uidFlag, ctx);
467 redirectedLink.setTruthSuppressionType(particleLink.getTruthSuppressionType());
468 return redirectedLink;
469}
470
471
476{
477 m_extBarcode = extBarcode;
478 m_store = SG::CurrentEventStore::store();
479 m_ptr.reset();
480}
481
482
490{
491 const McEventCollection* pEvtColl = nullptr;
492 SG::DataProxy* proxy = find_proxy (sg);
493 if (proxy) {
494 pEvtColl = SG::DataProxy_cast<McEventCollection> (proxy);
495 if (!pEvtColl) {
496 MsgStream log (Athena::getMessageSvc(), "HepMcParticleLink");
497 log << MSG::WARNING << "cptr: McEventCollection not found" << endmsg;
498 }
499 }
500 return pEvtColl;
501}
502
509{
511 unsigned int hint_orig = s_hint.load(std::memory_order_relaxed);
512 if (hint_orig >= NKEYS) hint_orig = 0;
513 unsigned int hint = hint_orig;
514 do {
515 SG::DataProxy* proxy = sg->proxy (clid, s_keys[hint]);
516 if (proxy) {
517 if (hint != s_hint.load(std::memory_order_relaxed)) {
518 s_hint.store(hint, std::memory_order_relaxed);
519 }
520 static std::once_flag log_flag;
521 std::call_once(log_flag, [hint]() {
522 MsgStream log (Athena::getMessageSvc(), "HepMcParticleLink");
523 log << MSG::INFO << "find_proxy: Using " << s_keys[hint]
524 << " as McEventCollection key for this job " << endmsg;
525 });
526 return proxy;
527 }
528 ++hint;
529 if (hint >= NKEYS) hint = 0;
530 } while (hint != hint_orig);
531
532 MsgStream log (Athena::getMessageSvc(), "HepMcParticleLink");
533 static std::atomic<unsigned long> msgCount {0};
534 unsigned int count = ++msgCount;
535 if (count <= CPTRMAXMSGCOUNT) {
536 log << MSG::WARNING << "find_proxy: No Valid MC event Collection found "
537 << endmsg;
538 }
539 if (count == CPTRMAXMSGCOUNT) {
540 log << MSG::WARNING <<"find_proxy: suppressing further messages about valid MC event Collection. Use \n"
541 << " msgSvc.setVerbose += [HepMcParticleLink]\n"
542 << "to see all messages" << endmsg;
543 }
544 if (count > CPTRMAXMSGCOUNT) {
545 log << MSG::VERBOSE << "find_proxy: No Valid MC event Collection found "
546 << endmsg;
547 }
548 return nullptr;
549}
550
551
556{
557 static const std::string unset = "CollectionNotSet";
558 unsigned idx = s_hint;
559 if (idx < NKEYS) {
560 return s_keys[idx];
561 }
562 return unset;
563}
564
565
571std::ostream&
572operator<< (std::ostream& os, const HepMcParticleLink& link)
573{
574 link.m_extBarcode.print(os);
575 return os;
576}
577
578
584MsgStream&
585operator<< (MsgStream& os, const HepMcParticleLink& link)
586{
587 link.m_extBarcode.print(os);
588 return os;
589}
#define endmsg
uint32_t CLID
The Class ID type.
static Double_t sz
static Double_t ss
EBC_SUPPRESSED_TRUTH
@ EBC_NSUPP
@ EBC_PU_SUPPRESSED
@ EBC_UNSUPPRESSED
Hold a pointer to the current event store.
size_t size() const
Number of registered mappings.
void print(char *figname, TCanvas *c1)
virtual SG::DataProxy * proxy(const CLID &id, const std::string &key) const =0
Get proxy with given id and key.
This defines the McEventCollection, which is really just an ObjectVector of McEvent objectsFile: Gene...
singleton-like access to IMessageSvc via open function and helper
int count(std::string s, const std::string &regx)
count how many occurances of a regx are in a string
Definition hcg.cxx:148
IMessageSvc * getMessageSvc(bool quiet=false)
int barcode(const T *p)
Definition Barcode.h:15
ConstGenParticlePtr barcode_to_particle(const GenEvent *e, int id)
Definition GenEvent.h:443
int uniqueID(const T &p)
HepMC3::ConstGenParticlePtr ConstGenParticlePtr
Definition GenParticle.h:20
HepMC3::GenEvent GenEvent
Definition GenEvent.h:39
DATA * DataProxy_cast(DataProxy *proxy)
cast the proxy into the concrete data object it proxies