ATLAS Offline Software
Loading...
Searching...
No Matches
HepMcParticleLink.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2026 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"
17#include "GaudiKernel/MsgStream.h"
19#include "SGTools/DataProxy.h"
20#include <sstream>
21#include <cassert>
22
23
24namespace {
25
26
30constexpr int NKEYS = 5;
31const
32std::string s_keys[NKEYS] = {"TruthEvent","G4Truth","GEN_AOD","GEN_EVENT","Bkg_TruthEvent"};
33
34
42std::atomic<unsigned> s_hint = NKEYS;
43
44
45const unsigned short CPTRMAXMSGCOUNT = 100;
46
47
48} // anonymous namespace
49
50
51//**************************************************************************
52// ExtendedBarCode
53//
54
55
59char
61{
62 static const char codes[EBC_NSUPP] = {'a', 'b'};
63 assert (suppEnum < EBC_NSUPP);
64 return codes[suppEnum];
65}
66
67
73{
74 switch (suppChar) {
75 case 'a': return EBC_UNSUPPRESSED;
76 case 'b': return EBC_PU_SUPPRESSED;
77 default:
78 // Should not reach this
79 MsgStream log (Athena::getMessageSvc(), "HepMcParticleLink");
80 log << MSG::ERROR << " Wrong truth Suppression Char (" << std::string(&suppChar,1) << ") set in HepMcParticleLink ExtendedBarCode object !!!" << endmsg;
81 }
82 return EBC_UNSUPPRESSED;
83}
84
85
89void HepMcParticleLink::ExtendedBarCode::print (std::ostream& os) const
90{
91 os << "Event index " ;
92 index_type event_number, position;
93 eventIndex (event_number, position);
94 if (position != UNDEFINED) {
95 os << position << " (position in collection) ";
96 }
97 else {
98 os << event_number << " (event number) ";
99 }
100 os << ", Unique ID " ;
101 barcode_type particle_id, particle_barcode;
102 uniqueID (particle_id, particle_barcode);
103 if (particle_barcode == 0 && particle_id == 0) {
104 os << " 0 (id/barcode) ";
105 }
106 else if (particle_barcode != UNDEFINEDBC) {
107 os << particle_barcode << " (barcode) ";
108 }
109 else {
110 os << particle_id << " (id) ";
111 }
112 os << ", McEventCollection "
114}
115
116
121{
122 std::ostringstream ss;
123 print (ss);
124 os << ss.str();
125}
126
127
128//**************************************************************************
129// HepMcParticleLink
130//
131
132
145 uint32_t eventIndex,
146 PositionFlag positionFlag /*= IS_EVENTNUM*/,
147 IProxyDict* sg /*= SG::CurrentEventStore::store()*/)
148 : m_store (sg),
149 m_ptr (part),
150 m_extBarcode((nullptr != part) ? HepMC::uniqueID(part) : 0, eventIndex, positionFlag, IS_ID)
151{
152 assert(part);
153
154 if (part != nullptr && positionFlag == IS_POSITION) {
155 if (const McEventCollection* pEvtColl = retrieveMcEventCollection(sg)) {
156 const HepMC::GenEvent *pEvt = pEvtColl->at (eventIndex);
157 m_extBarcode.makeIndex (pEvt->event_number(), eventIndex);
158 }
159 else {
160 MsgStream log (Athena::getMessageSvc(), "HepMcParticleLink");
161 log << MSG::WARNING << "cptr: McEventCollection not found" << endmsg;
162 }
163 }
164}
165
166
171 return m_extBarcode.linkIsNull();
172}
173
174
179{
180 // dummy link
181 const bool is_valid = m_ptr.isValid();
182 if (!is_valid && !m_store) {
183 return nullptr;
184 }
185 if (is_valid) {
186 return *m_ptr.ptr();
187 }
188 if (m_extBarcode.linkIsNull()) {
189 #if 0
190 MsgStream log (Athena::getMessageSvc(), "HepMcParticleLink");
191 log << MSG::DEBUG
192 << "cptr: no truth particle associated with this hit (barcode==0)."
193 << " Probably this is a noise hit" << endmsg;
194 #endif
195 return nullptr;
196 }
197 IProxyDict* sg = m_store;
198 if (!sg) {
199 sg = SG::CurrentEventStore::store();
200 }
201 if (const McEventCollection* pEvtColl = retrieveMcEventCollection(sg)) {
202 const HepMC::GenEvent *pEvt = nullptr;
203 index_type event_number, position;
204 m_extBarcode.eventIndex (event_number, position);
205 if (event_number == 0) {
206 pEvt = pEvtColl->at(0);
207 }
208 else if (position != ExtendedBarCode::UNDEFINED) {
209 if (position < pEvtColl->size()) {
210 pEvt = pEvtColl->at (position);
211 }
212 else {
213 #if 0
214 MsgStream log (Athena::getMessageSvc(), "HepMcParticleLink");
215 log << MSG::WARNING << "cptr: position = " << position << ", McEventCollection size = "<< pEvtColl->size() << endmsg;
216 #endif
217 return nullptr;
218 }
219 }
220 else {
221 pEvt = pEvtColl->find (event_number);
222 }
223
224 if (nullptr != pEvt) {
225 // Be sure to update m_extBarcode before m_ptrs;
226 // otherwise, the logic in eventIndex() won't work correctly.
227 if (position != ExtendedBarCode::UNDEFINED) {
228 m_extBarcode.makeIndex (pEvt->event_number(), position);
229 }
230 if (event_number == 0) {
231 m_extBarcode.makeIndex (pEvt->event_number(), position);
232 }
233 if ( !m_extBarcode.linkIsNull() ) { // Check that either the ID or Barcode is non-zero or undefined
234 barcode_type particle_id, particle_barcode;
235 m_extBarcode.uniqueID (particle_id, particle_barcode);
236 if (particle_id == ExtendedBarCode::UNDEFINEDBC) {
237 // barcode to GenParticle
238 const HepMC::ConstGenParticlePtr p = HepMC::barcode_to_particle(pEvt,int(particle_barcode));
239 if (p) {
240 int genParticleID = HepMC::uniqueID(p);
241 if (genParticleID > -1) {
242 particle_id = static_cast<barcode_type>(genParticleID);
243 m_extBarcode.makeID (particle_id, particle_barcode);
244 }
245 m_ptr.set (p);
246 return p;
247 }
248 }
249 else {
250 // id to GenParticle
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 }
260 }
261 } else {
262 MsgStream log (Athena::getMessageSvc(), "HepMcParticleLink");
263 if (position != ExtendedBarCode::UNDEFINED) {
264 log << MSG::WARNING
265 << "cptr: Mc Truth not stored for event at " << position
266 << endmsg;
267 } else {
268 log << MSG::WARNING
269 << "cptr: Mc Truth not stored for event with event number " << event_number
270 << endmsg;
271 }
272 }
273 } else {
274 MsgStream log (Athena::getMessageSvc(), "HepMcParticleLink");
275 log << MSG::WARNING << "cptr: McEventCollection not found" << endmsg;
276 }
277 return nullptr;
278}
279
280
285{
286 // if m_BC is zero (delta rays), then just return that same for barcode and id
287 if (m_extBarcode.uid()) {
288 // dummy link
289 if (!m_ptr.isValid() && !m_store) {
290 return 0; // TODO Decide if this is a good default - constant from MagicNumbers.h instead?
291 }
292
293 barcode_type particle_id, particle_barcode;
294 m_extBarcode.uniqueID (particle_id, particle_barcode);
295 if (particle_id == ExtendedBarCode::UNDEFINEDBC) {
296 (void) cptr(); // FIXME be careful to avoid an infinite loop of calls here
297 m_extBarcode.uniqueID (particle_id, particle_barcode);
298 }
299 if (particle_id != ExtendedBarCode::UNDEFINEDBC) {
300 return particle_id;
301 }
302 }
303 return 0;
304}
305
306
312{
313 // if m_BC is zero (delta rays), then just return that same for barcode and id
314 if (m_extBarcode.uid()) {
315 barcode_type particle_id, particle_barcode;
316 m_extBarcode.uniqueID (particle_id, particle_barcode);
317 if (particle_barcode != ExtendedBarCode::UNDEFINEDBC) {
318 return int(particle_barcode);
319 }
320 // dummy link
321 if (!m_ptr.isValid() && !m_store) {
322 return 0; // TODO Decide if this is a good default - constant from MagicNumbers.h instead?
323 }
324 // we will need to look up the barcode from the GenParticle
325 (void) eventIndex(); // FIXME be careful to avoid an infinite loop of calls here
326 if (cptr()) {
327 return HepMC::barcode(cptr());
328 }
329 }
330 return 0;
331}
332
333
339{
340 // dummy link
341 if (!m_ptr.isValid() && !m_store) {
343 }
344
345 index_type event_number, event_position;
346 m_extBarcode.eventIndex (event_number, event_position);
347 if (event_number == ExtendedBarCode::UNDEFINED) {
348 const HepMC::GenEvent* pEvt{};
350 if (event_position < coll->size()) {
351 pEvt = coll->at (event_position);
352 }
353 if (pEvt) {
354 const int genEventNumber = pEvt->event_number();
355 // Be sure to update m_extBarcode before m_ptr.
356 // Otherwise, if two threads run this method simultaneously,
357 // one thread could see event_number == UNDEFINED, but where m_ptr
358 // is already updated so we get nullptr back for sg.
359 if (genEventNumber > -1) {
360 event_number = static_cast<index_type>(genEventNumber);
361 m_extBarcode.makeIndex (event_number, event_position);
362 return event_number;
363 }
364 if (barcode() != 0) {
366 if (pp) {
367 m_ptr.set (pp);
368 }
369 }
370 }
371 }
372 }
373 // Don't trip the assertion for a null link.
374 if ( m_extBarcode.linkIsNull() )
375 {
376 return (event_number != ExtendedBarCode::UNDEFINED) ? event_number : 0;
377 }
378 // Attempt to find the GenParticle
379 cptr();
380 // Check if event_number is valid once more
381 m_extBarcode.eventIndex (event_number, event_position);
382 assert (event_number != ExtendedBarCode::UNDEFINED);
383 return event_number;
384}
385
386
393{
394 index_type event_number, position;
395 m_extBarcode.eventIndex (event_number, position);
396 if (position != ExtendedBarCode::UNDEFINED) {
397 return position;
398 }
399 if (event_number == 0) {
400 return 0;
401 }
402
403 std::vector<index_type> positions = getEventPositionInCollection(event_number, sg);
404 return positions[0];
405}
406
407
418
419
424std::vector<HepMcParticleLink::index_type>
426{
427 std::vector<index_type> positions; positions.reserve(1);
428 const int int_event_number = static_cast<int>(event_number);
429 if (const McEventCollection* coll = retrieveMcEventCollection (sg)) {
430 size_t sz = coll->size();
431 for (size_t i = 0; i < sz; i++) {
432 if ((*coll)[i]->event_number() == int_event_number) {
433 positions.push_back(i);
434 }
435 }
436 }
437 if (positions.empty() ) {
438 positions.push_back(ExtendedBarCode::UNDEFINED);
439 }
440 return positions;
441}
442
443
449{
450 if (const McEventCollection* coll = retrieveMcEventCollection (sg)) {
451 if (position < coll->size()) {
452 return coll->at (position)->event_number();
453 }
454 }
455#if 0
456 MsgStream log (Athena::getMessageSvc(), "HepMcParticleLink");
457 log << MSG::WARNING << "getEventNumberAtPosition: position = " << position << ", McEventCollection size = "<< coll->size() << endmsg;
458#endif
459 return -999;
460}
461
462
467int HepMcParticleLink::getEventNumberAtPosition (index_type position, const EventContext& ctx)
468{
470}
471
472
480HepMcParticleLink HepMcParticleLink::getRedirectedLink(const HepMcParticleLink& particleLink, uint32_t eventIndex, const EventContext& ctx)
481{
482 const HepMcParticleLink::PositionFlag idxFlag =
484 // Support reading in legacy barcode-based persistent EDM for now
485 const int uniqueID =
486 (particleLink.barcode() != 0) ? particleLink.barcode() : particleLink.id();
487 const HepMcParticleLink::UniqueIDFlag uidFlag =
489 HepMcParticleLink redirectedLink(uniqueID, eventIndex, idxFlag, uidFlag, ctx);
490 redirectedLink.setTruthSuppressionType(particleLink.getTruthSuppressionType());
491 return redirectedLink;
492}
493
494
499{
500 m_extBarcode = extBarcode;
501 m_store = SG::CurrentEventStore::store();
502 m_ptr.reset();
503}
504
505
513{
514 const McEventCollection* pEvtColl = nullptr;
515 SG::DataProxy* proxy = find_proxy (sg);
516 if (proxy) {
517 pEvtColl = SG::DataProxy_cast<McEventCollection> (proxy);
518 if (!pEvtColl) {
519 MsgStream log (Athena::getMessageSvc(), "HepMcParticleLink");
520 log << MSG::WARNING << "cptr: McEventCollection not found" << endmsg;
521 }
522 }
523 return pEvtColl;
524}
525
532{
534 unsigned int hint_orig = s_hint.load(std::memory_order_relaxed);
535 if (hint_orig >= NKEYS) hint_orig = 0;
536 unsigned int hint = hint_orig;
537 do {
538 SG::DataProxy* proxy = sg->proxy (clid, s_keys[hint]);
539 if (proxy) {
540 if (hint != s_hint.load(std::memory_order_relaxed)) {
541 s_hint.store(hint, std::memory_order_relaxed);
542 }
543 static std::once_flag log_flag;
544 std::call_once(log_flag, [hint]() {
545 MsgStream log (Athena::getMessageSvc(), "HepMcParticleLink");
546 log << MSG::INFO << "find_proxy: Using " << s_keys[hint]
547 << " as McEventCollection key for this job " << endmsg;
548 });
549 return proxy;
550 }
551 ++hint;
552 if (hint >= NKEYS) hint = 0;
553 } while (hint != hint_orig);
554
555 MsgStream log (Athena::getMessageSvc(), "HepMcParticleLink");
556 static std::atomic<unsigned long> msgCount {0};
557 unsigned int count = ++msgCount;
558 if (count <= CPTRMAXMSGCOUNT) {
559 log << MSG::WARNING << "find_proxy: No Valid MC event Collection found "
560 << endmsg;
561 }
562 if (count == CPTRMAXMSGCOUNT) {
563 log << MSG::WARNING <<"find_proxy: suppressing further messages about valid MC event Collection. Use \n"
564 << " msgSvc.setVerbose += [HepMcParticleLink]\n"
565 << "to see all messages" << endmsg;
566 }
567 if (count > CPTRMAXMSGCOUNT) {
568 log << MSG::VERBOSE << "find_proxy: No Valid MC event Collection found "
569 << endmsg;
570 }
571 return nullptr;
572}
573
574
579{
580 static const std::string unset = "CollectionNotSet";
581 unsigned idx = s_hint;
582 if (idx < NKEYS) {
583 return s_keys[idx];
584 }
585 return unset;
586}
587
588
594std::ostream&
595operator<< (std::ostream& os, const HepMcParticleLink& link)
596{
597 link.m_extBarcode.print(os);
598 return os;
599}
600
601
607MsgStream&
608operator<< (MsgStream& os, const HepMcParticleLink& link)
609{
610 link.m_extBarcode.print(os);
611 return os;
612}
#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)
IProxyDict * proxyDictFromEventContext()
Return the IProxyDict for this thread's current context.
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