Skip to content

Commit f642425

Browse files
author
Henrik Fribert
committed
Feature: Recalculation of Kink pT for better resolution
1 parent 93e4fbf commit f642425

File tree

3 files changed

+117
-12
lines changed

3 files changed

+117
-12
lines changed

PWGCF/Femto/Core/femtoUtils.h

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,96 @@ float qn(T const& col)
133133
return qn;
134134
}
135135

136+
/// Recalculate pT for Kinks (Sigmas) using kinematic constraints
137+
inline float calcPtnew(float pxMother, float pyMother, float pzMother, float pxDaughter, float pyDaughter, float pzDaughter)
138+
{
139+
// Particle masses in GeV/c^2
140+
const float massPion = 0.13957f;
141+
const float massNeutron = 0.93957f;
142+
const float massSigmaMinus = 1.19745f;
143+
144+
// Calculate mother momentum and direction versor
145+
float pMother = std::sqrt(pxMother * pxMother + pyMother * pyMother + pzMother * pzMother);
146+
if (pMother < 1e-6f)
147+
return -999.f;
148+
149+
float versorX = pxMother / pMother;
150+
float versorY = pyMother / pMother;
151+
float versorZ = pzMother / pMother;
152+
153+
// Calculate daughter energy
154+
float ePi = std::sqrt(massPion * massPion + pxDaughter * pxDaughter + pyDaughter * pyDaughter + pzDaughter * pzDaughter);
155+
156+
// Scalar product of versor with daughter momentum
157+
float a = versorX * pxDaughter + versorY * pyDaughter + versorZ * pzDaughter;
158+
159+
// Solve quadratic equation for momentum magnitude
160+
float K = massSigmaMinus * massSigmaMinus + massPion * massPion - massNeutron * massNeutron;
161+
float A = 4.f * (ePi * ePi - a * a);
162+
float B = -4.f * a * K;
163+
float C = 4.f * ePi * ePi * massSigmaMinus * massSigmaMinus - K * K;
164+
165+
if (std::abs(A) < 1e-6f)
166+
return -999.f;
167+
168+
float D = B * B - 4.f * A * C;
169+
if (D < 0.f)
170+
return -999.f;
171+
172+
float sqrtD = std::sqrt(D);
173+
float P1 = (-B + sqrtD) / (2.f * A);
174+
float P2 = (-B - sqrtD) / (2.f * A);
175+
176+
// Pick physical solution: prefer P2 if positive, otherwise P1
177+
if (P2 < 0.f && P1 < 0.f)
178+
return -999.f;
179+
if (P2 < 0.f)
180+
return P1;
181+
182+
// Choose solution closest to original momentum
183+
float p1Diff = std::abs(P1 - pMother);
184+
float p2Diff = std::abs(P2 - pMother);
185+
float P = (p1Diff < p2Diff) ? P1 : P2;
186+
187+
// Calculate pT from recalibrated momentum
188+
float pxS = versorX * P;
189+
float pyS = versorY * P;
190+
return std::sqrt(pxS * pxS + pyS * pyS);
191+
}
192+
193+
/// Helper function to calculate recalculated pT for kink particles (Sigma/SigmaPlus)
194+
template <typename TParticle, typename TTrackTable>
195+
float getRecalculatedPtForKink(const TParticle& particle, const TTrackTable& trackTable)
196+
{
197+
// Check if particle has chaDau index
198+
if constexpr (requires { particle.has_chaDau(); }) {
199+
if (particle.has_chaDau()) {
200+
try {
201+
auto chaDaughter = trackTable.rawIteratorAt(particle.chaDauId() - trackTable.offset());
202+
203+
// Extract momentum components directly from dynamic columns
204+
float pxDaug = chaDaughter.px();
205+
float pyDaug = chaDaughter.py();
206+
float pzDaug = chaDaughter.pz();
207+
208+
// Get momentum components from dynamic columns
209+
float pxMoth = particle.px();
210+
float pyMoth = particle.py();
211+
float pzMoth = particle.pz();
212+
213+
// Recalculate pT using kinematic constraints
214+
float ptRecalc = calcPtnew(pxMoth, pyMoth, pzMoth, pxDaug, pyDaug, pzDaug);
215+
if (ptRecalc > 0) {
216+
return ptRecalc;
217+
}
218+
} catch (const std::exception& e) {
219+
return -1.0f;
220+
}
221+
}
222+
}
223+
return -1.0f;
224+
}
225+
136226
inline bool enableTable(const char* tableName, int userSetting, o2::framework::InitContext& initContext)
137227
{
138228
if (userSetting == 1) {

PWGCF/Femto/Core/pairHistManager.h

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -334,12 +334,17 @@ class PairHistManager
334334
}
335335

336336
template <typename T1, typename T2>
337-
void setPair(const T1& particle1, const T2& particle2)
337+
void setPair(const T1& particle1, const T2& particle2, float pt1Recalc = -1.0f, float pt2Recalc = -1.0f)
338338
{
339339
// pt in track table is calculated from 1/signedPt from the original track table
340340
// in case of He with Z=2, we have to rescale the pt with the absolute charge
341-
mParticle1 = ROOT::Math::PtEtaPhiMVector(mAbsCharge1 * particle1.pt(), particle1.eta(), particle1.phi(), mPdgMass1);
342-
mParticle2 = ROOT::Math::PtEtaPhiMVector(mAbsCharge2 * particle2.pt(), particle2.eta(), particle2.phi(), mPdgMass2);
341+
342+
// Use recalculated pT if provided (for recalculated kink pT), otherwise use particle pT
343+
float pt1 = (pt1Recalc > 0.0f) ? pt1Recalc : particle1.pt();
344+
float pt2 = (pt2Recalc > 0.0f) ? pt2Recalc : particle2.pt();
345+
346+
mParticle1 = ROOT::Math::PtEtaPhiMVector(mAbsCharge1 * pt1, particle1.eta(), particle1.phi(), mPdgMass1);
347+
mParticle2 = ROOT::Math::PtEtaPhiMVector(mAbsCharge2 * pt2, particle2.eta(), particle2.phi(), mPdgMass2);
343348

344349
// set kT
345350
mKt = getKt(mParticle1, mParticle2);
@@ -363,17 +368,17 @@ class PairHistManager
363368
}
364369

365370
template <typename T1, typename T2, typename T3>
366-
void setPair(const T1& particle1, const T2& particle2, const T3& col)
371+
void setPair(const T1& particle1, const T2& particle2, const T3& col, float pt1Recalc = -1.0f, float pt2Recalc = -1.0f)
367372
{
368-
setPair(particle1, particle2);
373+
setPair(particle1, particle2, pt1Recalc, pt2Recalc);
369374
mMult = col.mult();
370375
mCent = col.cent();
371376
}
372377

373378
template <typename T1, typename T2, typename T3, typename T4>
374-
void setPair(const T1& particle1, const T2& particle2, const T3& col1, const T4& col2)
379+
void setPair(const T1& particle1, const T2& particle2, const T3& col1, const T4& col2, float pt1Recalc = -1.0f, float pt2Recalc = -1.0f)
375380
{
376-
setPair(particle1, particle2);
381+
setPair(particle1, particle2, pt1Recalc, pt2Recalc);
377382
mMult = 0.5f * (col1.mult() + col2.mult()); // if mixing with multiplicity, should be in the same mixing bin
378383
mCent = 0.5f * (col1.cent() + col2.cent()); // if mixing with centrality, should be in the same mixing bin
379384
}

PWGCF/Femto/Core/pairProcessHelpers.h

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818

1919
#include "PWGCF/Femto/Core/modes.h"
2020
#include "PWGCF/Femto/DataModel/FemtoTables.h"
21+
#include "PWGCF/Femto/Core/femtoUtils.h"
2122

2223
#include "Framework/ASoAHelpers.h"
2324

@@ -62,16 +63,19 @@ void processSameEvent(T1 const& SliceParticle,
6263
if (CprManager.isClosePair()) {
6364
continue;
6465
}
66+
// Calculate recalculated pT for kinks (if applicable)
67+
float pt1Recalc = o2::analysis::femto::utils::getRecalculatedPtForKink(p1, TrackTable);
68+
float pt2Recalc = o2::analysis::femto::utils::getRecalculatedPtForKink(p2, TrackTable);
6569
// Randomize pair order if enabled
6670
switch (pairOrder) {
6771
case kOrder12:
68-
PairHistManager.setPair(p1, p2, Collision);
72+
PairHistManager.setPair(p1, p2, Collision, pt1Recalc, pt2Recalc);
6973
break;
7074
case kOrder21:
71-
PairHistManager.setPair(p2, p1, Collision);
75+
PairHistManager.setPair(p2, p1, Collision, pt2Recalc, pt1Recalc);
7276
break;
7377
default:
74-
PairHistManager.setPair(p1, p2, Collision);
78+
PairHistManager.setPair(p1, p2, Collision, pt1Recalc, pt2Recalc);
7579
}
7680
// fill deta-dphi histograms with kstar cutoff
7781
CprManager.fill(PairHistManager.getKstar());
@@ -189,7 +193,10 @@ void processSameEvent(T1 const& SliceParticle1,
189193
if (CprManager.isClosePair()) {
190194
continue;
191195
}
192-
PairHistManager.setPair(p1, p2, Collision);
196+
// Calculate recalculated pT for kinks (if applicable)
197+
float pt1Recalc = o2::analysis::femto::utils::getRecalculatedPtForKink(p1, TrackTable);
198+
float pt2Recalc = o2::analysis::femto::utils::getRecalculatedPtForKink(p2, TrackTable);
199+
PairHistManager.setPair(p1, p2, Collision, pt1Recalc, pt2Recalc);
193200
CprManager.fill(PairHistManager.getKstar());
194201
if (PairHistManager.checkPairCuts()) {
195202
PairHistManager.template fill<mode>();
@@ -309,7 +316,10 @@ void processMixedEvent(T1 const& Collisions,
309316
if (CprManager.isClosePair()) {
310317
continue;
311318
}
312-
PairHistManager.setPair(p1, p2, collision1, collision2);
319+
// Calculate recalculated pT for kinks (if applicable)
320+
float pt1Recalc = o2::analysis::femto::utils::getRecalculatedPtForKink(p1, TrackTable);
321+
float pt2Recalc = o2::analysis::femto::utils::getRecalculatedPtForKink(p2, TrackTable);
322+
PairHistManager.setPair(p1, p2, collision1, collision2, pt1Recalc, pt2Recalc);
313323
CprManager.fill(PairHistManager.getKstar());
314324
if (PairHistManager.checkPairCuts()) {
315325
PairHistManager.template fill<mode>();

0 commit comments

Comments
 (0)