Skip to content

Commit f899d8b

Browse files
MarcellocostiMarcello Di Costanzoalibuild
authored
[PWGHF] Cache D* soft pions propagation (#18214)
Co-authored-by: Marcello Di Costanzo <mdicosta@aliceml.cern.ch> Co-authored-by: ALICE Action Bot <alibuild@cern.ch>
1 parent 07682c5 commit f899d8b

1 file changed

Lines changed: 93 additions & 43 deletions

File tree

‎PWGHF/TableProducer/trackIndexSkimCreator.cxx‎

Lines changed: 93 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -1506,6 +1506,8 @@ struct HfTrackIndexSkimCreator {
15061506
std::array<std::vector<double>, kN2ProngDecays> binsPt2Prong{};
15071507
std::array<LabeledArray<double>, kN3ProngDecays> cut3Prong{};
15081508
std::array<std::vector<double>, kN3ProngDecays> binsPt3Prong{};
1509+
LabeledArray<double> cutsDstar{};
1510+
std::vector<double> binsPtDstar{};
15091511

15101512
// ML response
15111513
o2::analysis::MlResponse<float> hfMlResponse2Prongs; // only D0
@@ -1584,6 +1586,9 @@ struct HfTrackIndexSkimCreator {
15841586
// cuts for 3-prong decays retrieved by json. the order must be then one in hf_cand_3prong::DecayType
15851587
cut3Prong = {config.cutsDplusToPiKPi, config.cutsLcToPKPi, config.cutsDsToKKPi, config.cutsXicToPKPi, config.cutsCdToDeKPi, config.cutsCtToTrKPi, config.cutsChToHeKPi, config.cutsCaToAlKPi};
15861588
binsPt3Prong = {config.binsPtDplusToPiKPi, config.binsPtLcToPKPi, config.binsPtDsToKKPi, config.binsPtXicToPKPi, config.binsPtCdToDeKPi, config.binsPtCtToTrKPi, config.binsPtChToHeKPi, config.binsPtCaToAlKPi};
1589+
// D* cuts retrieved by json
1590+
cutsDstar = config.cutsDstarToD0Pi;
1591+
binsPtDstar = config.binsPtDstarToD0Pi;
15871592

15881593
df2.setPropagateToPCA(config.propagateToPCA);
15891594
df2.setMaxR(config.maxR);
@@ -1724,6 +1729,15 @@ struct HfTrackIndexSkimCreator {
17241729
}
17251730
}
17261731

1732+
/// One track of the collision under study, propagated to that collision's primary vertex.
1733+
/// \tparam TTrackIndex is the iterator type of the track-collision associations
1734+
template <typename TTrackIndex>
1735+
struct HfPropagatedSoftPion {
1736+
TTrackIndex trackIndex; ///< track-collision association, carries isSelProng and isIdentifiedPid
1737+
int64_t trackGlobalIndex{-1}; ///< track global index
1738+
std::array<float, 3> pVec{}; ///< momentum at the PCA to the primary vertex
1739+
};
1740+
17271741
/// One track of the collision under study, propagated to that collision's primary vertex.
17281742
/// \tparam TTrackIndex is the iterator type of the track-collision associations
17291743
/// \tparam TTrack is the iterator type of the track table
@@ -1741,21 +1755,44 @@ struct HfTrackIndexSkimCreator {
17411755
/// \param collision is the collision under study
17421756
/// \param trackIndices are the track associations of this collision
17431757
/// \param prongs is the cache to be filled, in the order of trackIndices
1744-
template <typename TTracks, typename TCollision, typename TTrackIndices, typename TProng>
1758+
template <bool IsSoftPion, typename TTracks, typename TCollision, typename TTrackIndices, typename TProng>
17451759
void fillPropagatedProngCache(TCollision const& collision, TTrackIndices const& trackIndices, std::vector<TProng>& prongs)
17461760
{
17471761
prongs.clear();
17481762
const auto thisCollId = collision.globalIndex();
17491763
for (auto trackIndex = trackIndices.begin(); trackIndex != trackIndices.end(); ++trackIndex) {
17501764
const auto track = trackIndex.template track_as<TTracks>();
1751-
auto& prong = prongs.emplace_back(TProng{trackIndex, track, getTrackParCov(track), track.pVector(), {track.dcaXY(), track.dcaZ()}});
1752-
if (thisCollId != track.collisionId()) { // this is not the "default" collision for this track, we have to re-propagate it
1753-
o2::base::Propagator::Instance()->propagateToDCABxByBz({collision.posX(), collision.posY(), collision.posZ()}, prong.trackParVar, 2.f, noMatCorr, &prong.dcaInfo);
1754-
getPxPyPz(prong.trackParVar, prong.pVec);
1765+
if constexpr (IsSoftPion) {
1766+
std::array<float, 3> pVec = track.pVector();
1767+
if (thisCollId != track.collisionId()) { // this is not the "default" collision for this track, we have to re-propagate it
1768+
auto trackParCov = getTrackParCov(track);
1769+
std::array<float, 2> dcaInfo{};
1770+
o2::base::Propagator::Instance()->propagateToDCABxByBz({collision.posX(), collision.posY(), collision.posZ()}, trackParCov, 2.f, noMatCorr, &dcaInfo);
1771+
getPxPyPz(trackParCov, pVec);
1772+
}
1773+
prongs.push_back(TProng{trackIndex, track.globalIndex(), pVec});
1774+
} else {
1775+
auto& prong = prongs.emplace_back(TProng{trackIndex, track, getTrackParCov(track), track.pVector(), {track.dcaXY(), track.dcaZ()}});
1776+
if (thisCollId != track.collisionId()) { // this is not the "default" collision for this track, we have to re-propagate it
1777+
o2::base::Propagator::Instance()->propagateToDCABxByBz({collision.posX(), collision.posY(), collision.posZ()}, prong.trackParVar, 2.f, noMatCorr, &prong.dcaInfo);
1778+
getPxPyPz(prong.trackParVar, prong.pVec);
1779+
}
17551780
}
17561781
}
17571782
}
17581783

1784+
/// Overloaded function of fillPropagatedProngCache to handle optional track indices.
1785+
/// \param collision is the collision under study
1786+
/// \param trackIndices are the track associations of this collision
1787+
/// \param prongs is the cache to be filled, in the order of trackIndices
1788+
template <bool IsSoftPion, typename TTracks, typename TCollision, typename TTrackIndices, typename TProng>
1789+
void fillPropagatedProngCache(TCollision const& collision, std::optional<TTrackIndices> const& trackIndices, std::vector<TProng>& prongs)
1790+
{
1791+
if (trackIndices.has_value()) {
1792+
fillPropagatedProngCache<IsSoftPion, TTracks>(collision, *trackIndices, prongs);
1793+
}
1794+
}
1795+
17591796
/// Method to perform selections for 2-prong candidates before vertex reconstruction
17601797
/// \param pVecTrack0 is the momentum array of the first daughter track
17611798
/// \param pVecTrack1 is the momentum array of the second daughter track
@@ -1827,10 +1864,10 @@ struct HfTrackIndexSkimCreator {
18271864

18281865
// additional check for D0 to be used in D* finding
18291866
if (iDecay2P == hf_cand_2prong::DecayType::D0ToPiK && config.doDstar && TESTBIT(isSelected, iDecay2P)) {
1830-
const auto binPtDstar = findBin(config.binsPtDstarToD0Pi, pt * 1.2); // assuming the D* pT about 20% higher than the one of the D0 to be safe
1867+
const auto binPtDstar = findBin(&binsPtDstar, pt * 1.2); // assuming the D* pT about 20% higher than the one of the D0 to be safe
18311868
if (binPtDstar >= 0) {
18321869
whichHypo[kN2ProngDecays] = whichHypo[hf_cand_2prong::DecayType::D0ToPiK];
1833-
const double deltaMass = config.cutsDstarToD0Pi->get(binPtDstar, 1u);
1870+
const double deltaMass = cutsDstar.get(binPtDstar, 1u);
18341871

18351872
if (TESTBIT(whichHypo[iDecay2P], 0) && (massHypos[0] > (MassD0 + deltaMass) * (MassD0 + deltaMass) || massHypos[0] < (MassD0 - deltaMass) * (MassD0 - deltaMass))) {
18361873
CLRBIT(whichHypo[kN2ProngDecays], 0);
@@ -2156,18 +2193,18 @@ struct HfTrackIndexSkimCreator {
21562193
/// \param pVecTrack1 is the momentum array of the second daughter track (opposite charge)
21572194
/// \param pVecTrack2 is the momentum array of the third daughter track (same charge)
21582195
/// \param cutStatus is the cut status (filled only in case of debug)
2196+
/// \param invMassD0 is the invariant mass of the D0 candidate
21592197
/// \param deltaMass is the M(Kpipi) - M(Kpi) value to be filled in the control histogram
21602198
/// \return a bitmap with selection outcome
21612199
template <typename T1, typename T2>
2162-
uint8_t applySelectionDstar(T1 const& pVecTrack0, T1 const& pVecTrack1, T1 const& pVecTrack2, uint8_t& cutStatus, T2& deltaMass)
2200+
uint8_t applySelectionDstar(T1 const& pVecTrack0, T1 const& pVecTrack1, T1 const& pVecTrack2, uint8_t& cutStatus, T2 invMassD0, T2& deltaMass)
21632201
{
21642202
uint8_t isSelected{1};
21652203
const std::array arrMom{pVecTrack0, pVecTrack1, pVecTrack2};
2166-
const std::array arrMomD0{pVecTrack0, pVecTrack1};
21672204
const auto pt = RecoDecay::pt(pVecTrack0, pVecTrack1, pVecTrack2) + config.ptTolerance; // add tolerance because of no reco decay vertex
21682205

21692206
// pT
2170-
const auto binPt = findBin(config.binsPtDstarToD0Pi, pt);
2207+
const auto binPt = findBin(&binsPtDstar, pt);
21712208
// return immediately if it is outside the defined pT bins
21722209
if (binPt == -1) {
21732210
isSelected = 0;
@@ -2178,8 +2215,7 @@ struct HfTrackIndexSkimCreator {
21782215
}
21792216

21802217
// D0 mass
2181-
const double deltaMassD0 = config.cutsDstarToD0Pi->get(binPt, 1u); // 1u == deltaMassD0Index
2182-
const double invMassD0 = RecoDecay::m(arrMomD0, std::array{MassPiPlus, MassKPlus});
2218+
const double deltaMassD0 = cutsDstar.get(binPt, 1u); // 1u == deltaMassD0Index
21832219
if (std::abs(invMassD0 - MassD0) > deltaMassD0) {
21842220
isSelected = 0;
21852221
if (config.debug) {
@@ -2189,7 +2225,7 @@ struct HfTrackIndexSkimCreator {
21892225
}
21902226

21912227
// D*+ mass
2192-
const double maxDeltaMass = config.cutsDstarToD0Pi->get(binPt, 0u); // 0u == deltaMassIndex
2228+
const double maxDeltaMass = cutsDstar.get(binPt, 0u); // 0u == deltaMassIndex
21932229
const double invMassDstar = RecoDecay::m(arrMom, std::array{MassPiPlus, MassKPlus, MassPiPlus});
21942230
deltaMass = invMassDstar - invMassD0;
21952231
if (deltaMass > maxDeltaMass) {
@@ -2356,9 +2392,17 @@ struct HfTrackIndexSkimCreator {
23562392
using PropagatedProng = HfPropagatedProng<TrackIndexIterator, decltype(tracks.rawIteratorAt(0))>;
23572393
std::vector<PropagatedProng> prongsPos{};
23582394
std::vector<PropagatedProng> prongsNeg{};
2395+
using SoftPionIterator = decltype(positiveSoftPions->sliceByCached(aod::track::collisionId, 0, cache).begin());
2396+
using PropagatedSoftPi = HfPropagatedSoftPion<SoftPionIterator>;
2397+
std::vector<PropagatedSoftPi> softPionsPos{};
2398+
std::vector<PropagatedSoftPi> softPionsNeg{};
23592399

2400+
bool softPiPosCacheFilled{false}, softPiNegCacheFilled{false};
23602401
for (const auto& collision : collisions) {
23612402

2403+
softPiPosCacheFilled = false;
2404+
softPiNegCacheFilled = false;
2405+
23622406
/// retrieve PV contributors for the current collision
23632407
std::vector<int64_t> vecPvContributorGlobId{};
23642408
std::vector<o2::track::TrackParCov> vecPvContributorTrackParCov{};
@@ -2438,8 +2482,8 @@ struct HfTrackIndexSkimCreator {
24382482
int lastFilledD0 = -1; // index to be filled in table for D* mesons
24392483

24402484
// propagate each track to this collision's PV once, instead of once per pair or triplet
2441-
fillPropagatedProngCache<TTracks>(collision, groupedTrackIndicesPos1, prongsPos);
2442-
fillPropagatedProngCache<TTracks>(collision, groupedTrackIndicesNeg1, prongsNeg);
2485+
fillPropagatedProngCache<false, TTracks>(collision, groupedTrackIndicesPos1, prongsPos);
2486+
fillPropagatedProngCache<false, TTracks>(collision, groupedTrackIndicesNeg1, prongsNeg);
24432487

24442488
for (std::size_t iPos1 = 0; iPos1 < prongsPos.size(); ++iPos1) {
24452489
const auto& trackIndexPos1 = prongsPos[iPos1].trackIndex;
@@ -3216,32 +3260,35 @@ struct HfTrackIndexSkimCreator {
32163260
}
32173261
}
32183262

3219-
if (config.doDstar && TESTBIT(isSelected2ProngCand, hf_cand_2prong::DecayType::D0ToPiK) && (pt2Prong + config.ptTolerance) * 1.2 > config.binsPtDstarToD0Pi->at(0) && whichHypo2Prong[kN2ProngDecays] != 0) { // o2-linter: disable="magic-number" (see comment below)
3220-
// if D* enabled and pt of the D0 is larger than the minimum of the D* one within 20% (D* and D0 momenta are very similar, always within 20% according to PYTHIA8)
3263+
if (config.doDstar && TESTBIT(isSelected2ProngCand, hf_cand_2prong::DecayType::D0ToPiK) && (pt2Prong + config.ptTolerance) * 1.2 > binsPtDstar[0] && whichHypo2Prong[kN2ProngDecays] != 0) { // o2-linter: disable="magic-number" (see comment below)
3264+
// if D* enabled and pt of the D0 is larger than the minimum of the D* one within 20% (D* and D0 momenta are very similar, always within 20% according to PYTHIA8)
32213265
// second loop over positive tracks
32223266
if (TESTBIT(whichHypo2Prong[kN2ProngDecays], 0) && (!config.applyKaonPidIn3Prongs || TESTBIT(trackIndexNeg1.isIdentifiedPid(), ChannelKaonPid))) { // only for D0 candidates; moreover if kaon PID enabled, apply to the negative track
3223-
if (!groupedTrackIndicesSoftPionsPos) {
3267+
3268+
// Compute D0 invariant mass for all D* candidates
3269+
const std::array arrMomD0{pVecTrackPos1, pVecTrackNeg1};
3270+
const float invMassD0 = RecoDecay::m(arrMomD0, std::array{MassPiPlus, MassKPlus});
3271+
3272+
if (!softPiPosCacheFilled) {
32243273
groupedTrackIndicesSoftPionsPos.emplace(positiveSoftPions->sliceByCached(aod::track::collisionId, collision.globalIndex(), cache));
3274+
fillPropagatedProngCache<true, TTracks>(collision, groupedTrackIndicesSoftPionsPos, softPionsPos);
3275+
softPiPosCacheFilled = true;
32253276
}
3226-
for (auto trackIndexPos2 = groupedTrackIndicesSoftPionsPos->begin(); trackIndexPos2 != groupedTrackIndicesSoftPionsPos->end(); ++trackIndexPos2) {
3227-
if (trackIndexPos2 == trackIndexPos1) {
3277+
3278+
for (std::size_t iPos2 = 0; iPos2 < softPionsPos.size(); ++iPos2) {
3279+
if (softPionsPos[iPos2].trackIndex == trackIndexPos1) {
32283280
continue;
32293281
}
3230-
auto trackPos2 = trackIndexPos2.template track_as<TTracks>();
3231-
std::array pVecTrackPos2{trackPos2.pVector()};
3232-
if (thisCollId != trackPos2.collisionId()) { // this is not the "default" collision for this track, we have to re-propagate it
3233-
auto trackParVarPos2 = getTrackParCov(trackPos2);
3234-
std::array dcaInfoPos2{trackPos2.dcaXY(), trackPos2.dcaZ()};
3235-
o2::base::Propagator::Instance()->propagateToDCABxByBz({collision.posX(), collision.posY(), collision.posZ()}, trackParVarPos2, 2.f, noMatCorr, &dcaInfoPos2);
3236-
getPxPyPz(trackParVarPos2, pVecTrackPos2);
3237-
}
3282+
3283+
const auto& trackGlobalIndexPos2 = softPionsPos[iPos2].trackGlobalIndex;
3284+
const auto& pVecTrackPos2 = softPionsPos[iPos2].pVec;
32383285

32393286
uint8_t isSelectedDstar{0};
32403287
uint8_t cutStatus{BIT(kNCutsDstar) - 1};
32413288
float deltaMass{-1.};
3242-
isSelectedDstar = applySelectionDstar(pVecTrackPos1, pVecTrackNeg1, pVecTrackPos2, cutStatus, deltaMass); // we do not compute the D* decay vertex at this stage because we are not interested in applying topological selections
3289+
isSelectedDstar = applySelectionDstar(pVecTrackPos1, pVecTrackNeg1, pVecTrackPos2, cutStatus, invMassD0, deltaMass); // we do not compute the D* decay vertex at this stage because we are not interested in applying topological selections
32433290
if (isSelectedDstar) {
3244-
rowTrackIndexDstar(thisCollId, trackPos2.globalIndex(), lastFilledD0);
3291+
rowTrackIndexDstar(thisCollId, trackGlobalIndexPos2, lastFilledD0);
32453292
if (config.fillHistograms) {
32463293
registry.fill(HIST("hMassDstarToD0Pi"), deltaMass);
32473294
}
@@ -3259,28 +3306,31 @@ struct HfTrackIndexSkimCreator {
32593306

32603307
// second loop over negative tracks
32613308
if (TESTBIT(whichHypo2Prong[kN2ProngDecays], 1) && (!config.applyKaonPidIn3Prongs || TESTBIT(trackIndexPos1.isIdentifiedPid(), ChannelKaonPid))) { // only for D0bar candidates; moreover if kaon PID enabled, apply to the positive track
3262-
if (!groupedTrackIndicesSoftPionsNeg) {
3309+
3310+
// Compute D0 invariant mass for all D* candidates
3311+
const std::array arrMomD0{pVecTrackNeg1, pVecTrackPos1};
3312+
const float invMassD0 = RecoDecay::m(arrMomD0, std::array{MassPiPlus, MassKPlus});
3313+
3314+
if (!softPiNegCacheFilled) {
32633315
groupedTrackIndicesSoftPionsNeg.emplace(negativeSoftPions->sliceByCached(aod::track::collisionId, collision.globalIndex(), cache));
3316+
fillPropagatedProngCache<true, TTracks>(collision, groupedTrackIndicesSoftPionsNeg, softPionsNeg);
3317+
softPiNegCacheFilled = true;
32643318
}
3265-
for (auto trackIndexNeg2 = groupedTrackIndicesSoftPionsNeg->begin(); trackIndexNeg2 != groupedTrackIndicesSoftPionsNeg->end(); ++trackIndexNeg2) {
3266-
if (trackIndexNeg1 == trackIndexNeg2) {
3319+
3320+
for (std::size_t iNeg2 = 0; iNeg2 < softPionsNeg.size(); ++iNeg2) {
3321+
if (trackIndexNeg1 == softPionsNeg[iNeg2].trackIndex) {
32673322
continue;
32683323
}
3269-
auto trackNeg2 = trackIndexNeg2.template track_as<TTracks>();
3270-
std::array pVecTrackNeg2{trackNeg2.pVector()};
3271-
if (thisCollId != trackNeg2.collisionId()) { // this is not the "default" collision for this track, we have to re-propagate it
3272-
auto trackParVarNeg2 = getTrackParCov(trackNeg2);
3273-
std::array dcaInfoNeg2{trackNeg2.dcaXY(), trackNeg2.dcaZ()};
3274-
o2::base::Propagator::Instance()->propagateToDCABxByBz({collision.posX(), collision.posY(), collision.posZ()}, trackParVarNeg2, 2.f, noMatCorr, &dcaInfoNeg2);
3275-
getPxPyPz(trackParVarNeg2, pVecTrackNeg2);
3276-
}
3324+
3325+
const auto& trackGlobalIndexNeg2 = softPionsNeg[iNeg2].trackGlobalIndex;
3326+
const auto& pVecTrackNeg2 = softPionsNeg[iNeg2].pVec;
32773327

32783328
uint8_t isSelectedDstar{0};
32793329
uint8_t cutStatus{BIT(kNCutsDstar) - 1};
32803330
float deltaMass{-1.};
3281-
isSelectedDstar = applySelectionDstar(pVecTrackNeg1, pVecTrackPos1, pVecTrackNeg2, cutStatus, deltaMass); // we do not compute the D* decay vertex at this stage because we are not interested in applying topological selections
3331+
isSelectedDstar = applySelectionDstar(pVecTrackNeg1, pVecTrackPos1, pVecTrackNeg2, cutStatus, invMassD0, deltaMass); // we do not compute the D* decay vertex at this stage because we are not interested in applying topological selections
32823332
if (isSelectedDstar) {
3283-
rowTrackIndexDstar(thisCollId, trackNeg2.globalIndex(), lastFilledD0);
3333+
rowTrackIndexDstar(thisCollId, trackGlobalIndexNeg2, lastFilledD0);
32843334
if (config.fillHistograms) {
32853335
registry.fill(HIST("hMassDstarToD0Pi"), deltaMass);
32863336
}

0 commit comments

Comments
 (0)