@@ -232,7 +232,8 @@ class DndetaBuilder
232232 // / - reco: for every mc collision only the reconstructed collision with the most PV contributors is used
233233 // / (emulates bestCollisionIndex); it has to pass the full event selection including the reco trigger
234234 // / - gen: efficiency histograms for all generated collisions, loss histograms for the generated event class
235- // / (vertex z, optional INEL>0, optional generator-level trigger)
235+ // / (optional INEL>0, optional generator-level trigger); the loss block's reco requirement is Sel8
236+ // / only (no vtxZ, see isSelectedByMaskOnly), the vtxZ cut only gates the efficiency block above
236237 template <typename T1 , typename T2 , typename T3 , typename T4 , typename T5 , typename T6 , typename T7 , typename T8 , typename T9 , typename T10 , typename T11 >
237238 void processMc (T1 const & cols,
238239 T2 const & mcCols,
@@ -263,11 +264,20 @@ class DndetaBuilder
263264 }
264265
265266 // reconstructed side
267+ // selectedReco: full "selvtx" selection (Sel8 + |vtxZ| < cut + trigger), feeds the Gen-efficiency block (Ctrk)
268+ // hasSel8Reco: "sel" selection (Sel8 only, no vtxZ, no trigger), feeds the event/signal loss block (Csel);
269+ // per the analysis note, Csel's Gsel/Esel correspond to the Sel8 class only, Cvtx (the vtxZ-related bias) is
270+ // not implemented (every Run3 event with a vertex is already within the stored range), so the loss-block
271+ // reco requirement must not carry the vtxZ cut like the Ctrk-side "selvtx" one does
266272 std::vector<int64_t > selectedReco (nMcCols, -1 );
273+ std::vector<bool > hasSel8Reco (nMcCols, false );
267274 for (auto const & col : cols) {
268275 if (!col.has_fMcCol () || bestReco[static_cast <std::size_t >(col.fMcColId ())] != col.globalIndex ()) {
269276 continue ;
270277 }
278+ if (isSelectedByMaskOnly (col)) {
279+ hasSel8Reco[static_cast <std::size_t >(col.fMcColId ())] = true ;
280+ }
271281 if (!selectCollision (col, [&]() {
272282 return recoTrigger (col);
273283 })) {
@@ -300,13 +310,12 @@ class DndetaBuilder
300310 }
301311 }
302312
303- // event and signal loss: generated event class, true centrality
313+ // event and signal loss: generated event class (INEL or INEL>0), true centrality
314+ // Gall/Gsel (and Eall/Esel) are defined by the analysis note without any vtxZ restriction - the vtxZ
315+ // cut belongs only to Ctrk's "selvtx" quantities above, so it is intentionally not applied here
304316 if (!mDoMcLoss ) {
305317 continue ;
306318 }
307- if (mcCol.posZ () < mVtxZMin || mcCol.posZ () > mVtxZMax ) {
308- continue ;
309- }
310319 int nChMult = 0 ;
311320 int nChEta1 = 0 ;
312321 for (auto const & particle : particles) {
@@ -324,13 +333,14 @@ class DndetaBuilder
324333 if (mUseGenTrigger && !genTrigger (mcCol)) {
325334 continue ;
326335 }
336+ const bool hasSel8RecoForLoss = hasSel8Reco[mcColIndex];
327337 const auto mult = static_cast <float >(nChMult);
328- mHistManager .fillLossEvent (mcCol.cent (), mult, hasSelectedReco );
338+ mHistManager .fillLossEvent (mcCol.cent (), mult, hasSel8RecoForLoss );
329339 for (auto const & particle : particles) {
330340 if (!isGenParticleSelected (particle, pdg)) {
331341 continue ;
332342 }
333- mHistManager .fillLossParticle (particle.eta (), mcCol.cent (), mult, hasSelectedReco );
343+ mHistManager .fillLossParticle (particle.eta (), mcCol.cent (), mult, hasSel8RecoForLoss );
334344 }
335345 }
336346 }
@@ -353,6 +363,18 @@ class DndetaBuilder
353363 LOG (info) << name << " : pT range " << conf.ptMin .value << " - " << conf.ptMax .value << " GeV/c, eta range " << conf.etaMin .value << " - " << conf.etaMax .value ;
354364 }
355365
366+ // / selected by maks only class (no vtxZ, no INEL>0, no trigger; pure predicate, no cutflow side effects), used to
367+ // / build Gsel/Esel of the event/signal loss block - kept separate from selectCollision() below, whose
368+ // / vtxZ-gated "selvtx" result must not be reused for the loss block (see processMc)
369+ template <typename T>
370+ bool isSelectedByMaskOnly (T const & col) const
371+ {
372+ return col.mult () >= mMultMin && col.mult () <= mMultMax &&
373+ col.cent () >= mCentMin && col.cent () <= mCentMax &&
374+ col.magField () >= mMagFieldMin && col.magField () <= mMagFieldMax &&
375+ (col.mask () & mCollisionMask ) == mCollisionMask ;
376+ }
377+
356378 // / event selection with cutflow; the trigger is evaluated last, so the trigger QA
357379 // / only contains events that passed all other event selections
358380 template <typename T1 , typename T2 >
0 commit comments