diff --git a/PWGCF/Femto/Core/collisionBuilder.h b/PWGCF/Femto/Core/collisionBuilder.h index 7bd147009e5..344bc562316 100644 --- a/PWGCF/Femto/Core/collisionBuilder.h +++ b/PWGCF/Femto/Core/collisionBuilder.h @@ -57,7 +57,7 @@ struct ConfCollisionFilters : o2::framework::ConfigurableGroup { o2::framework::Configurable sphericityMax{"sphericityMax", 1.f, "Maximum sphericity"}; o2::framework::Configurable magFieldMin{"magFieldMin", -5, "Minimum magnetic field strength (kG)"}; o2::framework::Configurable magFieldMax{"magFieldMax", 5, "Maximum magnetic field strength (kG)"}; - o2::framework::Configurable 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 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 { diff --git a/PWGCF/Femto/Core/dndetaBuilder.h b/PWGCF/Femto/Core/dndetaBuilder.h index 651960283fb..2404c573ec3 100644 --- a/PWGCF/Femto/Core/dndetaBuilder.h +++ b/PWGCF/Femto/Core/dndetaBuilder.h @@ -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 void processMc(T1 const& cols, T2 const& mcCols, @@ -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 selectedReco(nMcCols, -1); + std::vector hasSel8Reco(nMcCols, false); for (auto const& col : cols) { if (!col.has_fMcCol() || bestReco[static_cast(col.fMcColId())] != col.globalIndex()) { continue; } + if (isSelectedByMaskOnly(col)) { + hasSel8Reco[static_cast(col.fMcColId())] = true; + } if (!selectCollision(col, [&]() { return recoTrigger(col); })) { @@ -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) { @@ -324,13 +333,14 @@ class DndetaBuilder if (mUseGenTrigger && !genTrigger(mcCol)) { continue; } + const bool hasSel8RecoForLoss = hasSel8Reco[mcColIndex]; const auto mult = static_cast(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); } } } @@ -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 + 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 diff --git a/PWGCF/Femto/Core/trackBuilder.h b/PWGCF/Femto/Core/trackBuilder.h index eaf95a5c033..8150e840011 100644 --- a/PWGCF/Femto/Core/trackBuilder.h +++ b/PWGCF/Femto/Core/trackBuilder.h @@ -129,13 +129,13 @@ struct ConfTrackBits : o2::framework::ConfigurableGroup { }; // define the template structure for TrackSelection -template +template struct ConfTrackSelection : public o2::framework::ConfigurableGroup { std::string prefix = Prefix; // Unique prefix based on the template argument // configuration parameters o2::framework::Configurable pdgCodeAbs{"pdgCodeAbs", 2212, "Absolute value of PDG code. Set sign of charge to -1 for antiparticle."}; o2::framework::Configurable chargeAbs{"chargeAbs", 1, "Absolute value of charge (e.g. 1 for most tracks, 2 for He3)"}; - o2::framework::Configurable chargeSign{"chargeSign", 1, "Track charge sign: +1 for positive, -1 for negative, 0 for both"}; + o2::framework::Configurable chargeSign{"chargeSign", DefaultChargeSign, "Track charge sign: +1 for positive, -1 for negative, 0 for both"}; // filters for kinematics o2::framework::Configurable ptMin{"ptMin", 0.0f, "Minimum pT (GeV/c)"}; o2::framework::Configurable ptMax{"ptMax", 6.f, "Maximum pT (GeV/c)"}; @@ -170,8 +170,8 @@ using ConfTrackSelection1 = ConfTrackSelection; using ConfTrackSelection2 = ConfTrackSelection; using ConfTrackSelection3 = ConfTrackSelection; -using ConfTrackSelectionDndetaGlobal = ConfTrackSelection; -using ConfTrackSelectionDndetaItsOnly = ConfTrackSelection; +using ConfTrackSelectionDndetaGlobal = ConfTrackSelection; +using ConfTrackSelectionDndetaItsOnly = ConfTrackSelection; // 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