ATLAS Offline Software
Loading...
Searching...
No Matches
HepMcParticleLink.icc
Go to the documentation of this file.
1/*
2 * Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration.
3 */
4/**
5 * @file GeneratorObjects/HepMcParticleLink.icc
6 * @author scott snyder <snyder@bnl.gov>
7 * @date Feb, 2019
8 * @brief a link optimized in size for a GenParticle in a McEventCollection
9 */
10
11
12//**************************************************************************
13// ExtendedBarCode
14//
15
16inline
17HepMcParticleLink::ExtendedBarCode::ExtendedBarCode()
18{
19}
20
21
22/**
23 * @brief Constructor.
24 * @param uid Unique ID of target particle.
25 * @param eventIndex Identifies the target GenEvent in a McEventCollection,
26 * as either the event number if @c isIndexEventPosition is IS_EVENTNUM,
27 * or the position in the container
28 * if isIndexEventPosition is IS_POSITION.
29 * 0 always means the first event in the collection.
30 * @param isIndexEventPosition: See @c eventIndex.
31 */
32inline
33HepMcParticleLink::ExtendedBarCode::ExtendedBarCode
34 (barcode_type uid,
35 index_type eventIndex,
36 PositionFlag isIndexEventPosition /*=IS_EVENTNUM*/,
37 UniqueIDFlag isUniqueIDBarcode /*= IS_ID*/)
38{
39 setIndex (eventIndex, isIndexEventPosition);
40 setUniqueID (uid, isUniqueIDBarcode);
41}
42
43
44/**
45 * @brief Copy constructor. (Can't be defaulted due to the atomic member.)
46 */
47inline
48HepMcParticleLink::ExtendedBarCode::ExtendedBarCode (const ExtendedBarCode& rhs)
49 : m_BC (static_cast<barcode_type> (rhs.m_BC)),
50 m_evtIndex (static_cast<index_type> (rhs.m_evtIndex)),
51 m_truthSupp (rhs.m_truthSupp)
52{
53}
54
55
56/**
57 * @brief Move constructor. (Can't be defaulted due to the atomic member.)
58 */
59inline
60HepMcParticleLink::ExtendedBarCode::ExtendedBarCode (ExtendedBarCode&& rhs) noexcept
61 : m_BC (rhs.m_BC.load()), // no move constructor for atomics
62 m_evtIndex (rhs.m_evtIndex.load()), // no move constructor for atomics
63 m_truthSupp (std::exchange(rhs.m_truthSupp,EBC_UNSUPPRESSED))
64{
65}
66
67/**
68 * @brief Assignment. (Can't be defaulted due to the atomic member.)
69 */
70inline
71HepMcParticleLink::ExtendedBarCode&
72HepMcParticleLink::ExtendedBarCode::operator= (const ExtendedBarCode& rhs)
73{
74 if (this != &rhs) {
75 m_BC = static_cast<barcode_type> (rhs.m_BC);
76 m_evtIndex = static_cast<index_type> (rhs.m_evtIndex);
77 m_truthSupp=rhs.m_truthSupp;
78 }
79 return *this;
80}
81
82/**
83 * @brief Assignment. (Can't be defaulted due to the atomic member.)
84 */
85inline
86HepMcParticleLink::ExtendedBarCode&
87HepMcParticleLink::ExtendedBarCode::operator= (ExtendedBarCode&& rhs) noexcept
88{
89 if (this != &rhs) {
90 m_BC = static_cast<barcode_type> (rhs.m_BC.load());
91 m_evtIndex = static_cast<index_type>(rhs.m_evtIndex.load());
92 m_truthSupp = std::exchange(rhs.m_truthSupp, EBC_UNSUPPRESSED);
93 }
94 return *this;
95}
96
97
98/**
99 * @brief Unique ID of target variable (0 for a null link).
100 */
101inline
102HepMcParticleLink::barcode_type
103HepMcParticleLink::ExtendedBarCode::uid() const
104{
105 return m_BC;
106}
107
108
109/**
110 * @brief Return the event index/position.
111 * @param index[out] Event index (number), or @c UNDEFINED.
112 * @param position[out] Event position, or @c UNDEFINED.
113 *
114 * The GenEvent within the McEventCollection is identified either by
115 * the GenEvent number or by the position within the collection.
116 * This method will return this by setting either @c index or @c position;
117 * the other one is set to @c UNDEFINED.
118 */
119inline
120void HepMcParticleLink::ExtendedBarCode::eventIndex (index_type& index,
121 index_type& position) const
122{
123 index_type idx = m_evtIndex;
124 if (idx & POSITION_MASK) {
125 index = UNDEFINED;
126 position = idx & ~POSITION_MASK;
127 }
128 else {
129 index = idx;
130 position = UNDEFINED;
131 }
132}
133
134
135/**
136 * @brief Return the GenParticle id/barcode.
137 * @param id[out] GenParticle::id, or @c UNDEFINEDBC.
138 * @param barcode[out] barcode (deprecated), or @c UNDEFINEDBC.
139 *
140 * The GenParticle within the GenEvent is identified either by
141 * the GenParticle::id or the barcode.
142 * This method will return this by setting either @c id or @c barcode;
143 * the other one is set to @c UNDEFINEDBC.
144 */
145inline
146void HepMcParticleLink::ExtendedBarCode::uniqueID (barcode_type& id,
147 barcode_type& barcode) const
148{
149 barcode_type uid = m_BC;
150 if (uid == 0) // special case for delta-rays
151 {
152 id = uid;
153 barcode = uid;
154 }
155 else if (uid & BARCODE_MASK) {
156 id = UNDEFINEDBC;
157 barcode = uid & ~BARCODE_MASK;
158 }
159 else {
160 id = uid;
161 barcode = UNDEFINEDBC;
162 }
163}
164
165
166/**
167 * @brief Return which collection we're targeting, as a char ('a'..'b').
168 */
169inline
170char HepMcParticleLink::ExtendedBarCode::getTruthSuppressionTypeAsChar() const
171{
172 return truthSuppressionTypeAsChar (m_truthSupp);
173}
174
175
176/**
177 * @brief Equality test.
178 *
179 * Be aware: if one EBC holds the target GenEvent by number and the
180 * other by position, then this will always return false, even if they
181 * reference the same GenEvent.
182 * To avoid this, use HepMcParticleLink::operator=.
183 */
184inline
185bool
186HepMcParticleLink::ExtendedBarCode::operator==(const ExtendedBarCode& rhs) const
187{
188 return (this->m_BC == rhs.m_BC &&
189 this->m_truthSupp == rhs.m_truthSupp &&
190 this->m_evtIndex == rhs.m_evtIndex);
191}
192
193
194/**
195 * @brief Inequality test.
196 *
197 * Be aware: if one EBC holds the target GenEvent by number and the
198 * other by position, then this will always return true, even if they
199 * reference the same GenEvent.
200 * To avoid this, use HepMcParticleLink::operator=.
201 */
202inline
203bool
204HepMcParticleLink::ExtendedBarCode::operator!= (const ExtendedBarCode& rhs) const
205{
206 return !(operator==(rhs));
207}
208
209
210/**
211 * @brief Ordering test.
212 *
213 * Be aware: if one EBC holds the target GenEvent by number and the
214 * other by position, then this will not work as expected.
215 * To avoid this, use HepMcParticleLink::operator=.
216 */
217inline
218bool
219HepMcParticleLink::ExtendedBarCode::operator< (const ExtendedBarCode& rhs) const
220{
221 return (m_truthSupp < rhs.m_truthSupp ||
222 (m_truthSupp == rhs.m_truthSupp && m_evtIndex < rhs.m_evtIndex) ||
223 (m_truthSupp == rhs.m_truthSupp && m_evtIndex == rhs.m_evtIndex && m_BC < rhs.m_BC) ) ;
224}
225
226
227/**
228 * @brief Compare the event index part of two links.
229 * @param lhs First link to compare.
230 * @param rhs Second link to compare.
231 * @returns -1, 0, or 1, depending on the result of the comparison.
232 *
233 * The event index part of the link can be represented as either
234 * an event number or the position within the container.
235 * If necessary, the links will be normalized so that they
236 * both refer to an event number.
237 */
238inline
239int
240HepMcParticleLink::ExtendedBarCode::compareIndex (const HepMcParticleLink& lhs,
241 const HepMcParticleLink& rhs)
242{
243 // Get the stored indices. The high bit will be set of they
244 // represent a position. Do a quick test for equality.
245 index_type idx1 = lhs.m_extBarcode.m_evtIndex;
246 index_type idx2 = rhs.m_extBarcode.m_evtIndex;
247 if (idx1 == idx2) return 0;
248
249 // Normalize the values so that they both refer to event number;
250 // this happens as a side-effect of calling cptr().
251 if (idx1 & POSITION_MASK) {
252 lhs.cptr();
253 idx1 = lhs.m_extBarcode.m_evtIndex;
254 }
255 if (idx2 & POSITION_MASK) {
256 rhs.cptr();
257 idx2 = rhs.m_extBarcode.m_evtIndex;
258 }
259
260 // Compare.
261 if (idx1 == idx2) {
262 return 0;
263 }
264 else if (idx1 < idx2) {
265 return -1;
266 }
267 else {
268 return 1;
269 }
270}
271
272
273
274/**
275 * @brief Compare the unique ID part of two links.
276 * @param lhs First link to compare.
277 * @param rhs Second link to compare.
278 * @returns -1, 0, or 1, depending on the result of the comparison.
279 *
280 * The unique ID part of the link can be represented as either
281 * a barcode or the id.
282 * If necessary, the links will be normalized so that they
283 * both refer to an id.
284 */
285inline
286int
287HepMcParticleLink::ExtendedBarCode::compareUniqueID (const HepMcParticleLink& lhs,
288 const HepMcParticleLink& rhs)
289{
290 // Get the stored indices. The high bit will be set of they
291 // represent a position. Do a quick test for equality.
292 barcode_type uid1 = lhs.m_extBarcode.m_BC;
293 barcode_type uid2 = rhs.m_extBarcode.m_BC;
294 if (uid1 == uid2) return 0;
295
296 // Normalize the values so that they both refer to the id;
297 // this happens as a side-effect of calling cptr().
298 if (uid1 & BARCODE_MASK) {
299 lhs.cptr();
300 uid1 = lhs.m_extBarcode.m_BC;
301 }
302 if (uid2 & BARCODE_MASK) {
303 rhs.cptr();
304 uid2 = rhs.m_extBarcode.m_BC;
305 }
306 // Compare.
307 if (uid1 == uid2) {
308 return 0;
309 }
310 else if (uid1 < uid2) {
311 return -1;
312 }
313 else {
314 return 1;
315 }
316}
317
318
319/**
320 * @brief Change m_BC from barcode to ID.
321 * @param ID GenParticle::id value to set.
322 * @param barcode existing barcode value.
323 *
324 * If the link is currently referencing a GenParticle with @c barcode,
325 * update it so that it instead references the GenParticle
326 * with id value @c ID.
327 *
328 * This may be called concurrently, as long as all such concurrent
329 * calls have the same arguments.
330 */
331inline
332void HepMcParticleLink::ExtendedBarCode::makeID (barcode_type ID,
333 barcode_type barcode) const
334{
335 assert ((ID & BARCODE_MASK) == 0);
336 barcode_type old = barcode | BARCODE_MASK;
337 m_BC.compare_exchange_strong (old, ID);
338 assert (old == (barcode|BARCODE_MASK) || old == ID);
339}
340
341
342/**
343 * @brief Change index from position to number.
344 * @param index Event number to set.
345 * @param position Existing event position.
346 *
347 * If the link is currently referencing the GenEvent at @c position,
348 * update it so that it instead references the GenEvent
349 * with number @c index.
350 *
351 * This may be called concurrently, as long as all such concurrent
352 * calls have the same arguments.
353 */
354inline
355void HepMcParticleLink::ExtendedBarCode::makeIndex (index_type index,
356 index_type position) const
357{
358 assert ((index & POSITION_MASK) == 0);
359 index_type old = position | POSITION_MASK;
360 m_evtIndex.compare_exchange_strong (old, index);
361 assert (old == (position|POSITION_MASK) || old == index || (position==UNDEFINED && old==0));
362}
363
364
365/**
366 * @brief Initialize the unique identifier part of the link.
367 * @param uid The id or barcode.
368 * @param barcodeFlag If IS_BARCODE, @c uid represents a GenParticle barcode (deprecated);
369 * otherwise, it represents a GenParticle::id().
370 */
371inline
372void
373HepMcParticleLink::ExtendedBarCode::setUniqueID (barcode_type uid,
374 UniqueIDFlag barcodeFlag)
375{
376 assert ((uid & BARCODE_MASK) == 0);
377 // For delta-rays barcode=id=0
378 if (uid != 0 && barcodeFlag == IS_BARCODE) {
379 uid |= BARCODE_MASK;
380 }
381 m_BC = uid;
382}
383
384
385/**
386 * @brief Initialize the event index part of the link.
387 * @param idx The index or position.
388 * @param positionFlag If IS_POSITION, @c idx represents a position
389 * in the collection; otherwise, it represents an event number.
390 */
391inline
392void
393HepMcParticleLink::ExtendedBarCode::setIndex (index_type idx,
394 PositionFlag positionFlag)
395{
396 assert ((idx & POSITION_MASK) == 0);
397 if (positionFlag == IS_POSITION) {
398 idx |= POSITION_MASK;
399 }
400 m_evtIndex = idx;
401}
402
403inline bool HepMcParticleLink::ExtendedBarCode::linkIsNull() const
404{
405 barcode_type particle_id, particle_barcode;
406 uniqueID (particle_id, particle_barcode);
407 return (
408 (particle_id == 0 && particle_barcode == 0) || // delta rays
409 (particle_id == 0 && particle_barcode == ExtendedBarCode::UNDEFINEDBC) ||
410 (particle_id == ExtendedBarCode::UNDEFINEDBC && particle_barcode == 0)
411 );
412}
413
414
415//**************************************************************************
416// HepMcParticleLink
417//
418
419
420/**
421 * @brief Default constructor. Makes a null link.
422 * @param sg Optional specification of a specific store to reference.
423 */
424inline
425HepMcParticleLink::HepMcParticleLink (IProxyDict* sg /*= nullptr*/)
426 : m_store (sg)
427{
428}
429
430
431/**
432 * @brief Default constructor. Makes a null link.
433 * @param ctx Context of the store to reference.
434 */
435inline
436HepMcParticleLink::HepMcParticleLink (const EventContext& ctx)
437 : HepMcParticleLink (Atlas::getExtendedEventContext(ctx).proxy())
438{
439}
440
441/**
442 * @brief Constructor.
443 * @param uid Unique ID of the target particle. 0 means a null link.
444 * @param eventIndex Identifies the target GenEvent in a McEventCollection,
445 * as either the event number if @c isIndexEventPosition is IS_EVENTNUM,
446 * or the position in the container
447 * if isIndexEventPosition is IS_POSITION.
448 * 0 always means the first event in the collection.
449 * @param positionFlag: See @c eventIndex.
450 * @param sg Optional specification of a specific store to reference.
451 */
452inline
453HepMcParticleLink::HepMcParticleLink (barcode_type uid,
454 uint32_t eventIndex /*= 0*/,
455 PositionFlag positionFlag /*= IS_EVENTNUM*/,
456 UniqueIDFlag uniqueIDFlag /*= IS_ID*/,
457 IProxyDict* sg /*= SG::CurrentEventStore::store()*/)
458 : m_store (sg),
459 m_extBarcode (uid, eventIndex, positionFlag, uniqueIDFlag)
460{
461}
462
463
464/**
465 * @brief Constructor.
466 * @param uid Unique ID of the target particle. 0 means a null link.
467 * @param eventIndex Identifies the target GenEvent in a McEventCollection,
468 * as either the event number if @c isIndexEventPosition is IS_EVENTNUM,
469 * or the position in the container
470 * if isIndexEventPosition is IS_POSITION.
471 * 0 always means the first event in the collection.
472 * @param positionFlag: See @c eventIndex.
473 * @param ctx Context of the store to reference.
474 */
475inline
476HepMcParticleLink::HepMcParticleLink (barcode_type uid,
477 uint32_t eventIndex,
478 PositionFlag positionFlag,
479 UniqueIDFlag uniqueIDFlag,
480 const EventContext& ctx)
481 : HepMcParticleLink (uid, eventIndex, positionFlag, uniqueIDFlag,
482 Atlas::getExtendedEventContext(ctx).proxy())
483{
484}
485
486
487/**
488 * @brief Constructor.
489 * @param p Particle to reference.
490 * @param eventIndex Identifies the target GenEvent in a McEventCollection,
491 * as either the event number if @c isIndexEventPosition is IS_EVENTNUM,
492 * or the position in the container
493 * if isIndexEventPosition is IS_POSITION.
494 * 0 always means the first event in the collection.
495 * @param positionFlag: See @c eventIndex.
496 * @param ctx Context of the store to reference.
497 */
498inline
499HepMcParticleLink::HepMcParticleLink (const HepMC::ConstGenParticlePtr& part,
500 uint32_t eventIndex,
501 PositionFlag positionFlag,
502 const EventContext& ctx)
503 : HepMcParticleLink (part, eventIndex, positionFlag,
504 Atlas::getExtendedEventContext(ctx).proxy())
505{
506}
507
508/**
509 * @brief Dereference.
510 */
511inline
512const HepMC::GenParticle& HepMcParticleLink::operator* () const
513{
514 return *cptr();
515}
516
517
518/**
519 * @brief Dereference.
520 */
521inline
522HepMC::ConstGenParticlePtr HepMcParticleLink::operator->() const
523{
524 return cptr();
525}
526
527
528/**
529 * @brief Dereference.
530 */
531inline
532HepMcParticleLink::operator HepMC::ConstGenParticlePtr() const
533{
534 return cptr();
535}
536
537
538/**
539 * @brief Validity check. Dereference and check for null.
540 */
541inline
542bool HepMcParticleLink::isValid() const
543{
544 return (nullptr != cptr());
545}
546
547
548/**
549 * @brief Validity check. Dereference and check for null.
550 */
551inline
552bool HepMcParticleLink::operator!() const
553{
554 return !isValid();
555}
556
557
558/**
559 * @brief Validity check. Dereference and check for null.
560 */
561inline
562HepMcParticleLink::operator bool() const
563{
564 return isValid();
565}
566
567
568/**
569 * @brief Equality comparison.
570 */
571inline
572bool HepMcParticleLink::operator== (const HepMcParticleLink& rhs) const
573{
574 return (m_extBarcode.getTruthSuppressionType()==rhs.m_extBarcode.getTruthSuppressionType() &&
575 ExtendedBarCode::compareUniqueID(*this, rhs) == 0 &&
576 ExtendedBarCode::compareIndex (*this, rhs) == 0);
577}
578
579
580/**
581 * @brief Inequality comparison.
582 */
583inline
584bool HepMcParticleLink::operator!= (const HepMcParticleLink& rhs) const
585{
586 return !(operator==(rhs));
587}
588
589
590/**
591 * @brief Ordering comparison.
592 */
593inline
594bool HepMcParticleLink::operator< (const HepMcParticleLink& rhs) const
595{
596 if (m_extBarcode.getTruthSuppressionType() < rhs.m_extBarcode.getTruthSuppressionType()) return true;
597 if (m_extBarcode.getTruthSuppressionType() == rhs.m_extBarcode.getTruthSuppressionType()) {
598 int cmpIndex = ExtendedBarCode::compareIndex (*this, rhs);
599 if (cmpIndex < 0) return true;
600 if (cmpIndex == 0) {
601 if (ExtendedBarCode::compareUniqueID(*this, rhs) < 0) return true;
602 }
603 }
604 return false;
605}
606
607
608/**
609 * @brief Return whether the truth particle has been suppressed, as an enum.
610 */
611inline
612EBC_SUPPRESSED_TRUTH HepMcParticleLink::getTruthSuppressionType() const
613{
614 return m_extBarcode.getTruthSuppressionType();
615}
616
617
618/**
619 * @brief Return whether the truth particle has been suppressed.
620 */
621inline void HepMcParticleLink::setTruthSuppressionType(EBC_SUPPRESSED_TRUTH truthSupp)
622{
623 m_extBarcode.setTruthSuppressionType(truthSupp);
624}
625
626
627/**
628 * @brief Return whether the truth particle has been suppressed, as a char ('a'..'b').
629 */
630inline
631char HepMcParticleLink::getTruthSuppressionTypeAsChar() const
632{
633 return m_extBarcode.getTruthSuppressionTypeAsChar();
634}
635
636
637/**
638 * @brief Hash the 32-bit barcode and 16-bit eventindex into a 32bit int.
639 */
640inline
641HepMcParticleLink::barcode_type HepMcParticleLink::compress() const
642{
643 return ( ((m_extBarcode.uid()&0xFFFF) << 16) |
644 eventIndex() );
645}
646
647
648/**
649 * @brief Comparison with ConstGenParticlePtr.
650 * Needed with c++20 to break an ambiguity.
651 */
652inline
653bool operator== (HepMC::ConstGenParticlePtr a,
654 const HepMcParticleLink& b)
655{
656 return a == b.cptr();
657}