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 = std::size (s_keys);
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 (const McEventCollection* coll = retrieveMcEventCollection (sg_nc)) {
351 if (event_position < coll->size()) {
352 pEvt = coll->at (event_position);
353 }
354 if (pEvt) {
355 const int genEventNumber = pEvt->event_number();
356 // Be sure to update m_extBarcode before m_ptr.
357 // Otherwise, if two threads run this method simultaneously,
358 // one thread could see event_number == UNDEFINED, but where m_ptr
359 // is already updated so we get nullptr back for sg.
360 if (genEventNumber > -1) {
361 event_number = static_cast<index_type>(genEventNumber);
362 m_extBarcode.makeIndex (event_number, event_position);
363 return event_number;
364 }
365 if (barcode() != 0) {
367 if (pp) {
368 m_ptr.set (pp);
369 }
370 }
371 }
372 }
373 }
374 // Don't trip the assertion for a null link.
375 if ( m_extBarcode.linkIsNull() )
376 {
377 return (event_number != ExtendedBarCode::UNDEFINED) ? event_number : 0;
378 }
379 // Attempt to find the GenParticle
380 cptr();
381 // Check if event_number is valid once more
382 m_extBarcode.eventIndex (event_number, event_position);
383 assert (event_number != ExtendedBarCode::UNDEFINED);
384 return event_number;
385}
386
387
394{
395 index_type event_number, position;
396 m_extBarcode.eventIndex (event_number, position);
397 if (position != ExtendedBarCode::UNDEFINED) {
398 return position;
399 }
400 if (event_number == 0) {
401 return 0;
402 }
403
404 std::vector<index_type> positions = getEventPositionInCollection(event_number, sg);
405 return positions[0];
406}
407
408
419
420
425std::vector<HepMcParticleLink::index_type>
427{
428 std::vector<index_type> positions; positions.reserve(1);
429 const int int_event_number = static_cast<int>(event_number);
430 if (const McEventCollection* coll = retrieveMcEventCollection (sg)) {
431 size_t sz = coll->size();
432 for (size_t i = 0; i < sz; i++) {
433 if ((*coll)[i]->event_number() == int_event_number) {
434 positions.push_back(i);
435 }
436 }
437 }
438 if (positions.empty() ) {
439 positions.push_back(ExtendedBarCode::UNDEFINED);
440 }
441 return positions;
442}
443
444
450{
451 if (const McEventCollection* coll = retrieveMcEventCollection (sg)) {
452 if (position < coll->size()) {
453 return coll->at (position)->event_number();
454 }
455 }
456#if 0
457 MsgStream log (Athena::getMessageSvc(), "HepMcParticleLink");
458 log << MSG::WARNING << "getEventNumberAtPosition: position = " << position << ", McEventCollection size = "<< coll->size() << endmsg;
459#endif
460 return -999;
461}
462
463
468int HepMcParticleLink::getEventNumberAtPosition (index_type position, const EventContext& ctx)
469{
471}
472
473
481HepMcParticleLink HepMcParticleLink::getRedirectedLink(const HepMcParticleLink& particleLink, uint32_t eventIndex, const EventContext& ctx)
482{
483 const HepMcParticleLink::PositionFlag idxFlag =
485 // Support reading in legacy barcode-based persistent EDM for now
486 const int uniqueID =
487 (particleLink.barcode() != 0) ? particleLink.barcode() : particleLink.id();
488 const HepMcParticleLink::UniqueIDFlag uidFlag =
490 HepMcParticleLink redirectedLink(uniqueID, eventIndex, idxFlag, uidFlag, ctx);
491 redirectedLink.setTruthSuppressionType(particleLink.getTruthSuppressionType());
492 return redirectedLink;
493}
494
495
500{
501 m_extBarcode = extBarcode;
502 m_store = SG::CurrentEventStore::store();
503 m_ptr.reset();
504}
505
506
514{
515 const McEventCollection* pEvtColl = nullptr;
516 SG::DataProxy* proxy = find_proxy (sg);
517 if (proxy) {
518 pEvtColl = SG::DataProxy_cast<McEventCollection> (proxy);
519 if (!pEvtColl) {
520 MsgStream log (Athena::getMessageSvc(), "HepMcParticleLink");
521 log << MSG::WARNING << "cptr: McEventCollection not found" << endmsg;
522 }
523 }
524 return pEvtColl;
525}
526
533{
535 unsigned int hint_orig = s_hint.load(std::memory_order_relaxed);
536 if (hint_orig >= std::size (s_keys)) hint_orig = 0;
537 unsigned int hint = hint_orig;
538
539 // Cache key -> sgkey translation.
540 using sgkey_array_t = std::array<SG::sgkey_t, std::size (s_keys)>;
541 static const sgkey_array_t s_sgkeys =
542 [&]() {
543 sgkey_array_t a;
544 for (size_t i = 0; i < std::size (s_keys); ++i)
545 a[i] = sg->stringToKey (s_keys[i], clid);
546 return a;
547 }();
548
549 do {
550 SG::DataProxy* proxy = sg->proxy (clid, s_keys[hint]);
551 if (!proxy) {
552 // try with input renamng.
553 SG::DataProxyHolder holder;
554 holder.toTransient (s_sgkeys[hint], sg, true);
555 proxy = holder.proxy();
556 }
557 if (proxy) {
558 if (hint != s_hint.load(std::memory_order_relaxed)) {
559 s_hint.store(hint, std::memory_order_relaxed);
560 }
561 static std::once_flag log_flag;
562 std::call_once(log_flag, [hint]() {
563 MsgStream log (Athena::getMessageSvc(), "HepMcParticleLink");
564 log << MSG::INFO << "find_proxy: Using " << s_keys[hint]
565 << " as McEventCollection key for this job " << endmsg;
566 });
567 return proxy;
568 }
569 ++hint;
570 if (hint >= std::size (s_keys)) hint = 0;
571 } while (hint != hint_orig);
572
573 MsgStream log (Athena::getMessageSvc(), "HepMcParticleLink");
574 static std::atomic<unsigned long> msgCount {0};
575 unsigned int count = ++msgCount;
576 if (count <= CPTRMAXMSGCOUNT) {
577 log << MSG::WARNING << "find_proxy: No Valid MC event Collection found "
578 << endmsg;
579 }
580 if (count == CPTRMAXMSGCOUNT) {
581 log << MSG::WARNING <<"find_proxy: suppressing further messages about valid MC event Collection. Use \n"
582 << " msgSvc.setVerbose += [HepMcParticleLink]\n"
583 << "to see all messages" << endmsg;
584 }
585 if (count > CPTRMAXMSGCOUNT) {
586 log << MSG::VERBOSE << "find_proxy: No Valid MC event Collection found "
587 << endmsg;
588 }
589 return nullptr;
590}
591
592
597{
598 static const std::string unset = "CollectionNotSet";
599 unsigned idx = s_hint;
600 if (idx < std::size (s_keys)) {
601 return s_keys[idx];
602 }
603 return unset;
604}
605
606
612std::ostream&
613operator<< (std::ostream& os, const HepMcParticleLink& link)
614{
615 link.m_extBarcode.print(os);
616 return os;
617}
618
619
625MsgStream&
626operator<< (MsgStream& os, const HepMcParticleLink& link)
627{
628 link.m_extBarcode.print(os);
629 return os;
630}
#define endmsg
Hold a pointer to the current event store.
uint32_t CLID
The Class ID type.
static Double_t sz
static Double_t a
static Double_t ss
EBC_SUPPRESSED_TRUTH
@ EBC_NSUPP
@ EBC_PU_SUPPRESSED
@ EBC_UNSUPPRESSED
size_t size() const
Number of registered mappings.
void print(char *figname, TCanvas *c1)
#define ATLAS_THREAD_SAFE
virtual SG::DataProxy * proxy(const CLID &id, const std::string &key) const =0
Get proxy with given id and key.
virtual sgkey_t stringToKey(const std::string &str, CLID clid)=0
Find the key for a string/CLID pair.
This defines the McEventCollection, which is really just an ObjectVector of McEvent objectsFile: Gene...
Manage DataProxy reference in ElementLink/DataLink.
void toTransient(sgkey_t sgkey, IProxyDict *sg=nullptr, bool noDummy=false)
Finish initialization after link has been read.
SG::DataProxy * proxy(bool nothrow=false) const
Return the DataProxy for this link.
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
uint32_t sgkey_t
Type used for hashed StoreGate key+CLID pairs.
Definition sgkey_t.h:32