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) {
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
419std::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
465HepMcParticleLink HepMcParticleLink::getRedirectedLink(const HepMcParticleLink& particleLink, uint32_t eventIndex, const EventContext& ctx)
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
498{
499 const McEventCollection* pEvtColl = nullptr;
500 SG::DataProxy* proxy = find_proxy (sg);
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
579std::ostream&
580operator<< (std::ostream& os, const HepMcParticleLink& link)
581{
582 link.m_extBarcode.print(os);
583 return os;
584}
585
586
592MsgStream&
593operator<< (MsgStream& os, const HepMcParticleLink& link)
594{
595 link.m_extBarcode.print(os);
596 return os;
597}
#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.
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...
static IProxyDict * store()
Fetch the current store.
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:146
IMessageSvc * getMessageSvc(bool quiet=false)
GenParticle * barcode_to_particle(const GenEvent *e, int id)
Definition GenEvent.h:630
int barcode(const T *p)
Definition Barcode.h:16
int uniqueID(const T &p)
const GenParticle * ConstGenParticlePtr
Definition GenParticle.h:38
DATA * DataProxy_cast(DataProxy *proxy)
cast the proxy into the concrete data object it proxies