@@ -132,10 +132,10 @@ enum CascadeSels {
132132 kCascadeTransRadMin , // /< max. transverse radius
133133
134134 // selection for lambda daughter
135- kLambdaCpaMin , // /< Min. DCA of the lambda daughers at primary vertex
136- kLambdaDcaDauMax , // /< TPC PID for daughters (Pion/Proton)
137- kLambdaTransRadMin , // /< Min. number of TPC clusters of daughter
138- kLambdaDcaToPvMin , // /< Min. DCA to primary vertex of daughter lambda
135+ kLambdaCpaMin , // /< Min. CPA of the lambda
136+ kLambdaDcaDauMax , // /< Max. DCA between the lambda daughters at lambda decay vertex
137+ kLambdaTransRadMin , // /< Min. tranverse radius of the lambda
138+ kLambdaDcaToPvMin , // /< Min. DCA of the lambda to the primary vertex
139139
140140 // selection for bachelor/daugthers
141141 kDauAbsEtaMax , // /< Max. |eta| of daughter tracks
@@ -181,9 +181,7 @@ const std::unordered_map<CascadeSels, std::string> cascadeSelectionNames = {
181181 {kPosDauTpc , " Positive Daughter TPC PID" },
182182 {kNegDauTpc , " Negative Daughter TPC PID" },
183183 {kPosDauTof , " Positive Daughter TOF PID" },
184- {kNegDauTof , " Negative Daughter TOF PID" },
185-
186- {kCascadeSelsMax , " Cascade Selections Max" }};
184+ {kNegDauTof , " Negative Daughter TOF PID" }};
187185
188186// / enum for all cascade pre-filters (evaluated in checkFilters, before the selection bitmask)
189187enum CascadeFilters {
@@ -237,6 +235,17 @@ class CascadeSelection : public baseselection::BaseSelection<float, o2::analysis
237235 {
238236 this ->init (config.passThrough .value );
239237
238+ mPtMin = filter.ptMin .value ;
239+ mPtMax = filter.ptMax .value ;
240+ mEtaMin = filter.etaMin .value ;
241+ mEtaMax = filter.etaMax .value ;
242+ mPhiMin = filter.phiMin .value ;
243+ mPhiMax = filter.phiMax .value ;
244+ mLambdaMassMin = filter.massLambdaMin .value ;
245+ mLambdaMassMax = filter.massLambdaMax .value ;
246+ mRequireTof = config.requireTof .value ;
247+ mKeepTracksWithoutTof = config.keepTracksWithoutTof .value ;
248+
240249 if constexpr (modes::isEqual (cascadeType, modes::Cascade::kXi )) {
241250 mXiMassLowerLimit = filter.massXiMin .value ;
242251 mXiMassUpperLimit = filter.massXiMax .value ;
@@ -256,17 +265,6 @@ class CascadeSelection : public baseselection::BaseSelection<float, o2::analysis
256265 this ->addSelection (kBachelorTofKaon , cascadeSelectionNames.at (kBachelorTofKaon ), config.bachelorTofKaon .value , limits::kAbsUpperLimit , true , mRequireTof , false );
257266 }
258267
259- mPtMin = filter.ptMin .value ;
260- mPtMax = filter.ptMax .value ;
261- mEtaMin = filter.etaMin .value ;
262- mEtaMax = filter.etaMax .value ;
263- mPhiMin = filter.phiMin .value ;
264- mPhiMax = filter.phiMax .value ;
265- mLambdaMassMin = filter.massLambdaMin .value ;
266- mLambdaMassMax = filter.massLambdaMax .value ;
267- mRequireTof = config.requireTof .value ;
268- mKeepTracksWithoutTof = config.keepTracksWithoutTof .value ;
269-
270268 this ->addSelection (kPosDauTpc , cascadeSelectionNames.at (kPosDauTpc ), config.posDauTpc .value , limits::kAbsUpperLimit , true , true , false );
271269 this ->addSelection (kNegDauTpc , cascadeSelectionNames.at (kNegDauTpc ), config.negDauTpc .value , limits::kAbsUpperLimit , true , true , false );
272270 this ->addSelection (kPosDauTof , cascadeSelectionNames.at (kPosDauTof ), config.posDauTof .value , limits::kAbsUpperLimit , true , mRequireTof , false );
@@ -324,56 +322,64 @@ class CascadeSelection : public baseselection::BaseSelection<float, o2::analysis
324322 auto negDaughter = cascade.template negTrack_as <T2 >();
325323
326324 // daughter selections
327- std::array<float , 3 > etaDaughters = {std::fabs (bachelor. eta ()), std::fabs (posDaughter. eta ()), std::fabs (negDaughter. eta ())};
325+ std::array<float , 3 > etaDaughters = {std::fabs (cascade. bacheloreta ()), std::fabs (cascade. positiveeta ()), std::fabs (cascade. negativeeta ())};
328326 this ->evaluateObservable (kDauAbsEtaMax , *std::max_element (etaDaughters.begin (), etaDaughters.end ()));
329327
330- std::array<float , 3 > dcaDaughters = {std::fabs (bachelor. dcaXY ()), std::fabs (posDaughter. dcaXY ()), std::fabs (negDaughter. dcaXY ())};
328+ std::array<float , 3 > dcaDaughters = {std::fabs (cascade. dcabachtopv ()), std::fabs (cascade. dcapostopv ()), std::fabs (cascade. dcanegtopv ())};
331329 this ->evaluateObservable (kDauAbsDcaxyMin , *std::min_element (dcaDaughters.begin (), dcaDaughters.end ()));
332330
333331 std::array<float , 3 > clustersDaughters = {1 .f * bachelor.tpcNClsFound (), 1 .f * posDaughter.tpcNClsFound (), 1 .f * negDaughter.tpcNClsFound ()};
334332 this ->evaluateObservable (kDauTpcClsMin , *std::min_element (clustersDaughters.begin (), clustersDaughters.end ()));
335333
336- // bachelor pid selection
337- // check both pion and kaon PID for xi and omega
338- this ->evaluateObservable (kBachelorTpcPion , bachelor.tpcNSigmaPi ());
339- this ->evaluateObservable (kBachelorTpcKaon , bachelor.tpcNSigmaKa ());
340- if (bachelor.hasTOF ()) {
341- this ->evaluateObservable (kBachelorTofPion , bachelor.tofNSigmaPi ());
342- this ->evaluateObservable (kBachelorTofKaon , bachelor.tofNSigmaKa ());
343- } else if (mKeepTracksWithoutTof ) {
344- this ->evaluateObservable (kBachelorTofPion , 0 );
345- this ->evaluateObservable (kBachelorTofKaon , 0 );
346- }
347-
348- // depending on the charge, we check lambda or antilambda hypothesis
349- if (cascade.sign () < 0 ) {
350- this ->evaluateObservable (kPosDauTpc , posDaughter.tpcNSigmaPr ());
351- this ->evaluateObservable (kNegDauTpc , negDaughter.tpcNSigmaPi ());
352- if (posDaughter.hasTOF ()) {
353- this ->evaluateObservable (kPosDauTof , posDaughter.tofNSigmaPr ());
334+ // pid selections
335+ // TPC nSigma comes from the daughter track, TOF nSigma and the has-TOF flags from the cascade candidate
336+ // if a daughter has no TOF signal, feed 0 so the bit passes any limit (opt-in via keepTracksWithoutTof)
337+ auto evaluatePid = [this ](CascadeSels tpcBit, float tpcNSigma,
338+ CascadeSels tofBit, float tofNSigma, bool hasTof) {
339+ this ->evaluateObservable (tpcBit, tpcNSigma);
340+ if (hasTof) {
341+ this ->evaluateObservable (tofBit, tofNSigma);
354342 } else if (mKeepTracksWithoutTof ) {
355- this ->evaluateObservable (kPosDauTof , 0 );
343+ this ->evaluateObservable (tofBit , 0 . f );
356344 }
357- if (negDaughter.hasTOF ()) {
358- this ->evaluateObservable (kNegDauTof , negDaughter.tofNSigmaPi ());
359- } else if (mKeepTracksWithoutTof ) {
360- this ->evaluateObservable (kNegDauTof , 0 );
361- }
362- } else if (cascade.sign () > 0 ) {
363- this ->evaluateObservable (kPosDauTpc , posDaughter.tpcNSigmaPi ());
364- this ->evaluateObservable (kNegDauTpc , negDaughter.tpcNSigmaPr ());
365- if (posDaughter.hasTOF ()) {
366- this ->evaluateObservable (kPosDauTof , posDaughter.tofNSigmaPi ());
367- } else if (mKeepTracksWithoutTof ) {
368- this ->evaluateObservable (kPosDauTof , 0 );
369- }
370- if (negDaughter.hasTOF ()) {
371- this ->evaluateObservable (kNegDauTof , negDaughter.tofNSigmaPr ());
372- } else if (mKeepTracksWithoutTof ) {
373- this ->evaluateObservable (kNegDauTof , 0 );
374- }
375- } else {
345+ };
346+
347+ const bool bachHasTof = cascade.bachelorHasTOF ();
348+ const bool posHasTof = cascade.positiveHasTOF ();
349+ const bool negHasTof = cascade.negativeHasTOF ();
350+
351+ // bachelor: pion for Xi, kaon for Omega
352+ if constexpr (modes::isEqual (cascadeType, modes::Cascade::kXi )) {
353+ evaluatePid (kBachelorTpcPion , bachelor.tpcNSigmaPi (),
354+ kBachelorTofPion , cascade.tofNSigmaXiPi (), bachHasTof);
355+ } else if constexpr (modes::isEqual (cascadeType, modes::Cascade::kOmega )) {
356+ evaluatePid (kBachelorTpcKaon , bachelor.tpcNSigmaKa (),
357+ kBachelorTofKaon , cascade.tofNSigmaOmKa (), bachHasTof);
358+ }
359+
360+ // v0 daughters: charge of the cascade fixes the Lambda vs. AntiLambda hypothesis
361+ if (cascade.sign () == 0 ) {
376362 LOG (warn) << " Encountered Cascade candidate with 0 charge" ;
363+ } else {
364+ // sign < 0: Xi-/Omega- -> Lambda -> p pi- (pos = proton, neg = pion)
365+ // sign > 0: Xi+/Omega+ -> AntiLambda (pos = pion, neg = antiproton)
366+ const bool isMatter = cascade.sign () < 0 ;
367+
368+ const float tpcPosDau = isMatter ? posDaughter.tpcNSigmaPr () : posDaughter.tpcNSigmaPi ();
369+ const float tpcNegDau = isMatter ? negDaughter.tpcNSigmaPi () : negDaughter.tpcNSigmaPr ();
370+
371+ float tofPosDau = 0 .f ;
372+ float tofNegDau = 0 .f ;
373+ if constexpr (modes::isEqual (cascadeType, modes::Cascade::kXi )) {
374+ tofPosDau = isMatter ? cascade.tofNSigmaXiLaPr () : cascade.tofNSigmaXiLaPi ();
375+ tofNegDau = isMatter ? cascade.tofNSigmaXiLaPi () : cascade.tofNSigmaXiLaPr ();
376+ } else if constexpr (modes::isEqual (cascadeType, modes::Cascade::kOmega )) {
377+ tofPosDau = isMatter ? cascade.tofNSigmaOmLaPr () : cascade.tofNSigmaOmLaPi ();
378+ tofNegDau = isMatter ? cascade.tofNSigmaOmLaPi () : cascade.tofNSigmaOmLaPr ();
379+ }
380+
381+ evaluatePid (kPosDauTpc , tpcPosDau, kPosDauTof , tofPosDau, posHasTof);
382+ evaluatePid (kNegDauTpc , tpcNegDau, kNegDauTof , tofNegDau, negHasTof);
377383 }
378384
379385 this ->assembleBitmask <SelectionHistName>();
@@ -657,6 +663,22 @@ class CascadeBuilder
657663 template <typename T1 , typename T2 , typename T3 , typename T4 >
658664 void fillCascade (T1 & collisionBuilder, T2 & cascadeProducts, T3 const & cascade, T4 const & col, int bachelorIndex, int posDaughterIndex, int negDaughterIndex)
659665 {
666+ float strangeTofBachelor = 0 .f ;
667+ float strangeTofPosDau = 0 .f ;
668+ float strangeTofNegDau = 0 .f ;
669+ const bool isMatter = cascade.sign () < 0 ; // Xi-/Omega- -> Lambda -> p pi- (pos=proton, neg=pion)
670+
671+ if constexpr (modes::isEqual (cascadeType, modes::Cascade::kXi )) {
672+ strangeTofBachelor = cascade.tofNSigmaXiPi ();
673+ strangeTofPosDau = isMatter ? cascade.tofNSigmaXiLaPr () : cascade.tofNSigmaXiLaPi ();
674+ strangeTofNegDau = isMatter ? cascade.tofNSigmaXiLaPi () : cascade.tofNSigmaXiLaPr ();
675+ }
676+ if constexpr (modes::isEqual (cascadeType, modes::Cascade::kOmega )) {
677+ strangeTofBachelor = cascade.tofNSigmaOmKa ();
678+ strangeTofPosDau = isMatter ? cascade.tofNSigmaOmLaPr () : cascade.tofNSigmaOmLaPi ();
679+ strangeTofNegDau = isMatter ? cascade.tofNSigmaOmLaPi () : cascade.tofNSigmaOmLaPr ();
680+ }
681+
660682 if constexpr (modes::isEqual (cascadeType, modes::Cascade::kXi )) {
661683 if (mProduceXis ) {
662684 cascadeProducts.producedXis (collisionBuilder.collisionIndex (),
@@ -691,7 +713,10 @@ class CascadeBuilder
691713 cascade.v0cosPA (col.posX (), col.posY (), col.posZ ()),
692714 cascade.dcaV0daughters (),
693715 cascade.v0radius (),
694- cascade.dcav0topv (col.posX (), col.posY (), col.posZ ()));
716+ cascade.dcav0topv (col.posX (), col.posY (), col.posZ ()),
717+ strangeTofBachelor,
718+ strangeTofPosDau,
719+ strangeTofNegDau);
695720 }
696721 }
697722 if constexpr (modes::isEqual (cascadeType, modes::Cascade::kOmega )) {
@@ -728,7 +753,10 @@ class CascadeBuilder
728753 cascade.v0cosPA (col.posX (), col.posY (), col.posZ ()),
729754 cascade.dcaV0daughters (),
730755 cascade.v0radius (),
731- cascade.dcav0topv (col.posX (), col.posY (), col.posZ ()));
756+ cascade.dcav0topv (col.posX (), col.posY (), col.posZ ()),
757+ strangeTofBachelor,
758+ strangeTofPosDau,
759+ strangeTofNegDau);
732760 }
733761 }
734762 }
0 commit comments