Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion PWGCF/Femto/Core/collisionBuilder.h
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ struct ConfCollisionFilters : o2::framework::ConfigurableGroup {
o2::framework::Configurable<float> sphericityMax{"sphericityMax", 1.f, "Maximum sphericity"};
o2::framework::Configurable<int> magFieldMin{"magFieldMin", -5, "Minimum magnetic field strength (kG)"};
o2::framework::Configurable<int> magFieldMax{"magFieldMax", 5, "Maximum magnetic field strength (kG)"};
o2::framework::Configurable<int> subGeneratorId{"subGeneratorId", 0, "MC ONLY: Sub-generator ID to keep (0 = MB). Only applied if >= 0; set to -1 (default) to disable and keep all sub-generators"};
o2::framework::Configurable<int> subGeneratorId{"subGeneratorId", -1, "MC ONLY: Sub-generator ID to keep (0 = MB). Only applied if >= 0; set to -1 (default) to disable and keep all sub-generators"};
};

struct ConfCollisionBits : o2::framework::ConfigurableGroup {
Expand Down
36 changes: 29 additions & 7 deletions PWGCF/Femto/Core/dndetaBuilder.h
Original file line number Diff line number Diff line change
Expand Up @@ -232,7 +232,8 @@ class DndetaBuilder
/// - reco: for every mc collision only the reconstructed collision with the most PV contributors is used
/// (emulates bestCollisionIndex); it has to pass the full event selection including the reco trigger
/// - gen: efficiency histograms for all generated collisions, loss histograms for the generated event class
/// (vertex z, optional INEL>0, optional generator-level trigger)
/// (optional INEL>0, optional generator-level trigger); the loss block's reco requirement is Sel8
/// only (no vtxZ, see isSelectedByMaskOnly), the vtxZ cut only gates the efficiency block above
template <typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename T8, typename T9, typename T10, typename T11>
void processMc(T1 const& cols,
T2 const& mcCols,
Expand Down Expand Up @@ -263,11 +264,20 @@ class DndetaBuilder
}

// reconstructed side
// selectedReco: full "selvtx" selection (Sel8 + |vtxZ| < cut + trigger), feeds the Gen-efficiency block (Ctrk)
// hasSel8Reco: "sel" selection (Sel8 only, no vtxZ, no trigger), feeds the event/signal loss block (Csel);
// per the analysis note, Csel's Gsel/Esel correspond to the Sel8 class only, Cvtx (the vtxZ-related bias) is
// not implemented (every Run3 event with a vertex is already within the stored range), so the loss-block
// reco requirement must not carry the vtxZ cut like the Ctrk-side "selvtx" one does
std::vector<int64_t> selectedReco(nMcCols, -1);
std::vector<bool> hasSel8Reco(nMcCols, false);
for (auto const& col : cols) {
if (!col.has_fMcCol() || bestReco[static_cast<std::size_t>(col.fMcColId())] != col.globalIndex()) {
continue;
}
if (isSelectedByMaskOnly(col)) {
hasSel8Reco[static_cast<std::size_t>(col.fMcColId())] = true;
}
if (!selectCollision(col, [&]() {
return recoTrigger(col);
})) {
Expand Down Expand Up @@ -300,13 +310,12 @@ class DndetaBuilder
}
}

// event and signal loss: generated event class, true centrality
// event and signal loss: generated event class (INEL or INEL>0), true centrality
// Gall/Gsel (and Eall/Esel) are defined by the analysis note without any vtxZ restriction - the vtxZ
// cut belongs only to Ctrk's "selvtx" quantities above, so it is intentionally not applied here
if (!mDoMcLoss) {
continue;
}
if (mcCol.posZ() < mVtxZMin || mcCol.posZ() > mVtxZMax) {
continue;
}
int nChMult = 0;
int nChEta1 = 0;
for (auto const& particle : particles) {
Expand All @@ -324,13 +333,14 @@ class DndetaBuilder
if (mUseGenTrigger && !genTrigger(mcCol)) {
continue;
}
const bool hasSel8RecoForLoss = hasSel8Reco[mcColIndex];
const auto mult = static_cast<float>(nChMult);
mHistManager.fillLossEvent(mcCol.cent(), mult, hasSelectedReco);
mHistManager.fillLossEvent(mcCol.cent(), mult, hasSel8RecoForLoss);
for (auto const& particle : particles) {
if (!isGenParticleSelected(particle, pdg)) {
continue;
}
mHistManager.fillLossParticle(particle.eta(), mcCol.cent(), mult, hasSelectedReco);
mHistManager.fillLossParticle(particle.eta(), mcCol.cent(), mult, hasSel8RecoForLoss);
}
}
}
Expand All @@ -353,6 +363,18 @@ class DndetaBuilder
LOG(info) << name << ": pT range " << conf.ptMin.value << " - " << conf.ptMax.value << " GeV/c, eta range " << conf.etaMin.value << " - " << conf.etaMax.value;
}

/// selected by maks only class (no vtxZ, no INEL>0, no trigger; pure predicate, no cutflow side effects), used to
/// build Gsel/Esel of the event/signal loss block - kept separate from selectCollision() below, whose
/// vtxZ-gated "selvtx" result must not be reused for the loss block (see processMc)
template <typename T>
bool isSelectedByMaskOnly(T const& col) const
{
return col.mult() >= mMultMin && col.mult() <= mMultMax &&
col.cent() >= mCentMin && col.cent() <= mCentMax &&
col.magField() >= mMagFieldMin && col.magField() <= mMagFieldMax &&
(col.mask() & mCollisionMask) == mCollisionMask;
}

/// event selection with cutflow; the trigger is evaluated last, so the trigger QA
/// only contains events that passed all other event selections
template <typename T1, typename T2>
Expand Down
8 changes: 4 additions & 4 deletions PWGCF/Femto/Core/trackBuilder.h
Original file line number Diff line number Diff line change
Expand Up @@ -129,13 +129,13 @@ struct ConfTrackBits : o2::framework::ConfigurableGroup {
};

// define the template structure for TrackSelection
template <auto& Prefix>
template <auto& Prefix, int DefaultChargeSign = 1>
struct ConfTrackSelection : public o2::framework::ConfigurableGroup {
std::string prefix = Prefix; // Unique prefix based on the template argument
// configuration parameters
o2::framework::Configurable<int> pdgCodeAbs{"pdgCodeAbs", 2212, "Absolute value of PDG code. Set sign of charge to -1 for antiparticle."};
o2::framework::Configurable<int> chargeAbs{"chargeAbs", 1, "Absolute value of charge (e.g. 1 for most tracks, 2 for He3)"};
o2::framework::Configurable<int> chargeSign{"chargeSign", 1, "Track charge sign: +1 for positive, -1 for negative, 0 for both"};
o2::framework::Configurable<int> chargeSign{"chargeSign", DefaultChargeSign, "Track charge sign: +1 for positive, -1 for negative, 0 for both"};
// filters for kinematics
o2::framework::Configurable<float> ptMin{"ptMin", 0.0f, "Minimum pT (GeV/c)"};
o2::framework::Configurable<float> ptMax{"ptMax", 6.f, "Maximum pT (GeV/c)"};
Expand Down Expand Up @@ -170,8 +170,8 @@ using ConfTrackSelection1 = ConfTrackSelection<PrefixTrackSelection1>;
using ConfTrackSelection2 = ConfTrackSelection<PrefixTrackSelection2>;
using ConfTrackSelection3 = ConfTrackSelection<PrefixTrackSelection3>;

using ConfTrackSelectionDndetaGlobal = ConfTrackSelection<PrefixTrackSelectionDndetaGlobal>;
using ConfTrackSelectionDndetaItsOnly = ConfTrackSelection<PrefixTrackSelectionDndetaItsOnly>;
using ConfTrackSelectionDndetaGlobal = ConfTrackSelection<PrefixTrackSelectionDndetaGlobal, 0>;
using ConfTrackSelectionDndetaItsOnly = ConfTrackSelection<PrefixTrackSelectionDndetaItsOnly, 0>;

// Track selection for resonance daughters (pion+/-, kaon+/-). Charge sign and abs charge are fixed
// by the species itself, so they are compile-time constants rather than configurables. No pdg code
Expand Down
Loading