1616// / \author Martin Voelkl <martin.andreas.volkl@cern.ch>, University of Birmingham
1717
1818#include < vector>
19+ #include < array>
20+ #include < algorithm>
1921
2022#include " CommonConstants/PhysicsConstants.h"
2123#include " Framework/AnalysisTask.h"
@@ -42,7 +44,7 @@ struct HfTaskLb {
4244 Configurable<int > selectionFlagLb{" selectionFlagLb" , 0 , " Selection Flag for Lb" };
4345 Configurable<float > yCandGenMax{" yCandGenMax" , 0.5 , " max. gen particle rapidity" };
4446 Configurable<float > yCandRecoMax{" yCandRecoMax" , 0.8 , " max. cand. rapidity" };
45- Configurable<float > DCALengthParameter{ " DCALengthParameter " , 0.02 , " decay length for DCA" };
47+ Configurable<float > lengthDCAParameter{ " lengthDCAParameter " , 0.02 , " decay length for DCA" };
4648 Configurable<float > minLikelihoodRatio{" minLikelihoodRatio" , 10 ., " min. likelihood ratio for combined DCAs" };
4749 Configurable<float > minLikelihoodRatioLc{" minLikelihoodRatioLc" , 10 ., " min. likelihood ratio for Lc cross check" };
4850 Configurable<float > mDiffKStar892Max {" mDiffKStar892Max" , 0.0473 , " Accepted range around KStar mass peak" };
@@ -57,24 +59,24 @@ struct HfTaskLb {
5759 HfHelper hfHelper;
5860 Service<o2::framework::O2DatabasePDG> pdg;
5961
60- Filter filterSelectCandidates = (aod::hf_sel_candidate_lb::isSelLbToLcPi >= selectionFlagLb);
61-
6262 using TracksWExt = soa::Join<o2::aod::Tracks, o2::aod::TracksExtra, aod::TrackSelection, o2::aod::TrackSelectionExtension, aod::TracksPidPi, aod::PidTpcTofFullPi, aod::TracksPidKa, aod::PidTpcTofFullKa>;
6363 using TracksWExtMc = soa::Join<o2::aod::Tracks, o2::aod::TracksExtra, aod::TrackSelection, o2::aod::TrackSelectionExtension, aod::TracksPidPi, aod::PidTpcTofFullPi, aod::TracksPidKa, aod::PidTpcTofFullKa, McTrackLabels>;
6464
65- PresliceUnsorted<aod::TracksWMc> McPartID = aod::mctracklabel::mcParticleId;
65+ Filter filterSelectCandidates = (aod::hf_sel_candidate_lb::isSelLbToLcPi >= selectionFlagLb);
66+
67+ PresliceUnsorted<aod::TracksWMc> mcPartID = aod::mctracklabel::mcParticleId;
6668
6769 bool passesImpactParameterResolution (float pT, float d0Resolution)
6870 {
6971 float expectedResolution (0.001 + 0.0052 * std::exp (-0.655 * pT));
7072 return (d0Resolution <= expectedResolution * 1.5 );
7173 } // Compares to pT dependent cut on impact parameter resolution
7274
73- float logLikelihoodRatioSingleTrackDCA (float DCA , float reso, float lengthParameter)
75+ float logLikelihoodRatioSingleTrackDCA (float dca , float reso, float lengthParameter)
7476 {
7577 reso *= resoCorrectionFactor; // In case real resolution is worse
76- float numerator = 1 . / lengthParameter * std::exp (-DCA / lengthParameter);
77- float denominator = (1 . - largeLifetimeBG) * TMath::Gaus (DCA , 0 ., reso, true ) + largeLifetimeBG / 0.2 ; // flat distribution to 2 mm
78+ float numerator = 1 . / lengthParameter * std::exp (-dca / lengthParameter);
79+ float denominator = (1 . - largeLifetimeBG) * TMath::Gaus (dca , 0 ., reso, true ) + largeLifetimeBG / 0.2 ; // flat distribution to 2 mm
7880 return std::log (numerator / denominator);
7981 } // Creates the single track log likelihood assuming an exonential law for the secondaries
8082
@@ -172,6 +174,8 @@ struct HfTaskLb {
172174 {
173175 float massKStar892 = 0.892 ;
174176 float massDelta1232 = 1.232 ;
177+ std::array<float , 3 > dca = {0 .f , 0 .f , 0 .f };
178+ std::array<float , 3 > dcaResolution = {0 .f , 0 .f , 0 .f };
175179
176180 for (const auto & candidateLc : candidatesLc) {
177181 if (!candidateLc.isSelLcToPKPi () && !candidateLc.isSelLcToPiKP ())
@@ -194,12 +198,26 @@ struct HfTaskLb {
194198 continue ;
195199 if (!passesImpactParameterResolution (track2.pt (), reso2))
196200 continue ;
197- float DCA0 = candidateLc.impactParameter0 ();
198- float DCA1 = candidateLc.impactParameter1 ();
199- float DCA2 = candidateLc.impactParameter2 ();
200- if (DCA0 > maximumImpactParameterForLambdaCCrossChecks || DCA1 > maximumImpactParameterForLambdaCCrossChecks || DCA2 > maximumImpactParameterForLambdaCCrossChecks)
201+
202+ dca = {
203+ candidateLc.impactParameter0 (),
204+ candidateLc.impactParameter1 (),
205+ candidateLc.impactParameter2 ()};
206+
207+ bool exceedsMaxDca = std::any_of (dca.begin (), dca.end (), [&](float val) {
208+ return val > maximumImpactParameterForLambdaCCrossChecks;
209+ });
210+
211+ if (exceedsMaxDca) {
201212 continue ;
202- float likelihoodRatio = logLikelihoodRatioSingleTrackDCA (DCA0, reso0, DCALengthParameter) + logLikelihoodRatioSingleTrackDCA (DCA1, reso1, DCALengthParameter) + logLikelihoodRatioSingleTrackDCA (DCA2, reso2, DCALengthParameter);
213+ }
214+ dcaResolution = {reso0, reso1, reso2};
215+
216+ float likelihoodRatio = 0 .0f ;
217+ for (size_t i = 0 ; i < dca.size (); ++i) {
218+ likelihoodRatio += logLikelihoodRatioSingleTrackDCA (dca[i], dcaResolution[i], lengthDCAParameter);
219+ }
220+
203221 registry.get <TH2>(HIST (" hPtlogLikelihood" ))->Fill (candidateLc.pt (), likelihoodRatio);
204222 if (likelihoodRatio < minLikelihoodRatioLc)
205223 continue ;
@@ -255,24 +273,31 @@ struct HfTaskLb {
255273 } // Lambda_c candidates loop for cross checks
256274
257275 for (const auto & candidate : candidates) {
258- if (!(candidate.hfflag () & 1 << hf_cand_lb::DecayType::LbToLcPi)) { // This should never be true as the loop is over Lb candidates
259- continue ;
260- }
276+
261277 if (yCandRecoMax >= 0 . && std::abs (hfHelper.yLb (candidate)) > yCandRecoMax) {
262278 continue ;
263279 }
264280 registry.get <TH1>(HIST (" hZVertex" ))->Fill (collision.posZ ());
265281
266282 auto candLc = candidate.prong0_as <soa::Join<aod::HfCand3Prong, aod::HfSelLc>>();
267- float d0resolution0 = candLc.errorImpactParameter0 ();
268- float d0resolution1 = candLc.errorImpactParameter1 ();
269- float d0resolution2 = candLc.errorImpactParameter2 ();
270- float DCA0 = candLc.impactParameter0 ();
271- float DCA1 = candLc.impactParameter1 ();
272- float DCA2 = candLc.impactParameter2 ();
273- float likelihoodRatio = logLikelihoodRatioSingleTrackDCA (DCA0, d0resolution0, DCALengthParameter) + logLikelihoodRatioSingleTrackDCA (DCA1, d0resolution1, DCALengthParameter) + logLikelihoodRatioSingleTrackDCA (DCA2, d0resolution2, DCALengthParameter);
274- if (likelihoodRatio < minLikelihoodRatio)
283+ dca = {
284+ candLc.impactParameter0 (),
285+ candLc.impactParameter1 (),
286+ candLc.impactParameter2 ()};
287+
288+ dcaResolution = {
289+ candLc.errorImpactParameter0 (),
290+ candLc.errorImpactParameter1 (),
291+ candLc.errorImpactParameter2 ()};
292+
293+ float likelihoodRatio = 0 .0f ;
294+ for (size_t i = 0 ; i < dca.size (); ++i) {
295+ likelihoodRatio += logLikelihoodRatioSingleTrackDCA (dca[i], dcaResolution[i], lengthDCAParameter);
296+ }
297+
298+ if (likelihoodRatio < minLikelihoodRatio) {
275299 continue ; // Larger likelihood means more likely to be signal
300+ }
276301 float lbMass = hfHelper.invMassLbToLcPi (candidate);
277302 registry.get <TH2>(HIST (" hPtinvMassLb" ))->Fill (candidate.pt (), lbMass);
278303
@@ -304,15 +329,14 @@ struct HfTaskLb {
304329 {
305330 // MC rec
306331 for (const auto & candidate : candidates) {
307- if (!(candidate.hfflag () & 1 << hf_cand_lb::DecayType::LbToLcPi)) {
308- continue ;
309- }
332+
310333 if (yCandRecoMax >= 0 . && std::abs (hfHelper.yLb (candidate)) > yCandRecoMax) {
311334 continue ;
312335 }
313- auto candLc = candidate.prong0_as <aod::HfCand3Prong>();
336+ auto candLc = candidate.prong0_as <soa::Join<aod::HfCand3Prong, aod::HfCand3ProngMcRec>>();
337+ int flagMcMatchRecLb = std::abs (candidate.flagMcMatchRec ());
314338
315- if (std::abs (candidate. flagMcMatchRec ()) == 1 << hf_cand_lb::DecayType::LbToLcPi) {
339+ if (TESTBIT (flagMcMatchRecLb, hf_cand_lb::DecayType::LbToLcPi) ) {
316340
317341 auto indexMother = RecoDecay::getMother (mcParticles, candidate.prong1_as <TracksWExtMc>().mcParticle_as <soa::Join<aod::McParticles, aod::HfCandLbMcGen>>(), o2::constants::physics::Pdg::kLambdaB0 , true );
318342 auto particleMother = mcParticles.rawIteratorAt (indexMother);
0 commit comments