Skip to content

Commit ab2b0ed

Browse files
committed
[PWGLF] Refine jet definition for generated particles and code optimization
1 parent 7c3d72f commit ab2b0ed

File tree

1 file changed

+140
-22
lines changed

1 file changed

+140
-22
lines changed

PWGLF/Tasks/Strangeness/strangenessInJets.cxx

Lines changed: 140 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -307,6 +307,7 @@ struct StrangenessInJets {
307307
}
308308
}
309309

310+
/*
310311
// Calculation of perpendicular axes
311312
void getPerpendicularAxis(TVector3 p, TVector3& u, double sign)
312313
{
@@ -370,6 +371,96 @@ struct StrangenessInJets {
370371
371372
return deltaPhi;
372373
}
374+
*/
375+
376+
// Check if particle is a physical primary or a decay product of a heavy-flavor hadron
377+
bool isPhysicalPrimaryOrFromHF(aod::McParticle const& particle, aod::McParticles const& mcParticles)
378+
{
379+
// Keep only pi, K, p, e, mu
380+
int pdg = std::abs(particle.pdgCode());
381+
if (!(pdg == PDG_t::kPiPlus || pdg == PDG_t::kKPlus || pdg == PDG_t::kProton || pdg == PDG_t::kElectron || pdg == PDG_t::kMuonMinus))
382+
return false;
383+
384+
// Constants for identifying heavy-flavor (charm and bottom) content from PDG codes
385+
static constexpr int kCharmQuark = 4;
386+
static constexpr int kBottomQuark = 5;
387+
static constexpr int hundreds = 100;
388+
static constexpr int thousands = 1000;
389+
390+
// Check if particle is from heavy-flavor decay
391+
bool fromHF = false;
392+
if (particle.has_mothers()) {
393+
auto mother = mcParticles.iteratorAt(particle.mothersIds()[0]);
394+
int motherPdg = std::abs(mother.pdgCode());
395+
fromHF = (motherPdg / hundreds == kCharmQuark || motherPdg / hundreds == kBottomQuark || motherPdg / thousands == kCharmQuark || motherPdg / thousands == kBottomQuark);
396+
}
397+
398+
// Select only physical primary particles or from heavy-flavor
399+
return (particle.isPhysicalPrimary() || fromHF);
400+
}
401+
402+
// Compute two transverse directions orthogonal to vector p
403+
void getPerpendicularDirections(const TVector3& p, TVector3& u1, TVector3& u2)
404+
{
405+
// Get momentum components
406+
double px = p.X();
407+
double py = p.Y();
408+
double pz = p.Z();
409+
410+
// Precompute squared terms
411+
double px2 = px * px;
412+
double py2 = py * py;
413+
double pz2 = pz * pz;
414+
double pz4 = pz2 * pz2;
415+
416+
// Case 1: vector along z-axis -> undefined perpendiculars
417+
if (px == 0 && py == 0) {
418+
u1.SetXYZ(0, 0, 0);
419+
u2.SetXYZ(0, 0, 0);
420+
return;
421+
}
422+
423+
// Case 2: px = 0 -> avoid division by zero
424+
if (px == 0 && py != 0) {
425+
double ux = std::sqrt(py2 - pz4 / py2);
426+
double uy = -pz2 / py;
427+
u1.SetXYZ(ux, uy, pz);
428+
u2.SetXYZ(-ux, uy, pz);
429+
return;
430+
}
431+
432+
// Case 3: py = 0 -> avoid division by zero
433+
if (py == 0 && px != 0) {
434+
double ux = -pz2 / px;
435+
double uy = std::sqrt(px2 - pz4 / px2);
436+
u1.SetXYZ(ux, uy, pz);
437+
u2.SetXYZ(ux, -uy, pz);
438+
return;
439+
}
440+
441+
// General case: solve quadratic for perpendicular vectors
442+
double a = px2 + py2;
443+
double b = 2.0 * px * pz2;
444+
double c = pz4 - py2 * py2 - px2 * py2;
445+
double delta = b * b - 4.0 * a * c;
446+
447+
// Invalid or degenerate solutions
448+
if (delta < 0 || a == 0) {
449+
u1.SetXYZ(0, 0, 0);
450+
u2.SetXYZ(0, 0, 0);
451+
return;
452+
}
453+
454+
// Solution 1
455+
double u1x = (-b + std::sqrt(delta)) / (2.0 * a);
456+
double u1y = (-pz2 - px * u1x) / py;
457+
u1.SetXYZ(u1x, u1y, pz);
458+
459+
// Solution 2
460+
double u2x = (-b - std::sqrt(delta)) / (2.0 * a);
461+
double u2y = (-pz2 - px * u2x) / py;
462+
u2.SetXYZ(u2x, u2y, pz);
463+
}
373464

374465
// Find ITS hit
375466
template <typename TrackIts>
@@ -879,10 +970,11 @@ struct StrangenessInJets {
879970

880971
// Calculation of perpendicular cones
881972
TVector3 jetAxis(jet.px(), jet.py(), jet.pz());
882-
TVector3 ueAxis1(0, 0, 0);
883-
TVector3 ueAxis2(0, 0, 0);
884-
getPerpendicularAxis(jetAxis, ueAxis1, +1);
885-
getPerpendicularAxis(jetAxis, ueAxis2, -1);
973+
TVector3 ueAxis1(0, 0, 0), ueAxis2(0, 0, 0);
974+
getPerpendicularDirections(jetAxis, ueAxis1, ueAxis2);
975+
if (ueAxis1.Mag() == 0 || ueAxis2.Mag() == 0) {
976+
continue;
977+
}
886978

887979
// Store jet and UE axes
888980
selectedJet.emplace_back(jetAxis);
@@ -1058,6 +1150,7 @@ struct StrangenessInJets {
10581150
}
10591151
PROCESS_SWITCH(StrangenessInJets, processData, "Process data", true);
10601152

1153+
// Define per-collision preslices for V0s, cascades, MC particles, and daughter tracks
10611154
Preslice<aod::V0Datas> perCollisionV0 = o2::aod::v0data::collisionId;
10621155
Preslice<aod::CascDataExt> perCollisionCasc = o2::aod::cascade::collisionId;
10631156
Preslice<aod::McParticles> perMCCollision = o2::aod::mcparticle::mcCollisionId;
@@ -1066,9 +1159,23 @@ struct StrangenessInJets {
10661159
// Generated MC events
10671160
void processMCgenerated(aod::McCollisions const& collisions, aod::McParticles const& mcParticles)
10681161
{
1162+
// Define per-event particle containers
1163+
std::vector<fastjet::PseudoJet> fjParticles;
1164+
std::vector<TVector3> strHadronMomentum;
1165+
std::vector<int> pdg;
1166+
1167+
// Jet and area definitions
1168+
fastjet::JetDefinition jetDef(fastjet::antikt_algorithm, rJet);
1169+
fastjet::AreaDefinition areaDef(fastjet::active_area, fastjet::GhostedAreaSpec(1.0));
1170+
10691171
// Loop over all simulated collision events
10701172
for (const auto& collision : collisions) {
10711173

1174+
// Clear containers at the start of the event loop
1175+
fjParticles.clear();
1176+
strHadronMomentum.clear();
1177+
pdg.clear();
1178+
10721179
// Fill event counter before any selection
10731180
registryMC.fill(HIST("number_of_events_mc_gen"), 0.5);
10741181

@@ -1088,15 +1195,13 @@ struct StrangenessInJets {
10881195
// MC particles per collision
10891196
auto mcParticlesPerColl = mcParticles.sliceBy(perMCCollision, collision.globalIndex());
10901197

1091-
// Store strange hadron pdg code and momentum
1092-
std::vector<int> pdg;
1093-
std::vector<TVector3> strHadronMomentum;
1094-
10951198
// Loop over all MC particles and select physical primaries within acceptance
1096-
std::vector<fastjet::PseudoJet> fjParticles;
10971199
for (const auto& particle : mcParticlesPerColl) {
1098-
if (!particle.isPhysicalPrimary())
1200+
1201+
// Select physical primary particles or HF decay products
1202+
if (!isPhysicalPrimaryOrFromHF(particle, mcParticles))
10991203
continue;
1204+
11001205
double minPtParticle = 0.1;
11011206
if (particle.eta() < etaMin || particle.eta() > etaMax || particle.pt() < minPtParticle)
11021207
continue;
@@ -1122,8 +1227,6 @@ struct StrangenessInJets {
11221227
registryMC.fill(HIST("number_of_events_mc_gen"), 3.5);
11231228

11241229
// Cluster MC particles into jets using anti-kt algorithm
1125-
fastjet::JetDefinition jetDef(fastjet::antikt_algorithm, rJet);
1126-
fastjet::AreaDefinition areaDef(fastjet::active_area, fastjet::GhostedAreaSpec(1.0));
11271230
fastjet::ClusterSequenceArea cs(fjParticles, jetDef, areaDef);
11281231
std::vector<fastjet::PseudoJet> jets = fastjet::sorted_by_pt(cs.inclusive_jets());
11291232

@@ -1150,8 +1253,10 @@ struct StrangenessInJets {
11501253
TVector3 jetAxis(jet.px(), jet.py(), jet.pz());
11511254
double coneRadius = std::sqrt(jet.area() / PI);
11521255
TVector3 ueAxis1(0, 0, 0), ueAxis2(0, 0, 0);
1153-
getPerpendicularAxis(jetAxis, ueAxis1, +1);
1154-
getPerpendicularAxis(jetAxis, ueAxis2, -1);
1256+
getPerpendicularDirections(jetAxis, ueAxis1, ueAxis2);
1257+
if (ueAxis1.Mag() == 0 || ueAxis2.Mag() == 0) {
1258+
continue;
1259+
}
11551260

11561261
// Loop over strange hadrons
11571262
int index = -1;
@@ -1327,8 +1432,25 @@ struct StrangenessInJets {
13271432
aod::V0Datas const& fullV0s, aod::CascDataExt const& Cascades,
13281433
const aod::McParticles&)
13291434
{
1435+
// Define per-event containers
1436+
std::vector<fastjet::PseudoJet> fjParticles;
1437+
std::vector<TVector3> selectedJet;
1438+
std::vector<TVector3> ue1;
1439+
std::vector<TVector3> ue2;
1440+
1441+
// Jet and area definitions
1442+
fastjet::JetDefinition jetDef(fastjet::antikt_algorithm, rJet);
1443+
fastjet::AreaDefinition areaDef(fastjet::active_area, fastjet::GhostedAreaSpec(1.0));
1444+
1445+
// Loop over reconstructed collisions
13301446
for (const auto& collision : collisions) {
13311447

1448+
// Clear containers at the start of the event loop
1449+
fjParticles.clear();
1450+
selectedJet.clear();
1451+
ue1.clear();
1452+
ue2.clear();
1453+
13321454
// Fill event counter before any selection
13331455
registryMC.fill(HIST("number_of_events_mc_rec"), 0.5);
13341456
if (!collision.sel8())
@@ -1351,7 +1473,6 @@ struct StrangenessInJets {
13511473
auto tracksPerColl = mcTracks.sliceBy(perCollisionTrk, collision.globalIndex());
13521474

13531475
// Loop over reconstructed tracks
1354-
std::vector<fastjet::PseudoJet> fjParticles;
13551476
for (auto const& track : tracksPerColl) {
13561477
if (!passedTrackSelectionForJetReconstruction(track))
13571478
continue;
@@ -1367,17 +1488,12 @@ struct StrangenessInJets {
13671488
registryMC.fill(HIST("number_of_events_mc_rec"), 3.5);
13681489

13691490
// Cluster particles using the anti-kt algorithm
1370-
fastjet::JetDefinition jetDef(fastjet::antikt_algorithm, rJet);
1371-
fastjet::AreaDefinition areaDef(fastjet::active_area, fastjet::GhostedAreaSpec(1.0));
13721491
fastjet::ClusterSequenceArea cs(fjParticles, jetDef, areaDef);
13731492
std::vector<fastjet::PseudoJet> jets = fastjet::sorted_by_pt(cs.inclusive_jets());
13741493
auto [rhoPerp, rhoMPerp] = backgroundSub.estimateRhoPerpCone(fjParticles, jets);
13751494

13761495
// Jet selection
13771496
bool isAtLeastOneJetSelected = false;
1378-
std::vector<TVector3> selectedJet;
1379-
std::vector<TVector3> ue1;
1380-
std::vector<TVector3> ue2;
13811497

13821498
// Loop over clustered jets
13831499
for (const auto& jet : jets) {
@@ -1396,8 +1512,10 @@ struct StrangenessInJets {
13961512
// Perpendicular cones
13971513
TVector3 jetAxis(jet.px(), jet.py(), jet.pz());
13981514
TVector3 ueAxis1(0, 0, 0), ueAxis2(0, 0, 0);
1399-
getPerpendicularAxis(jetAxis, ueAxis1, +1);
1400-
getPerpendicularAxis(jetAxis, ueAxis2, -1);
1515+
getPerpendicularDirections(jetAxis, ueAxis1, ueAxis2);
1516+
if (ueAxis1.Mag() == 0 || ueAxis2.Mag() == 0) {
1517+
continue;
1518+
}
14011519

14021520
// Store selected jet and UE cone axes
14031521
selectedJet.emplace_back(jetAxis);

0 commit comments

Comments
 (0)