@@ -29,11 +29,12 @@ class BasePairCleaner
2929 virtual ~BasePairCleaner () = default ;
3030
3131 template <modes::Mode mode, typename T>
32- void init (T const & pairCuts )
32+ void init (T const & PairCuts )
3333 {
3434 if constexpr (modes::isFlagSet (mode, modes::Mode::kMc )) {
35- mMixPairsWithCommonAncestor = pairCuts.mixOnlyCommonAncestor .value ;
36- mMixPairsWithNonCommonAncestor = pairCuts.mixOnlyNonCommonAncestor .value ;
35+ mMixPairsWithCommonAncestor = PairCuts.mixOnlyCommonAncestor .value ;
36+ mMixPairsWithNonCommonAncestor = PairCuts.mixOnlyNonCommonAncestor .value ;
37+ mUseMotherAsAncestor = PairCuts.useMotherAsAncestor .value ;
3738 if (mMixPairsWithCommonAncestor && mMixPairsWithNonCommonAncestor ) {
3839 LOG (fatal) << " Both mixing with common and non-common ancestor is activated. Breaking..." ;
3940 }
@@ -48,34 +49,31 @@ class BasePairCleaner
4849 };
4950
5051 // mc only
52+ // ancestry is checked either with the partonic mother or with the last ancestor (i.e. the direct mother), depending on mUseMotherAsAncestor
5153 template <typename T1 , typename T2 , typename T3 >
52- bool mcPairHasCommonAncestor (T1 const & particle1, T2 const & particle2, T3 const & /* partonicMothers*/ ) const
54+ bool mcPairHasCommonAncestor (T1 const & particle1, T2 const & particle2, T3 const & partonicMothers) const
5355 {
54- // if one of the two particles has no associated partonic mother, we cannot know if they have a common anchestor, so we break out with false
55- if (!particle1.has_fMcPartMoth () || !particle2.has_fMcPartMoth ()) {
56- return false ;
56+ if (mUseMotherAsAncestor ) {
57+ return this ->mcPairHasCommonMother (particle1, particle2);
5758 }
58-
59- // get partonic mothers
60- auto partonicMother1 = particle1.template fMcPartMoth_as <T3 >();
61- auto partonicMother2 = particle2.template fMcPartMoth_as <T3 >();
62-
63- return partonicMother1.globalIndex () == partonicMother2.globalIndex ();
59+ return this ->mcPairHasCommonPartonicMother (particle1, particle2, partonicMothers);
6460 };
6561
6662 template <typename T1 , typename T2 , typename T3 >
67- bool mcPairHasNonCommonAncestor (T1 const & particle1, T2 const & particle2, T3 const & /* partonicMothers*/ ) const
63+ bool mcPairHasNonCommonAncestor (T1 const & particle1, T2 const & particle2, T3 const & partonicMothers) const
6864 {
65+ if (mUseMotherAsAncestor ) {
66+ // if one of the two particles has no associated mother, we cannot know if they have a common anchestor, so we break out with false
67+ if (!particle1.has_fMcMother () || !particle2.has_fMcMother ()) {
68+ return false ;
69+ }
70+ return !this ->mcPairHasCommonMother (particle1, particle2);
71+ }
6972 // if one of the two particles has no associated partonic mother, we cannot know if they have a common anchestor, so we break out with false
7073 if (!particle1.has_fMcPartMoth () || !particle2.has_fMcPartMoth ()) {
7174 return false ;
7275 }
73-
74- // get partonic mothers
75- auto partonicMother1 = particle1.template fMcPartMoth_as <T3 >();
76- auto partonicMother2 = particle2.template fMcPartMoth_as <T3 >();
77-
78- return partonicMother1.globalIndex () != partonicMother2.globalIndex ();
76+ return !this ->mcPairHasCommonPartonicMother (particle1, particle2, partonicMothers);
7977 };
8078
8179 // reco + mc
@@ -111,6 +109,38 @@ class BasePairCleaner
111109
112110 bool mMixPairsWithCommonAncestor = false ;
113111 bool mMixPairsWithNonCommonAncestor = false ;
112+
113+ private:
114+ // require both particles to originate from the same partonic mother
115+ template <typename T1 , typename T2 , typename T3 >
116+ bool mcPairHasCommonPartonicMother (T1 const & particle1, T2 const & particle2, T3 const & /* partonicMothers*/ ) const
117+ {
118+ // if one of the two particles has no associated partonic mother, we cannot know if they have a common anchestor, so we break out with false
119+ if (!particle1.has_fMcPartMoth () || !particle2.has_fMcPartMoth ()) {
120+ return false ;
121+ }
122+
123+ // get partonic mothers
124+ auto partonicMother1 = particle1.template fMcPartMoth_as <T3 >();
125+ auto partonicMother2 = particle2.template fMcPartMoth_as <T3 >();
126+
127+ return partonicMother1.globalIndex () == partonicMother2.globalIndex ();
128+ };
129+
130+ // require both particles to have the same last ancestor, i.e. the same direct mother
131+ // there is exactly one row in the mother table per generated mother, so comparing the indices is sufficient
132+ template <typename T1 , typename T2 >
133+ bool mcPairHasCommonMother (T1 const & particle1, T2 const & particle2) const
134+ {
135+ // if one of the two particles has no associated mother, we cannot know if they have a common anchestor, so we break out with false
136+ if (!particle1.has_fMcMother () || !particle2.has_fMcMother ()) {
137+ return false ;
138+ }
139+
140+ return particle1.fMcMotherId () == particle2.fMcMotherId ();
141+ };
142+
143+ bool mUseMotherAsAncestor = false ;
114144};
115145
116146class TrackTrackPairCleaner : public BasePairCleaner
@@ -147,14 +177,14 @@ class V0V0PairCleaner : public BasePairCleaner // also works for particles decay
147177 public:
148178 V0V0PairCleaner () = default ;
149179 template <typename T1 , typename T2 , typename T3 >
150- bool isCleanPair (T1 const & v01, T2 const & v02, T3 const & trackTable) const
180+ bool isCleanPair (const T1 & v01, const T2 & v02, const T3 & trackTable) const
151181 {
152182 auto posDaughter1 = trackTable.rawIteratorAt (v01.posDauId () - trackTable.offset ());
153183 auto negDaughter1 = trackTable.rawIteratorAt (v01.negDauId () - trackTable.offset ());
154184 auto posDaughter2 = trackTable.rawIteratorAt (v02.posDauId () - trackTable.offset ());
155185 auto negDaughter2 = trackTable.rawIteratorAt (v02.negDauId () - trackTable.offset ());
156- return this -> isCleanParticlePair (v01, v02) &&
157- this ->isCleanParticlePair (posDaughter1, posDaughter2) && this ->isCleanParticlePair (negDaughter1, negDaughter2) &&
186+ // check all charge combinations
187+ return this ->isCleanParticlePair (posDaughter1, posDaughter2) && this ->isCleanParticlePair (negDaughter1, negDaughter2) &&
158188 this ->isCleanParticlePair (posDaughter1, negDaughter2) && this ->isCleanParticlePair (negDaughter1, posDaughter2);
159189 }
160190
@@ -181,7 +211,7 @@ class TrackV0PairCleaner : public BasePairCleaner // also works for particles de
181211 public:
182212 TrackV0PairCleaner () = default ;
183213 template <typename T1 , typename T2 , typename T3 >
184- bool isCleanPair (T1 const & track, T2 const & v0, T3 const & trackTable) const
214+ bool isCleanPair (const T1 & track, const T2 & v0, const T3 & trackTable) const
185215 {
186216 auto posDaughter = trackTable.rawIteratorAt (v0.posDauId () - trackTable.offset ());
187217 auto negDaughter = trackTable.rawIteratorAt (v0.negDauId () - trackTable.offset ());
@@ -211,7 +241,7 @@ class TrackKinkPairCleaner : public BasePairCleaner
211241 public:
212242 TrackKinkPairCleaner () = default ;
213243 template <typename T1 , typename T2 , typename T3 >
214- bool isCleanPair (T1 const & track, T2 const & kink, T3 const & trackTable) const
244+ bool isCleanPair (const T1 & track, const T2 & kink, const T3 & trackTable) const
215245 {
216246 auto chaDaughter = trackTable.rawIteratorAt (kink.chaDauId () - trackTable.offset ());
217247 return this ->isCleanParticlePair (chaDaughter, track);
@@ -240,7 +270,7 @@ class TrackCascadePairCleaner : public BasePairCleaner
240270 public:
241271 TrackCascadePairCleaner () = default ;
242272 template <typename T1 , typename T2 , typename T3 >
243- bool isCleanPair (T1 const & track, T2 const & cascade, T3 const & trackTable) const
273+ bool isCleanPair (const T1 & track, const T2 & cascade, const T3 & trackTable) const
244274 {
245275 auto bachelor = trackTable.rawIteratorAt (cascade.bachelorId () - trackTable.offset ());
246276 auto posDaughter = trackTable.rawIteratorAt (cascade.posDauId () - trackTable.offset ());
0 commit comments