@@ -3293,6 +3293,7 @@ struct HfTrackIndexSkimCreatorLfCascades {
32933293
32943294 Configurable<bool > do3Prong{" do3Prong" , false , " do 3-prong cascade" };
32953295 Configurable<bool > rejDiffCollTrack{" rejDiffCollTrack" , false , " Reject tracks coming from different collisions" };
3296+ Configurable<double > ptTolerance{" ptTolerance" , 0.1 , " pT tolerance in GeV/c for applying preselections before vertex reconstruction" };
32963297
32973298 // charm baryon invariant mass spectra limits
32983299 Configurable<double > massXiPiMin{" massXiPiMin" , 2.1 , " Invariant mass lower limit for xi pi decay channel" };
@@ -3324,10 +3325,12 @@ struct HfTrackIndexSkimCreatorLfCascades {
33243325 Configurable<float > ptMinXicplusLfCasc{" ptMinXicplusLfCasc" , 0 .f , " min. pT for Xicplus in Xi + Pi + Pi decays" };
33253326 Configurable<float > v0TransvRadius{" v0TransvRadius" , 1.0 , " V0 radius in xy plane" }; // 1.2 (xi) and 1.1 (omega) in run2
33263327 Configurable<float > cascTransvRadius{" cascTransvRadius" , 0.4 , " Cascade radius in xy plane" }; // 0.5 cm (xi) and 0.6 (omega) in run2
3328+ Configurable<float > decayLengthXicMin{" decayLengthXicMin" , 0.4 , " Min. decay length of Xic" }; // ...
33273329 Configurable<float > dcaBachToPv{" dcaBachToPv" , 0.03 , " DCA Bach To PV" }; // 0.04 in run2
33283330 Configurable<float > dcaV0ToPv{" dcaV0ToPv" , 0.02 , " DCA V0 To PV" }; // 0.03 in run2
33293331 Configurable<double > v0CosPA{" v0CosPA" , 0.95 , " V0 CosPA" }; // 0.97 in run2 - KEEP LOSE to re-cut after PVRefit! - double -> N.B. dcos(x)/dx = 0 at x=0)
33303332 Configurable<double > cascCosPA{" cascCosPA" , 0.95 , " Casc CosPA" }; // 0.97 in run2 - KEEP LOSE to re-cut after PVRefit! - double -> N.B. dcos(x)/dx = 0 at x=0)
3333+ Configurable<double > xicCosPA{" xicCosPA" , 0.95 , " Xic CosPA" }; // 0.97 in run2 - KEEP LOSE to re-cut after PVRefit! - double -> N.B. dcos(x)/dx = 0 at x=0)
33313334 Configurable<float > dcaV0Dau{" dcaV0Dau" , 2.0 , " DCA V0 Daughters" }; // conservative, a cut ar 1.0 should also be fine
33323335 Configurable<float > dcaCascDau{" dcaCascDau" , 2.0 , " DCA Casc Daughters" }; // conservative, a cut ar 1.0 should also be fine
33333336 Configurable<float > dcaNegToPv{" dcaNegToPv" , 0.05 , " DCA Neg To PV" }; // 0.06 in run2
@@ -3490,6 +3493,58 @@ struct HfTrackIndexSkimCreatorLfCascades {
34903493 return false ;
34913494 }
34923495
3496+ // / Method to perform selections for 3-prong candidates before vertex reconstruction
3497+ // / \param pVecTrack0 is the momentum array of the first daughter track
3498+ // / \param pVecTrack1 is the momentum array of the second daughter track
3499+ // / \param pVecTrack2 is the momentum array of the third daughter track
3500+ template <typename T1>
3501+ bool isPreselectedCandidate (T1 const & pVecTrack0, T1 const & pVecTrack1, T1 const & pVecTrack2)
3502+ {
3503+ // pt
3504+ auto pt = RecoDecay::pt (pVecTrack0, pVecTrack1, pVecTrack2) + config.ptTolerance ; // add tolerance because of no reco decay vertex
3505+ if (pt < config.ptMinXicplusLfCasc ) {
3506+ return false ;
3507+ }
3508+
3509+ // invariant mass
3510+ double invMassMin = config.massXiPiPiMin ;
3511+ double invMassMax = config.massXiPiPiMax ;
3512+ if (invMassMin >= 0 . && invMassMax > 0 .) {
3513+ auto arrMom = std::array{pVecTrack0, pVecTrack1, pVecTrack2};
3514+ auto invMass2 = RecoDecay::m2 (arrMom, arrMass3Prong[hf_cand_casc_lf::DecayType3Prong::XicplusToXiPiPi]);
3515+ if (invMass2 < invMassMin * invMassMin || invMass2 >= invMassMax * invMassMax) {
3516+ return false ;
3517+ }
3518+ }
3519+ }
3520+
3521+ // / Method to perform selections for 3-prong candidates after vertex reconstruction
3522+ // / \param pVecCand is the array for the candidate momentum after reconstruction of secondary vertex
3523+ // / \param secVtx is the secondary vertex
3524+ // / \param primVtx is the primary vertex
3525+ // / \return selection outcome
3526+ template <typename T1, typename T2, typename T3>
3527+ bool isSelectedCandidate (const T1& pVecCand, const T2& secVtx, const T3& primVtx)
3528+ {
3529+ // pt
3530+ auto pt = RecoDecay::pt (pVecCand);
3531+ if (pt <= config.ptMinXicplusLfCasc ) {
3532+ return false ;
3533+ }
3534+
3535+ // CPA
3536+ auto cpa = RecoDecay::cpa (primVtx, secVtx, pVecCand);
3537+ if (cpa < config.xicCosPA ) {
3538+ return false ;
3539+ }
3540+
3541+ // decay length
3542+ auto decayLength = RecoDecay::distance (primVtx, secVtx);
3543+ if (decayLength < config.decayLengthXicMin ) {
3544+ return false ;
3545+ }
3546+ }
3547+
34933548 void processNoLfCascades (SelectedCollisions const &)
34943549 {
34953550 // dummy
@@ -3560,20 +3615,20 @@ struct HfTrackIndexSkimCreatorLfCascades {
35603615 covCasc[i] = casc.positionCovMat ()[i];
35613616 }
35623617 // create cascade track
3563- o2::track::TrackParCov trackCascXi ;
3618+ o2::track::TrackParCov trackParCovCascXi ;
35643619 if (trackCascDauCharged.sign () > 0 ) {
3565- trackCascXi = o2::track::TrackParCov (vertexCasc, pVecCasc, covCasc, 1 , true );
3620+ trackParCovCascXi = o2::track::TrackParCov (vertexCasc, pVecCasc, covCasc, 1 , true );
35663621 } else if (trackCascDauCharged.sign () < 0 ) {
3567- trackCascXi = o2::track::TrackParCov (vertexCasc, pVecCasc, covCasc, -1 , true );
3622+ trackParCovCascXi = o2::track::TrackParCov (vertexCasc, pVecCasc, covCasc, -1 , true );
35683623 } else {
35693624 continue ;
35703625 }
3571- trackCascXi .setAbsCharge (1 );
3626+ trackParCovCascXi .setAbsCharge (1 );
35723627
3573- auto trackCascOmega = trackCascXi ;
3628+ auto trackParCovCascOmega = trackParCovCascXi ;
35743629
3575- trackCascXi .setPID (o2::track::PID::XiMinus);
3576- trackCascOmega .setPID (o2::track::PID::OmegaMinus);
3630+ trackParCovCascXi .setPID (o2::track::PID::XiMinus);
3631+ trackParCovCascOmega .setPID (o2::track::PID::OmegaMinus);
35773632
35783633 // --------------combining cascade and pion tracks--------------
35793634 auto groupedBachTrackIndices = trackIndices.sliceBy (trackIndicesPerCollision, thisCollId);
@@ -3600,12 +3655,12 @@ struct HfTrackIndexSkimCreatorLfCascades {
36003655 }
36013656
36023657 // primary pion track to be processed with DCAFitter
3603- auto trackParVarCharmBachelor1 = getTrackParCov (trackCharmBachelor1);
3658+ auto trackParCovCharmBachelor1 = getTrackParCov (trackCharmBachelor1);
36043659
36053660 // find charm baryon decay using xi PID hypothesis (xi pi channel)
36063661 int nVtxFrom2ProngFitterXiHyp = 0 ;
36073662 try {
3608- nVtxFrom2ProngFitterXiHyp = df2.process (trackCascXi, trackParVarCharmBachelor1 );
3663+ nVtxFrom2ProngFitterXiHyp = df2.process (trackParCovCascXi, trackParCovCharmBachelor1 );
36093664 } catch (...) {
36103665 if (config.fillHistograms ) {
36113666 registry.fill (HIST (" hFitterStatusXi2Prong" ), 1 );
@@ -3651,7 +3706,7 @@ struct HfTrackIndexSkimCreatorLfCascades {
36513706 // find charm baryon decay using omega PID hypothesis to be combined with the charm bachelor (either pion or kaon)
36523707 int nVtxFrom2ProngFitterOmegaHyp = 0 ;
36533708 try {
3654- nVtxFrom2ProngFitterOmegaHyp = df2.process (trackCascOmega, trackParVarCharmBachelor1 );
3709+ nVtxFrom2ProngFitterOmegaHyp = df2.process (trackParCovCascOmega, trackParCovCharmBachelor1 );
36553710 } catch (...) {
36563711 if (config.fillHistograms ) {
36573712 registry.fill (HIST (" hFitterStatusOmega2Prong" ), 1 );
@@ -3719,14 +3774,16 @@ struct HfTrackIndexSkimCreatorLfCascades {
37193774 hfFlag);
37203775 }
37213776
3722- // first loop over tracks
3777+ // Xic -> Xi pi pi
37233778 if (config.do3Prong ) {
3779+ // Xi mass cut
3780+ if (std::abs (casc.mXi () - MassXiMinus) > config.cascadeMassWindow ) {
3781+ continue ;
3782+ }
37243783
3725- // second loop over positive tracks
3784+ // second loop over tracks
37263785 for (auto trackIdCharmBachelor2 = trackIdCharmBachelor1 + 1 ; trackIdCharmBachelor2 != groupedBachTrackIndices.end (); ++trackIdCharmBachelor2) {
37273786
3728- hfFlag = 0 ;
3729-
37303787 if (!TESTBIT (trackIdCharmBachelor2.isSelProng (), CandidateType::CandCascadeBachelor)) {
37313788 continue ;
37323789 }
@@ -3747,14 +3804,16 @@ struct HfTrackIndexSkimCreatorLfCascades {
37473804 continue ;
37483805 }
37493806
3750- // primary pion track to be processed with DCAFitter
3751- auto trackParVarPion2 = getTrackParCov (trackCharmBachelor2);
3807+ if (!isPreselectedCandidate (pVecCasc, trackCharmBachelor1.pVector (), trackCharmBachelor2.pVector ())) {
3808+ continue ;
3809+ }
37523810
37533811 // reconstruct Xic with DCAFitter
3812+ // Use only bachelor tracks for vertex reconstruction because the Xi track has large uncertainties.
37543813 int nVtxFrom3ProngFitterXiHyp = 0 ;
37553814 try {
3756- // Use only bachelor tracks for vertex reconstruction because the Xi track has large uncertainties.
3757- nVtxFrom3ProngFitterXiHyp = df2.process (trackParVarCharmBachelor1, trackParVarPion2 );
3815+ auto trackParCovCharmBachelor2 = getTrackParCov (trackCharmBachelor2);
3816+ nVtxFrom3ProngFitterXiHyp = df2.process (trackParCovCharmBachelor1, trackParCovCharmBachelor2 );
37583817 } catch (...) {
37593818 if (config.fillHistograms ) {
37603819 registry.fill (HIST (" hFitterStatusXi3Prong" ), 1 );
@@ -3766,47 +3825,45 @@ struct HfTrackIndexSkimCreatorLfCascades {
37663825 }
37673826
37683827 if (nVtxFrom3ProngFitterXiHyp > 0 ) {
3769-
37703828 df2.propagateTracksToVertex ();
3771-
37723829 if (df2.isPropagateTracksToVertexDone ()) {
3773-
3774- std::array<float , 3 > pVec1 = {0 .};
3775- std::array<float , 3 > pVec2 = { 0 .};
3776- std::array< float , 3 > pVec3 = pVecCasc;
3777- df2.getTrack (0 ).getPxPyPzGlo (pVec1); // take the momentum at the Xic vertex
3830+ std::array< float , 3 > pVec1{ 0 .};
3831+ std::array<float , 3 > pVec2 {0 .};
3832+ std::array<float , 3 > pVec3{pVecCasc}; // Use the Xi track for the 3-prong calculations.
3833+ // get bachelor momenta at the Xic vertex
3834+ df2.getTrack (0 ).getPxPyPzGlo (pVec1);
37783835 df2.getTrack (1 ).getPxPyPzGlo (pVec2);
3779- float ptXic3Prong = RecoDecay::pt (pVec1, pVec2, pVec3);
3780-
3781- std::array<std::array<float , 3 >, 3 > arr3Mom = {pVec1, pVec2, pVec3};
3782- auto mass3Prong = RecoDecay::m (arr3Mom, arrMass3Prong[hf_cand_casc_lf::DecayType3Prong::XicplusToXiPiPi]);
3836+ auto pVecCand = RecoDecay::pVec (pVec1, pVec2, pVec3);
3837+ auto ptCand = RecoDecay::pt (pVecCand);
3838+ std::array<float , 3 > primaryVertex{collision.posX (), collision.posY (), collision.posZ ()}; // primary vertex
3839+ const auto & secondaryVertex = df2.getPCACandidate (); // secondary vertex
3840+
3841+ registry.fill (HIST (" hRejpTStatusXicPlusToXiPiPi" ), 0 );
3842+ if (ptCand >= config.ptMinXicplusLfCasc ) {
3843+ registry.fill (HIST (" hRejpTStatusXicPlusToXiPiPi" ), 1 );
3844+ }
37833845
3784- if ((std::abs (casc.mXi () - MassXiMinus) < config.cascadeMassWindow ) && (mass3Prong >= config.massXiPiPiMin ) && (mass3Prong <= config.massXiPiPiMax )) {
3785- registry.fill (HIST (" hRejpTStatusXicPlusToXiPiPi" ), 0 );
3786- if (ptXic3Prong >= config.ptMinXicplusLfCasc ) {
3787- SETBIT (hfFlag, aod::hf_cand_casc_lf::DecayType3Prong::XicplusToXiPiPi);
3788- registry.fill (HIST (" hRejpTStatusXicPlusToXiPiPi" ), 1 );
3789- }
3846+ if (!isSelectedCandidate (pVecCand, secondaryVertex, primaryVertex)) {
3847+ continue ;
37903848 }
37913849
37923850 // fill histograms
3793- if (config.fillHistograms && (TESTBIT (hfFlag, aod::hf_cand_casc_lf::DecayType3Prong::XicplusToXiPiPi))) {
3851+ if (config.fillHistograms ) {
3852+ std::array<std::array<float , 3 >, 3 > arr3Mom = {pVec1, pVec2, pVec3};
3853+ auto mass3Prong = RecoDecay::m (arr3Mom, arrMass3Prong[hf_cand_casc_lf::DecayType3Prong::XicplusToXiPiPi]);
37943854 registry.fill (HIST (" hMassXicPlusToXiPiPi" ), mass3Prong);
3795- registry.fill (HIST (" hPtCutsXicPlusToXiPiPi" ), ptXic3Prong );
3855+ registry.fill (HIST (" hPtCutsXicPlusToXiPiPi" ), ptCand );
37963856 }
3857+
3858+ // fill table row if a vertex was found
3859+ rowTrackIndexCasc3Prong (thisCollId,
3860+ casc.cascadeId (),
3861+ trackCharmBachelor1.globalIndex (),
3862+ trackCharmBachelor2.globalIndex ());
37973863 } else if (df2.isPropagationFailure ()) {
37983864 LOGF (info, " Exception caught: failed to propagate tracks (3prong) to charm baryon decay vtx" );
37993865 }
38003866 }
3801-
3802- // fill table row only if a vertex was found
3803- if (hfFlag != 0 ) {
3804- rowTrackIndexCasc3Prong (thisCollId,
3805- casc.cascadeId (),
3806- trackCharmBachelor1.globalIndex (),
3807- trackCharmBachelor2.globalIndex ());
3808- }
3809-
38103867 } // end 3prong loop
38113868 } // end 3prong condition
38123869
0 commit comments