ATLAS Offline Software
Loading...
Searching...
No Matches
CompositeParticle_v1.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2021 CERN for the benefit of the ATLAS collaboration
3*/
4
5// $Id: CompositeParticle_v1.cxx 677733 2015-06-23 19:31:10Z kkoeneke $
6
7// standard includes
8#include <cmath> /* remainder and M_PI */
9
10// Event Kernel include
11#include "TruthUtils/HepMCHelpers.h" // for MC::isElectron(...) and others
12
13// EDM include(s):
15#include "xAODBase/IParticle.h"
18
19// Local include(s):
21
22// ROOT include(s):
23#include "Math/Vector4D.h"
24
25namespace xAOD {
26
30
32 //
33 // Functions implementing four-momentum
34 //
35
41 static const SG::AuxElement::Accessor< int > pdgAcc( "pdgId" );
42
43
44 double CompositeParticle_v1::pt() const {
45 return std::hypot( px(), py() );
46 }
47
49 return p4().Eta();
50 }
51
53 return p4().Phi();
54 }
55
56 double CompositeParticle_v1::m() const {
57 return p4().M();
58 }
59
61 return p4().Rapidity();
62 }
63
65 if ( accPx.isAvailable(*this) && accPy.isAvailable(*this)
66 && accPz.isAvailable(*this) && accE.isAvailable(*this) ) {
67 // We have everything stored with this CompositeParticle. Just use it.
68 const double px = static_cast<double>(accPx(*this));
69 const double py = static_cast<double>(accPy(*this));
70 const double pz = static_cast<double>(accPz(*this));
71 const double e = static_cast<double>(accE(*this));
72 return FourMom_t( px, py, pz, e );
73 }
74 else {
75 // Not everything is stored, we need to re-calculate the p4 based on the constituents.
76 // Create an empty vector such that the subsequent call will use all constituents.
77 const std::vector<int> partIndices;
78 return p4( partIndices );
79 }
80 }
81
82 // note, if calculating from constituent particles, can be slower than p4()
84 if ( accPx.isAvailable(*this) && accPy.isAvailable(*this)
85 && accPz.isAvailable(*this) && accE.isAvailable(*this) ) {
86 // We have everything stored with this CompositeParticle. Just use it.
87 const double px = static_cast<double>(accPx(*this));
88 const double py = static_cast<double>(accPy(*this));
89 const double pz = static_cast<double>(accPz(*this));
90 const double e = static_cast<double>(accE(*this));
91 return GenVecFourMom_t( px, py, pz, e );
92 }
93 else {
94 // Not everything is stored, we need to re-calculate the p4 based on the constituents.
95 // Create an empty vector such that the subsequent call will use all constituents.
96 const std::vector<int> partIndices;
97 FourMom_t fourmom = p4(partIndices);
98 return GenVecFourMom_t(fourmom.Px(), fourmom.Py(), fourmom.Pz(), fourmom.E());
99 }
100 }
101
102 Type::ObjectType CompositeParticle_v1::type() const {
103 return Type::CompositeParticle;
104 }
105
106
107 double CompositeParticle_v1::e() const {
108 return p4().E();
109 }
110
111
113 return p4().Px();
114 }
115
116
118 return p4().Py();
119 }
120
121
123 return p4().Pz();
124 }
125
126
128 return p4().Et();
129 }
130
131
133 accPx( *this ) = static_cast<float>(vec.Px());
134 accPy( *this ) = static_cast<float>(vec.Py());
135 accPz( *this ) = static_cast<float>(vec.Pz());
136 accE( *this ) = static_cast<float>(vec.E());
137 }
138
139
141 double py,
142 double pz,
143 double e ) {
144 static const Accessor< float > acc1( "px" );
145 acc1( *this ) = (float)px;
146 static const Accessor< float > acc2( "py" );
147 acc2( *this ) = (float)py;
148 static const Accessor< float > acc3( "pz" );
149 acc3( *this ) = (float)pz;
150 static const Accessor< float > acc4( "e" );
151 acc4( *this ) = (float)e;
152 }
153
154
156 float, double,
157 px, setPx )
159 float, double,
160 py, setPy )
162 float, double,
163 pz, setPz )
165 float, double,
166 e, setE )
167
168 // End: Functions implementing four-momentum
170
171
173 //
174 // Functions implementing other particly-type properties
175 //
176
178 return chargeAcc.isAvailable( *this );
179 }
180
181
183 if ( chargeAcc.isAvailable(*this) ) {
184 // If we have stored the charge with this CompositeParticle, just use it.
185 return chargeAcc(*this);
186 }
187 else {
188 // Otherwise, try to re-calculate it from the constituents
189 float charge = 0.0;
190 // Sum up the charges of all constituents, if all have it
191 std::size_t nParts = this->nParts();
192 for ( std::size_t i=0; i<nParts; ++i ) {
193 const xAOD::IParticle* part = this->part(i);
194 if (!part) {
195 throw std::runtime_error("Got a zero pointer to an xAOD::IParticle!");
196 }
197 if ( chargeAcc.isAvailable(*part) ) {
198 charge += chargeAcc(*part);
199 }
200 else if ( part->type() != xAOD::Type::CompositeParticle ) {
201 // We have an electron
203 charge += compPart->charge();
204 }
205 } // End: loop over all constituent particles
206 return charge;
207 }
208 }
209
210
212 chargeAcc(*this) = charge;
213 return;
214 }
215
216
218 return pdgAcc.isAvailable( *this );
219 }
220
222 pdgId, setPdgId )
223
224
225 // End: Functions implementing other particly-type properties
227
228
229
230
231 //
232 // Functions returning variables that are calculated from 4-momentum
233 // information from constituents.
234 //
235
237 CompositeParticle_v1::p4( const std::vector<int>& partIndices ) const {
238 // We want a static here such that this TLorentzVector is only once in
239 // memory. We anyhow have to reset it every time this function is called.
241 fourMom.SetPxPyPzE(0.0, 0.0, 0.0, 0.0);
242 // If the given vector of indices is an empty vector, run over all particles
243 if ( partIndices.empty() ) {
244 // Sum up the 4-momenta of all constituents
245 std::size_t nParts = this->nParts();
246 for ( std::size_t i=0; i<nParts; ++i ) {
247 const xAOD::IParticle* part = this->part(i);
248 if (!part) {
249 throw std::runtime_error("Got a zero pointer to an xAOD::IParticle!");
250 }
251 fourMom += part->p4();
252 }
253 // Also add the 4-momentum of the missingET
254 const xAOD::MissingET* met = this->missingET();
255 if (met) {
256 double px = met->mpx();
257 double py = met->mpy();
258 fourMom += CompositeParticle_v1::FourMom_t( px, py, 0.0, std::hypot(px, py) );
259 }
260 }
261 else {
262 for ( int i : partIndices ) {
263 if ( i == -1 ) {
264 const xAOD::MissingET* met = this->missingET();
265 double px = met->mpx();
266 double py = met->mpy();
267 fourMom += CompositeParticle_v1::FourMom_t( px, py, 0.0, std::hypot(px, py) );
268 }
269 else if ( i < 0 ) {
270 throw std::runtime_error("Got a negative index which is not -1");
271 }
272 else {
273 const xAOD::IParticle* part = this->part(i);
274 if ( !part ) {
275 throw std::runtime_error("Got a zero pointer to an xAOD::IParticle");
276 }
277 fourMom += part->p4();
278 }
279 }
280 }
281 return fourMom;
282 }
283
284
285 double CompositeParticle_v1::pt( const std::vector<int>& partIndices ) const {
286 return (this->p4(partIndices)).Pt();
287 }
288
289 double CompositeParticle_v1::eta( const std::vector<int>& partIndices ) const {
290 return (this->p4(partIndices)).Eta();
291 }
292
293 double CompositeParticle_v1::phi( const std::vector<int>& partIndices ) const {
294 return (this->p4(partIndices)).Phi();
295 }
296
297 double CompositeParticle_v1::m( const std::vector<int>& partIndices ) const {
298 return (this->p4(partIndices)).M();
299 }
300
301 double CompositeParticle_v1::p( const std::vector<int>& partIndices ) const {
302 return (this->p4(partIndices)).P();
303 }
304
305 double CompositeParticle_v1::e( const std::vector<int>& partIndices ) const {
306 return (this->p4(partIndices)).E();
307 }
308
309 double CompositeParticle_v1::rapidity( const std::vector<int>& partIndices ) const {
310 return (this->p4(partIndices)).Rapidity();
311 }
312
313 double CompositeParticle_v1::px( const std::vector<int>& partIndices ) const {
314 return (this->p4(partIndices)).Px();
315 }
316
317 double CompositeParticle_v1::py( const std::vector<int>& partIndices ) const {
318 return (this->p4(partIndices)).Py();
319 }
320
321 double CompositeParticle_v1::pz( const std::vector<int>& partIndices ) const {
322 return (this->p4(partIndices)).Pz();
323 }
324
325 double CompositeParticle_v1::et( const std::vector<int>& partIndices ) const{
326 return (this->p4(partIndices)).Et();
327 }
328
329
330
331 // Get the transverse mass.
332 // Specify which calculation method to use as an optional additional argument.
333 double CompositeParticle_v1::mt( const std::vector<int>& partIndices, MT::Method method ) const
334 {
335 // Use the different calculation methods, depending on the given input
337 // Calculate m_T according to the ATLAS Higgs->WW publication
338 // from 2014/2015 (http://arxiv.org/pdf/1412.2641v1.pdf, page 3)
339
340 // Get all the visible constituents and sum up their 4-momenta.
341 // If the user provides as one of these indices a -1, then missingET will
342 // also be used... THIS WILL GIVE WRONG RESULTS!
343 xAOD::CompositeParticle_v1::FourMom_t fourMom( this->p4(partIndices) );
344
345 // Get the missing e_T
346 const xAOD::MissingET* metObj = this->missingET();
347 if ( !metObj ) {
348 // This should not be... throw an error.
349 throw std::runtime_error("Got a zero pointer to an xAOD::MissingET when calling mt");
350 }
351 const double mpx( metObj->mpx() );
352 const double mpy( metObj->mpy() );
353 const double met( metObj->met() );
354
355 // Now, actually calculate the result (in two parts)
356 const double px( fourMom.Px() );
357 const double py( fourMom.Py() );
358 const double part2 = (px+mpx)*(px+mpx) + (py+mpy)*(py+mpy);
359
360 double mll2( fourMom.M2() );
361 // This is needed for rare cases when the TLorentzVector.M2 returns negative values
362 mll2 = mll2 < 0.0 ? -mll2 : mll2;
363 const double etll( std::sqrt( (px*px + py*py) + mll2 ) );
364 const double part1( (etll+met)*(etll+met) );
365
366 // One last sanity check
367 if ( part1 < part2 ) {
368 // This should not be... throw an error.
369 throw std::runtime_error("Got an invalid mt calculation");
370 }
371 return std::sqrt( part1 - part2 );
372 }
373
374 return 0.0;
375 }
376
377
378
379
380 // End: Functions returning variables that are calculated from 4-momentum
381 // information from constituents.
383
384
385
386
388 // Begin: Functions returning variables that are calculated from
389 // information from constituents (not only using their 4-momenta).
390
391 float CompositeParticle_v1::weight( const std::vector<std::string>& varNames,
392 const std::vector<int>& partIndices ) const {
393 // Default return value
394 float weight(1.0);
395 // Iterate over each variable name
396 for ( const std::string& varName : varNames ) {
397 // Protect against empty strings
398 if ( varName.empty() ) { continue; }
399 const xAOD::IParticle::ConstAccessor<float> varAcc(varName);
400 // If the given vector of indices is an empty vector, run over all particles
401 if ( partIndices.empty() ) {
402 weight *= this->weightHelper( this, varAcc );
403 }
404 else {
405 // If we have specific indices given, we will only look there
406 for ( int i : partIndices ) {
407 if ( i == -1 ) {
408 const xAOD::MissingET* met = this->missingET();
409 if ( met && varAcc.isAvailable(*met) ) { weight *= varAcc(*met); }
410 continue;
411 }
412 else if ( i < 0 ) {
413 throw std::runtime_error("Got a negative index which is not -1");
414 }
415 else {
416 const xAOD::IParticle* part = this->part(i);
417 weight *= this->weightHelper( part, varAcc );
418 }
419 }
420 } // End: if/else partIndices.empty()
421 } // End: Loop over variable names
422 return weight;
423 }
424
425
426
427 // This is a private helper method
428 float CompositeParticle_v1::weightHelper( const xAOD::IParticle* part,
429 const xAOD::IParticle::ConstAccessor<float>& varAcc ) const {
430 if (!part) {
431 throw std::runtime_error("Got a zero pointer to an xAOD::IParticle!");
432 }
433 if ( varAcc.isAvailable(*part) ) {
434 return varAcc(*part);
435 }
436 if ( part->type() != xAOD::Type::CompositeParticle ) {
437 // We didn't find the weight variable for this particle and we cannot
438 // iterate further down into the constituent tree (as it ends here).
439 return 1.0;
440 }
441 // We have a CompositeParticle, but it doesn't have its own weight variable
442 // of the given name. Thus, we search in all of its constituents for the weight.
443 const xAOD::CompositeParticle_v1* compPart = static_cast<const xAOD::CompositeParticle_v1*>(part);
444 float weight(1.0);
445 std::size_t nParts = compPart->nParts();
446 for ( std::size_t i=0; i<nParts; ++i ) {
447 const xAOD::IParticle* part2 = compPart->part(i);
448 weight *= this->weightHelper( part2, varAcc );
449 }
450 const xAOD::MissingET* met = compPart->missingET();
451 if ( met && varAcc.isAvailable(*met) ) { weight *= varAcc(*met); }
452 return weight;
453 }
454
455
456 // End: Functions returning variables that are calculated from
457 // information from constituents (not only using their 4-momenta).
459
461 //
462 // Functions implementing handling of constituents
463 //
464
465 // Get the accessor for the vector of element links to the constituents
467 partLinksAcc( "partLinks" );
468
469
470
471 void
472 CompositeParticle_v1::addPart( const xAOD::IParticle* part, bool updateFourMom ) {
473 // Check if we have a valid pointer
474 if ( !part ) {
475 // This should not be... throw an error.
476 throw std::runtime_error("Got a zero pointer to an xAOD::IParticle when adding constituent!");
477 return;
478 }
479 xAOD::IParticleLinkContainer& constitLinks = partLinksAcc( *this );
480
481 // Update the four-momentum of this composite particle, if requested
482 if ( updateFourMom ) {
483 this->setP4( this->p4() + part->p4() );
484 // Cannot add charge automatically as this is NOT part of the xAOD::IParticle interface
485 //this->setCharge( this->charge() + (*partLink)->charge() );
486 }
487
488 // Add the given ElementLink as a constituent of this composite particle
489 const std::size_t partIdx = part->index();
490 const xAOD::IParticleContainer* partCont =
491 static_cast<const xAOD::IParticleContainer*>(part->container());
492 constitLinks.push_back( IParticleLink( *partCont, partIdx ) );
493 return;
494 }
495
496
497
498 void
500 // Check if we have a valid ElementLink
501 if ( ! partLink.isValid() ) {
502 // This should not be... throw an error.
503 throw std::runtime_error("Got an invalid ElementLink when adding constituent!");
504 }
505 xAOD::IParticleLinkContainer& constitLinks = partLinksAcc( *this );
506
507 // Update the four-momentum of this composite particle, if requested
508 if ( updateFourMom ) {
509 this->setP4( this->p4() + (*partLink)->p4() );
510 // Cannot add charge automatically as this is NOT part of the xAOD::IParticle interface
511 //this->setCharge( this->charge() + (*partLink)->charge() );
512 }
513
514 // Add the given ElementLink as a constituent of this composite particle
515 constitLinks.push_back( partLink );
516 return;
517 }
518
519
520 void
522 bool updateFourMom ) {
523 for ( xAOD::IParticleLinkContainer::const_iterator
524 constitItr = partLinkCont.begin(),
525 constitItrEnd = partLinkCont.end();
526 constitItr != constitItrEnd;
527 ++constitItr ) {
528 const xAOD::IParticleLink& currentLink = *constitItr;
529 this->addPart( currentLink, updateFourMom );
530 }
531 return;
532 }
533
534
535
537 bool updateFourMom ) {
538 // Check if we have a valid pointer
539 if ( !part ) {
540 // This should not be... throw an error.
541 throw std::runtime_error("Got a zero pointer to an xAOD::IParticle when adding constituent!");
542 }
543
544 // Add the ElementLink of the given particle and pass it on
545 const std::size_t partIdx = part->index();
546 const xAOD::IParticleContainer* partCont =
547 static_cast<const xAOD::IParticleContainer*>(part->container());
548 this->removePart( IParticleLink( *partCont, partIdx ), updateFourMom );
549 return;
550 }
551
552
553
554 void
556 bool updateFourMom ) {
557 // Check if we have a valid ElementLink
558 if ( ! partLink.isValid() ) {
559 // This should not be... throw an error.
560 throw std::runtime_error("Got an invalid ElementLink when adding constituent!");
561 }
562 xAOD::IParticleLinkContainer& constitLinks = partLinksAcc( *this );
563
564 // Find the constituent particle that should be removed
565 for ( xAOD::IParticleLinkContainer::iterator
566 constitItr = constitLinks.begin(),
567 constitItrEnd = constitLinks.end();
568 constitItr != constitItrEnd;
569 ++constitItr ) {
570 const xAOD::IParticleLink& currentLink = *constitItr;
571 if ( partLink == currentLink ) {
572 // Update the four-momentum of this composite particle, if requested
573 if ( updateFourMom ) {
574 this->setP4( this->p4() - (*partLink)->p4() );
575 // Cannot add charge automatically as this is NOT part of the xAOD::IParticle interface
576 //this->setCharge( this->charge() - (*partLink)->charge() );
577 }
578
579 // Remove the found link
580 constitLinks.erase( constitItr );
581 return;
582 }
583 }
584 return;
585 }
586
587 // Get the accessor for the element link to the MissingET object
589 metLinkAcc( "missingETLink" );
590
591
592 const xAOD::MissingET*
594 if ( !(metLinkAcc.isAvailable(*this)) ) {
595 return nullptr;
596 }
598 // Check if we have a valid ElementLink
599 if ( ! metLink.isValid() ) {
600 return nullptr;
601 }
602 return *metLink;
603 }
604
605
606
607 void
609 bool updateFourMom ) {
610 // Check if we have a valid pointer
611 if ( !met ) {
612 // This should not be... throw an error.
613 throw std::runtime_error("Got a zero pointer to xAOD::MissingET when adding it!");
614 }
615
616 // Update the four-momentum of this composite particle, if requested
617 if ( updateFourMom ) {
619 double metpx = met->mpx();
620 double metpy = met->mpy();
621 metP4.SetPxPyPzE( metpx, metpy, 0.0, std::sqrt(metpx*metpx + metpy*metpy) );
622 this->setP4( this->p4() + metP4 );
623 }
624
625 // Add the given ElementLink as a constituent of this composite particle
626 const std::size_t metIdx = met->index();
627 const xAOD::MissingETContainer* metCont =
628 static_cast<const xAOD::MissingETContainer*>(met->container());
629 metLinkAcc(*this) = ElementLink<xAOD::MissingETContainer>( *metCont, metIdx );
630 return;
631 }
632
633
634
635 void
637 const xAOD::MissingET* met = this->missingET();
638 if ( !met ) {
639 // There is no valid MissingET object assigned... nothing can done
640 return;
641 }
642
643 // Update the four-momentum of this composite particle, if requested
644 if ( updateFourMom ) {
646 double metpx = met->mpx();
647 double metpy = met->mpy();
648 metP4.SetPxPyPzE( metpx, metpy, 0.0, std::sqrt(metpx*metpx + metpy*metpy) );
649 this->setP4( this->p4() - metP4 );
650 }
651 // Assign an invalid ElementLink here
653 return;
654 }
655
656
657
658
659 bool
662 // Check if we have a valid ElementLink. If not, return false. This is
663 // because the given met that we check against obviously exists, meaning
664 // that if it would be the same, the ElementLink should have been valid.
665 if ( ! metLink.isValid() ) {
666 return false;
667 }
668 const xAOD::MissingET* thisMet = *metLink;
669
670 // Check if the pointers are equal
671 if ( thisMet == met ) {
672 return true;
673 }
674
675 // Use the MissingET == operator
676 if ( (*thisMet) == (*met) ) {
677 return true;
678 }
679
680 // Otherwise, return false
681 return false;
682 }
683
684
685
686 bool
688 const xAOD::IParticleLinkContainer& constitLinks = this->partLinks();
689 for ( xAOD::IParticleLinkContainer::const_iterator
690 constitItr = constitLinks.begin(),
691 constitItrEnd = constitLinks.end();
692 constitItr != constitItrEnd;
693 ++constitItr ) {
694 const xAOD::IParticleLink& currentLink = *constitItr;
695 if ( ! currentLink.isValid() ) continue;
696 const xAOD::IParticle* currentPart = *currentLink;
697 if ( part == currentPart ) {
698 return true;
699 }
700 }
701 return false;
702 }
703
704
705 bool
707 const xAOD::IParticleLinkContainer& constitLinks = this->partLinks();
708 for ( xAOD::IParticleLinkContainer::const_iterator
709 constitItr = constitLinks.begin(),
710 constitItrEnd = constitLinks.end();
711 constitItr != constitItrEnd;
712 ++constitItr ) {
713 const xAOD::IParticleLink& currentLink = *constitItr;
714 if ( partLink == currentLink ) {
715 return true;
716 }
717 }
718 return false;
719 }
720
721
722 std::size_t CompositeParticle_v1::nParts() const {
723 if( partLinksAcc.isAvailable( *this ) ) {
724 return partLinksAcc( *this ).size();
725 }
726 return 0;
727 }
728
729
730
731// Define a pre-processor macro for the implementations of all these methods
732#define NUM_PARTS( FUNCNAME, OBJTYPE ) \
733 std::size_t CompositeParticle_v1::FUNCNAME() const { \
734 std::size_t n(0); \
735 std::size_t nParts = this->nParts(); \
736 for ( std::size_t i=0; i<nParts; ++i ) { \
737 const xAOD::IParticle* part = this->part(i); \
738 if (!part) { throw std::runtime_error("Got a zero pointer to an xAOD::IParticle!"); } \
739 if ( part->type() == xAOD::Type::OBJTYPE ) { n += 1; } \
740 } \
741 return n; \
742 }
743
744 NUM_PARTS(nCompParts,CompositeParticle)
745 NUM_PARTS(nPhotons,Photon)
746 NUM_PARTS(nElectrons,Electron)
747 NUM_PARTS(nMuons,Muon)
748 NUM_PARTS(nTaus,Tau)
749
751 return this->nElectrons() + this->nMuons() + this->nTaus();
752 }
753
754 NUM_PARTS(nJets,Jet)
755 NUM_PARTS(nTruthParts,TruthParticle)
756
757#define NUM_TRUTHPARTS( FUNCNAME, PIDMETHOD ) \
758 std::size_t CompositeParticle_v1::FUNCNAME() const { \
759 std::size_t n(0); \
760 std::size_t nParts = this->nParts(); \
761 for ( std::size_t i=0; i<nParts; ++i ) { \
762 const xAOD::IParticle* part = this->part(i); \
763 if (!part) { throw std::runtime_error("Got a zero pointer to an xAOD::IParticle!"); } \
764 if ( part->type() != xAOD::Type::TruthParticle ) { continue; } \
765 const xAOD::TruthParticle* truthParticle = dynamic_cast<const xAOD::TruthParticle*>(part); \
766 if (!truthParticle) { throw std::runtime_error("Zero pointer to xAOD::TruthParticle"); } \
767 if ( PIDMETHOD(truthParticle->pdgId()) ) { n += 1; } \
768 } \
769 return n; \
770 }
771
772 NUM_TRUTHPARTS(nTruthPhotons,MC::isPhoton)
773 NUM_TRUTHPARTS(nTruthElectrons,MC::isElectron)
774 NUM_TRUTHPARTS(nTruthMuons,MC::isMuon)
775 NUM_TRUTHPARTS(nTruthTaus,MC::isTau)
776
778 return this->nTruthElectrons() + this->nTruthMuons() + this->nTruthTaus();
779 }
780
781 const xAOD::IParticle*
782 CompositeParticle_v1::part( std::size_t index ) const {
783 if ( index >= this->nParts() ) {
784 return nullptr;
785 }
786 const xAOD::IParticleLink & constitLink = partLink( index );
787 if ( ! constitLink.isValid() ) {
788 return nullptr;
789 }
790 return *constitLink;
791 }
792
793
796 if ( index >= this->nParts() ) {
797 static const xAOD::IParticleLink dummy;
798 return dummy;
799 }
800 return partLinks()[ index ];
801 }
802
803
804
807 partLinks,
808 setPartLinks )
809
810
811 template<typename CONTTYPE>
813 // Create the return object
815
816 std::size_t nParts = this->nParts();
817 for ( std::size_t i=0; i<nParts; ++i ) {
818 const xAOD::IParticle* part = this->part(i);
819 if (!part) {
820 delete outCont;
821 throw std::runtime_error("Got a zero pointer to an xAOD::IParticle!");
822 }
824 = dynamic_cast<typename ConstDataVector<CONTTYPE>::const_pointer>(part);
825 if (typePart) {
826 outCont->push_back(typePart);
827 }
828 }
829 return outCont;
830 }
831
832
833
834 xAOD::CompositeParticle_v1*
835 CompositeParticle_v1::compPart( const std::vector<int>& partIndices,
836 const std::vector<int>& otherPartIndices,
837 bool updateFourMom ) const {
838 xAOD::CompositeParticle_v1* compPart = new CompositeParticle_v1();
839 compPart->makePrivateStore();
840 for ( int i : partIndices ) {
841 if ( i == -1 ) {
842 compPart->setMissingET( this->missingET(), updateFourMom );
843 }
844 else if ( i >= 0 ) {
845 const xAOD::IParticleLink& pLink = this->partLink( static_cast<std::size_t>(i) );
846 compPart->addPart( pLink, updateFourMom );
847 }
848 else {
849 throw std::runtime_error("Got a non-valid index");
850 }
851 }
852 for ( int i : otherPartIndices ) {
853 if ( i >= 0 ) {
854 const xAOD::IParticleLink& pLink = this->otherPartLink( static_cast<std::size_t>(i) );
855 compPart->addPart( pLink, updateFourMom );
856 }
857 else {
858 throw std::runtime_error("Got a non-valid index for an other particle");
859 }
860 }
861 return compPart;
862 }
863
864
865
866
867 // End: Functions implementing handling of constituents
869
871 //
872 // Functions implementing handling of other constituents
873 //
874
875 // Get the accessor for the vector of element links to the other constituents
877 otherPartLinksAcc( "otherPartLinks" );
878
879
880
881 void
882 CompositeParticle_v1::addOtherPart( const xAOD::IParticle* part ) {
883 // Check if we have a valid pointer
884 if ( !part ) {
885 // This should not be... throw an error.
886 throw std::runtime_error("Got a zero pointer to an xAOD::IParticle when adding constituent!");
887 }
888 xAOD::IParticleLinkContainer& otherPartLinks = otherPartLinksAcc( *this );
889
890 // Add the given ElementLink as a constituent of this composite particle
891 const std::size_t partIdx = part->index();
892 const xAOD::IParticleContainer* partCont =
893 static_cast<const xAOD::IParticleContainer*>(part->container());
894 otherPartLinks.push_back( IParticleLink( *partCont, partIdx ) );
895 return;
896 }
897
898
899
900 void
902 // Check if we have a valid ElementLink
903 if ( ! partLink.isValid() ) {
904 // This should not be... throw an error.
905 throw std::runtime_error("Got an invalid ElementLink when adding constituent!");
906 }
907 xAOD::IParticleLinkContainer& otherPartLinks = otherPartLinksAcc( *this );
908
909 // Add the given ElementLink as a constituent of this composite particle
910 otherPartLinks.push_back( partLink );
911 return;
912 }
913
914
915 void
917 for ( xAOD::IParticleLinkContainer::const_iterator
918 constitItr = partLinkCont.begin(),
919 constitItrEnd = partLinkCont.end();
920 constitItr != constitItrEnd;
921 ++constitItr ) {
922 const xAOD::IParticleLink& currentLink = *constitItr;
923 this->addOtherPart( currentLink );
924 }
925 return;
926 }
927
928
929
931 // Check if we have a valid pointer
932 if ( !part ) {
933 // This should not be... throw an error.
934 throw std::runtime_error("Got a zero pointer to an xAOD::IParticle when adding constituent!");
935 }
936
937 // Add the ElementLink of the given particle and pass it on
938 const std::size_t partIdx = part->index();
939 const xAOD::IParticleContainer* partCont =
940 static_cast<const xAOD::IParticleContainer*>(part->container());
941 this->removeOtherPart( IParticleLink( *partCont, partIdx ) );
942 return;
943 }
944
945
946
947 void
949 // Check if we have a valid ElementLink
950 if ( ! partLink.isValid() ) {
951 // This should not be... throw an error.
952 throw std::runtime_error("Got an invalid ElementLink when adding constituent!");
953 }
954 xAOD::IParticleLinkContainer& otherPartLinks = otherPartLinksAcc( *this );
955
956 // Find the constituent particle that should be removed
957 for ( xAOD::IParticleLinkContainer::iterator
958 constitItr = otherPartLinks.begin(),
959 constitItrEnd = otherPartLinks.end();
960 constitItr != constitItrEnd;
961 ++constitItr ) {
962 const xAOD::IParticleLink& currentLink = *constitItr;
963 if ( partLink == currentLink ) {
964 // Remove the found link
965 otherPartLinks.erase( constitItr );
966 return;
967 }
968 }
969 return;
970 }
971
972
973
974 bool
977 for ( xAOD::IParticleLinkContainer::const_iterator
978 constitItr = otherPartLinks.begin(),
979 constitItrEnd = otherPartLinks.end();
980 constitItr != constitItrEnd;
981 ++constitItr ) {
982 const xAOD::IParticleLink& currentLink = *constitItr;
983 if ( ! currentLink.isValid() ) continue;
984 const xAOD::IParticle* currentPart = *currentLink;
985 if ( part == currentPart ) {
986 return true;
987 }
988 }
989 return false;
990 }
991
992
993 bool
996 for ( xAOD::IParticleLinkContainer::const_iterator
997 constitItr = otherPartLinks.begin(),
998 constitItrEnd = otherPartLinks.end();
999 constitItr != constitItrEnd;
1000 ++constitItr ) {
1001 const xAOD::IParticleLink& currentLink = *constitItr;
1002 if ( partLink == currentLink ) {
1003 return true;
1004 }
1005 }
1006 return false;
1007 }
1008
1009
1011 if( otherPartLinksAcc.isAvailable( *this ) ) {
1012 return otherPartLinksAcc( *this ).size();
1013 }
1014 return 0;
1015 }
1016
1017
1018
1019// Define a pre-processor macro for the implementations of all these methods
1020#define NUM_OTHERPARTS( FUNCNAME, OBJTYPE ) \
1021 std::size_t CompositeParticle_v1::FUNCNAME() const { \
1022 std::size_t n(0); \
1023 std::size_t nParts = this->nOtherParts(); \
1024 for ( std::size_t i=0; i<nParts; ++i ) { \
1025 const xAOD::IParticle* part = this->otherPart(i); \
1026 if (!part) { throw std::runtime_error("Got a zero pointer to an xAOD::IParticle!"); } \
1027 if ( part->type() == xAOD::Type::OBJTYPE ) { n += 1; } \
1028 } \
1029 return n; \
1030 }
1031
1032 NUM_OTHERPARTS(nOtherCompParts,CompositeParticle)
1033 NUM_OTHERPARTS(nOtherPhotons,Photon)
1034 NUM_OTHERPARTS(nOtherElectrons,Electron)
1035 NUM_OTHERPARTS(nOtherMuons,Muon)
1036 NUM_OTHERPARTS(nOtherTaus,Tau)
1037
1039 return this->nOtherElectrons() + this->nOtherMuons() + this->nOtherTaus();
1040 }
1041
1042 NUM_OTHERPARTS(nOtherJets,Jet)
1043 NUM_OTHERPARTS(nOtherTruthParts,TruthParticle)
1044
1045#define NUM_OTHERTRUTHPARTS( FUNCNAME, PIDMETHOD ) \
1046 std::size_t CompositeParticle_v1::FUNCNAME() const { \
1047 std::size_t n(0); \
1048 std::size_t nParts = this->nOtherParts(); \
1049 for ( std::size_t i=0; i<nParts; ++i ) { \
1050 const xAOD::IParticle* part = this->otherPart(i); \
1051 if (!part) { throw std::runtime_error("Got a zero pointer to an xAOD::IParticle!"); } \
1052 if ( part->type() != xAOD::Type::TruthParticle ) { continue; } \
1053 const xAOD::TruthParticle* truthParticle = dynamic_cast<const xAOD::TruthParticle*>(part); \
1054 if (!truthParticle) { throw std::runtime_error("Zero pointer to xAOD::TruthParticle"); } \
1055 if ( PIDMETHOD(truthParticle->pdgId()) ) { n += 1; } \
1056 } \
1057 return n; \
1058 }
1059
1060 NUM_OTHERTRUTHPARTS(nOtherTruthPhotons,MC::isPhoton)
1061 NUM_OTHERTRUTHPARTS(nOtherTruthElectrons,MC::isElectron)
1062 NUM_OTHERTRUTHPARTS(nOtherTruthMuons,MC::isMuon)
1063 NUM_OTHERTRUTHPARTS(nOtherTruthTaus,MC::isTau)
1064
1066 return this->nOtherTruthElectrons() + this->nOtherTruthMuons() + this->nOtherTruthTaus();
1067 }
1068
1069
1070 const xAOD::IParticle*
1072 if ( index >= this->nOtherParts() ) {
1073 return nullptr;
1074 }
1075 const xAOD::IParticleLink & otherPartLink = this->otherPartLink( index );
1076 if ( ! otherPartLink.isValid() ) {
1077 return nullptr;
1078 }
1079 return *otherPartLink;
1080 }
1081
1082
1083 const xAOD::IParticleLink&
1085 if ( index >= this->nOtherParts() ) {
1086 static const xAOD::IParticleLink dummy;
1087 return dummy;
1088 }
1089 return otherPartLinks()[ index ];
1090 }
1091
1092
1093
1096 otherPartLinks,
1097 setOtherPartLinks )
1098
1099 // End: Functions implementing handling of other constituents
1101
1103 if( partLinksAcc.isAvailableWritable( *this ) ) {
1104 for ( xAOD::IParticleLinkContainer::iterator
1105 itr = partLinksAcc( *this ).begin(),
1106 itrEnd = partLinksAcc( *this ).end();
1107 itr != itrEnd;
1108 ++itr ) {
1109 itr->toPersistent();
1110 }
1111 }
1112 return;
1113 }
1114
1115
1116} // namespace xAOD
#define AUXSTORE_PRIMITIVE_SETTER_WITH_CAST(CL, PERSTYPE, TRANSTYPE, NAME, SETTER)
Macro creating a setter function with a type conversion.
#define AUXSTORE_PRIMITIVE_SETTER_AND_GETTER(CL, TYPE, NAME, SETTER)
Macro creating the accessors of primitive auxiliary properties.
#define AUXSTORE_OBJECT_SETTER_AND_GETTER(CL, TYPE, NAME, SETTER)
Macro creating the accessors of complex auxiliary properties.
std::vector< size_t > vec
#define NUM_PARTS(FUNCNAME, OBJTYPE)
#define NUM_TRUTHPARTS(FUNCNAME, PIDMETHOD)
#define NUM_OTHERTRUTHPARTS(FUNCNAME, PIDMETHOD)
#define NUM_OTHERPARTS(FUNCNAME, OBJTYPE)
ATLAS-specific HepMC functions.
class which is made from the composition of other particles.
DataVector adapter that acts like it holds const pointers.
value_type push_back(value_type pElem)
Add an element to the end of the collection.
DV::const_value_type const * const_pointer
SG::Accessor< T, ALLOC > Accessor
Definition AuxElement.h:572
bool isAvailable(const ELT &e) const
Test to see if this variable exists in the store.
Description of a composite particle, i.e.
bool containsOther(const xAOD::IParticle *part) const
Check if a given xAOD::IParticle is an other constituent.
bool hasPdgId() const
Check if this composite particle has its charge set.
std::size_t nOtherLeptons() const
Number of other constituent leptons (electrons, muons, and taus).
virtual double phi() const
The azimuthal angle ( ) of the particle.
double pz() const
Get the pz momentum component of the particle.
const xAOD::IParticle * part(std::size_t index=0) const
Get the constituent IParticle number i.
std::size_t nOtherMuons() const
Number of other constituent muons.
std::size_t nOtherTruthTaus() const
Number of other constituent truth taus.
std::size_t nElectrons() const
Number of constituent electrons.
const xAOD::IParticleLinkContainer & partLinks() const
Get all constituents in one go.
std::size_t nOtherTruthMuons() const
Number of other constituent truth muons.
const xAOD::IParticleLink & partLink(std::size_t index=0) const
Get the constituent IParticle number i as an ElementLink.
virtual FourMom_t p4() const
The full 4-momentum of the particle.
std::size_t nOtherElectrons() const
Number of other constituent electrons.
bool hasCharge() const
Check if this composite particle has its charge set.
double py() const
Get the py momentum component of the particle.
void removeOtherPart(const xAOD::IParticle *part)
Remove a particle as an other constituent from this CompostiteParticle.
double p(const std::vector< int > &partIndices) const
The total 3-momentum.
void setPxPyPzE(double px, double py, double pz, double e)
Set the 4-vec.
CompositeParticle_v1()
Default constructor.
std::size_t nMuons() const
Number of constituent muons.
void addOtherPart(const xAOD::IParticle *part)
Add a particle as an additional other constituent.
std::size_t nOtherTaus() const
Number of other constituent taus.
double et() const
The transverse energy ( ) of the particle.
IParticle::FourMom_t FourMom_t
Definition of the 4-momentum type.
virtual Type::ObjectType type() const
The type of the object as a simple enumeration.
double px() const
Get the px momentum component of the particle.
const xAOD::IParticle * otherPart(std::size_t index=0) const
Get the other constituent IParticle number i.
float weight(const std::vector< std::string > &varNames, const std::vector< int > &partIndices={}) const
Get the weight for this xAOD::CompositeParticle by providing a vector of variable names that will be ...
virtual double e() const
The total energy of the particle.
void setCharge(float charge)
Set the electric charge.
const xAOD::MissingET * missingET() const
Get the MissingET object that is associated with this CompositeParticle.
void addPart(const xAOD::IParticle *part, bool updateFourMom=true)
Add a particle as an additional constituent.
std::size_t nTruthElectrons() const
Number of constituent truth electrons.
double mt(const std::vector< int > &partIndices, MT::Method method=MT::DEFAULT) const
Get the transverse mass.
std::size_t nParts() const
Number of constituent particles.
std::size_t nTruthLeptons() const
Number of constituent truth leptons (truth electrons, truth muons, and truth taus).
std::size_t nLeptons() const
Number of constituent leptons (electrons, muons, and taus).
void addOtherParts(const xAOD::IParticleLinkContainer &partLinkCont)
Add many other constituents at the same time.
float charge() const
Return the electric charge.
void toPersistent()
Function preparing the object to be persistified.
std::size_t nOtherParts() const
Number of other constituent particles.
std::size_t nOtherTruthElectrons() const
Number of other constituent truth electrons.
bool contains(const xAOD::MissingET *met) const
Check if a given xAOD::MissingET object is part of this CompositeParticle.
void removeMissingET(bool updateFourMom=true)
Remove the existing MissingET object from this CompositeParticle.
void setP4(const FourMom_t &vec)
Set the 4-vec.
const xAOD::IParticleLinkContainer & otherPartLinks() const
Get all other constituents in one go.
xAOD::CompositeParticle_v1 * compPart(const std::vector< int > &partIndices, const std::vector< int > &otherPartIndices=std::vector< int >{}, bool updateFourMom=true) const
Get a CompositeParticle that is build on the fly from the constituent particles associated to the ind...
std::size_t nOtherTruthLeptons() const
Number of other constituent truth leptons (truth electrons, truth muons, and truth taus).
std::size_t nTruthTaus() const
Number of constituent truth taus.
ConstDataVector< CONTTYPE > * parts() const
Method to return a DataVector<T>, e.g., a MuonContainer, for all the constituent particles,...
float weightHelper(const xAOD::IParticle *part, const xAOD::IParticle::ConstAccessor< float > &varAcc) const
This is a private helper method to calculate the weight.
const xAOD::IParticleLink & otherPartLink(std::size_t index=0) const
Get the other constituent IParticle number i as an ElementLink.
ROOT::Math::LorentzVector< ROOT::Math::PxPyPzE4D< double > > GenVecFourMom_t
Base 4 Momentum type (GenVector)
void removePart(const xAOD::IParticle *part, bool updateFourMom=true)
Remove a particle as a constituent from this CompostiteParticle.
virtual double eta() const
The pseudorapidity ( ) of the particle.
GenVecFourMom_t genvecP4() const
The full 4-momentum of the particle : GenVector form Note: can be slower than just p4 for this class;...
virtual double rapidity() const
The true rapidity (y) of the particle.
std::size_t nTruthMuons() const
Number of constituent truth muons.
void setMissingET(const xAOD::MissingET *met, bool updateFourMom=true)
Set the MissingET for this CompositeParticle.
virtual double m() const
The invariant mass of the particle.
virtual double pt() const
The transverse momentum ( ) of the particle.
void addParts(const xAOD::IParticleLinkContainer &partLinkCont, bool updateFourMom=true)
Add many constituents at the same time Note that the 4-momentum of this CompositeParticle will be upd...
std::size_t nTaus() const
Number of constituent taus.
Class describing an electron.
Class providing the definition of the 4-vector interface.
IParticle()=default
virtual FourMom_t p4() const =0
The full 4-momentum of the particle.
TLorentzVector FourMom_t
Definition of the 4-momentum type.
SG::Accessor< T, ALLOC > Accessor
Definition AuxElement.h:572
float met() const
Returns .
float mpx() const
Returns .
float mpy() const
Returns .
Class describing an photon.
bool isPhoton(const T &p)
bool isElectron(const T &p)
bool isMuon(const T &p)
bool isTau(const T &p)
NRpcCablingAlg reads raw condition data and writes derived condition data to the condition store.
str varName
end cluster ToT and charge
@ VIEW_ELEMENTS
this data object is a view, it does not own its elmts
Definition index.py:1
STL namespace.
@ CompositeParticle
Particle composed of other particles.
Definition ObjectType.h:95
ICaloAffectedTool is abstract interface for tools checking if 4 mom is in calo affected region.
Jet_v1 Jet
Definition of the current "jet version".
static const SG::AuxElement::Accessor< float > accPx("px")
AUXSTORE_PRIMITIVE_SETTER_WITH_CAST(CompositeParticle_v1, float, double, px, setPx) AUXSTORE_PRIMITIVE_SETTER_WITH_CAST(CompositeParticle_v1
static const SG::AuxElement::Accessor< float > accPy("py")
MissingET_v1 MissingET
Version control by type defintion.
static const SG::AuxElement::Accessor< int > pdgAcc("pdgId")
static const SG::AuxElement::Accessor< float > accPz("pz")
IParticleLinkContainer_v1 IParticleLinkContainer
Define the latest version of the IParticleLinkContainer class.
static const SG::AuxElement::Accessor< float > accE("e")
IParticleLink_v1 IParticleLink
Define the latest version of the IParticleLink class.
static const SG::AuxElement::Accessor< float > chargeAcc("charge")
TruthParticle_v1 TruthParticle
Typedef to implementation.
static const SG::AuxElement::Accessor< ElementLink< xAOD::MissingETContainer > > metLinkAcc("missingETLink")
DataVector< IParticle > IParticleContainer
Simple convenience declaration of IParticleContainer.