@@ -52,6 +52,7 @@ struct HistogramOptions : ConfigurableGroup {
5252 Configurable<int > cNbinsDiv{" cNbinsDiv" , 1 , " Integer to divide the number of bins" };
5353 Configurable<bool > additionalQAplots{" additionalQAplots" , true , " Additional QA plots" };
5454 Configurable<int > cfgTruthDebug{" cfgTruthDebug" , 0 , " Maximum logged matched candidates per truth channel" };
55+ Configurable<bool > cUseTruthRapidity{" cUseTruthRapidity" , true , " Require generated K1 rapidity in the configured window for MC efficiency numerators" };
5556};
5657
5758enum BinAnti : unsigned int {
@@ -231,12 +232,15 @@ struct K1AnalysisMicro {
231232 AxisSpec channelAxis = {3 , -0.5 , 2.5 , " 0: non-K1, 1: rho K, 2: K* pi" };
232233 histos.add (" MCReco/collisions" , " Selected reconstructed MC collisions" , HistType::kTH1D , {{1 , 0 , 1 }});
233234 histos.add (" MCReco/microTracks" , " Input micro tracks in selected MC collisions" , HistType::kTH1D , {{1 , 0 , 1 }});
234- histos.add (" MCReco/channel" , " All selected pi-pi-K combinations by truth channel" , HistType::kTH1D , {channelAxis});
235+ // These channel and pT histograms are pre-truth-fiducial QA; MCReco/response is the validated numerator.
236+ histos.add (" MCReco/channel" , " Pre-truth-fiducial QA: selected pi-pi-K combinations by truth channel" , HistType::kTH1D , {channelAxis});
235237 histos.add (" MCReco/mass" , " Reconstructed mass by truth channel" , HistType::kTH2D , {channelAxis, invMassAxisReso});
236- histos.add (" MCReco/pt" , " Reconstructed pT by truth channel" , HistType::kTH2D , {channelAxis, ptAxis});
238+ histos.add (" MCReco/pt" , " Pre-truth-fiducial QA: reconstructed pT by truth channel" , HistType::kTH2D , {channelAxis, ptAxis});
237239 histos.add (" MCReco/piPiMass" , " pi-pi mass by truth channel" , HistType::kTH2D , {channelAxis, invMassAxisRho});
238240 histos.add (" MCReco/pi1KMass" , " First pion-kaon mass by truth channel" , HistType::kTH2D , {channelAxis, invMassAxisK892});
239241 histos.add (" MCReco/pi2KMass" , " Second pion-kaon mass by truth channel" , HistType::kTH2D , {channelAxis, invMassAxisK892});
242+ histos.add (" MCReco/response" , " Selected MC candidates;reconstructed pT;generated pT;channel;charge;centrality" , HistType::kTHnSparseD ,
243+ {ptAxis, ptAxis, channelAxis, AxisSpec{2 , -1.5 , 1.5 , " K1 charge" }, centAxis});
240244 histos.add (" k1invmass_MC" , " Invariant mass of K1(1270)" , HistType::kTH1F , {invMassAxisReso});
241245 histos.add (" k1invmass_MC_noK1" , " Invariant mass of K1(1270)" , HistType::kTH1F , {invMassAxisReso});
242246
@@ -272,6 +276,8 @@ struct K1AnalysisMicro {
272276 AxisSpec channelAxis = {3 , -0.5 , 2.5 , " 0: other/unresolved, 1: rho K, 2: K* pi" };
273277 histos.add (" MCGen/chargeChannel" , " K1 parents in selected reconstructed events, inside the K1 rapidity window" , HistType::kTH2D , {{2 , -1.5 , 1.5 , " K1 charge" }, channelAxis});
274278 histos.add (" MCGen/ptChannel" , " Generated K1 pT by immediate decay channel" , HistType::kTH2D , {channelAxis, ptAxis});
279+ histos.add (" MCGen/response" , " Generated K1 parents;generated pT;channel;charge;centrality" , HistType::kTHnSparseD ,
280+ {ptAxis, channelAxis, AxisSpec{2 , -1.5 , 1.5 , " K1 charge" }, centAxis});
275281 }
276282 }
277283
@@ -380,7 +386,8 @@ struct K1AnalysisMicro {
380386 // (or one mixed pair of collisions). The selection itself is the shared K1 core.
381387 // dTracks1: bachelor kaons, dTracks2: pions.
382388 template <bool IsMC, bool IsMix, bool IsResoMicrotrack, typename CollisionType, typename TracksType>
383- void fillHistograms (const CollisionType& collision, const TracksType& dTracks1, const TracksType& dTracks2)
389+ void fillHistograms (const CollisionType& collision, const TracksType& dTracks1, const TracksType& dTracks2,
390+ const K1ParentTruthMap* parentTruth = nullptr )
384391 {
385392 const bool fillQA = !IsMix && histogramOptions.additionalQAplots ;
386393 const auto multiplicity = collision.cent ();
@@ -474,9 +481,17 @@ struct K1AnalysisMicro {
474481 pion1.motherPDG (), pion2.motherPDG (), kaon.motherPDG (),
475482 pion1.siblingIds ()[0 ], pion1.siblingIds ()[1 ], pion2.siblingIds ()[0 ], pion2.siblingIds ()[1 ], kaon.siblingIds ()[0 ], kaon.siblingIds ()[1 ]);
476483 }
477- typeK1 = kaon.sign () > 0 ? BinType::kK1P_Rec : BinType::kK1N_Rec ;
478- histos.fill (HIST (" hInvmass_K1" ), typeNormal, typeK1, multiplicity, c.k1 .Pt (), c.k1 .M ());
479- histos.fill (HIST (" k1invmass_MC" ), c.k1 .M ());
484+ const int motherId = k1MotherId (channel, kaon, pion1, pion2);
485+ const int charge = kaon.pdgCode () > 0 ? 1 : -1 ;
486+ const auto * parent = parentTruth ? findK1ParentTruth (*parentTruth, motherId, channel, charge) : nullptr ;
487+ const bool truthRapidity = c.isUnlikeSign && parent && (!histogramOptions.cUseTruthRapidity || (parent->y >= candidateCuts.cK1MinRap && parent->y <= candidateCuts.cK1MaxRap ));
488+ if (truthRapidity) {
489+ typeK1 = kaon.sign () > 0 ? BinType::kK1P_Rec : BinType::kK1N_Rec ;
490+ histos.fill (HIST (" hInvmass_K1" ), typeNormal, typeK1, multiplicity, c.k1 .Pt (), c.k1 .M ());
491+ histos.fill (HIST (" k1invmass_MC" ), c.k1 .M ());
492+ const int parentCharge = parent->pdgCode > 0 ? 1 : -1 ;
493+ histos.fill (HIST (" MCReco/response" ), c.k1 .Pt (), parent->pt , channelBin, parentCharge, multiplicity);
494+ }
480495 histos.fill (HIST (" QAMC/K1OA" ), c.angle );
481496 histos.fill (HIST (" QAMC/K1PairAsym" ), c.pairAsym );
482497 histos.fill (HIST (" QAMC/hInvmassK892_Rho" ), c.mass13 , c.secondary .M ());
@@ -515,17 +530,18 @@ struct K1AnalysisMicro {
515530 PROCESS_SWITCH (K1AnalysisMicro, processResoMicroTracks, " Process ResoMicroTracks" , true );
516531
517532 void processMC (ResoMCCols::iterator const & collision,
518- ResoMCTracks const & resotracks)
533+ ResoMCTracks const & resotracks, ResoMCParents const & resoParents )
519534 {
520535 if (!core.passesEventCuts (collision) || !core.passesMCEventCuts (collision)) {
521536 return ;
522537 }
523538 histos.fill (HIST (" MCReco/collisions" ), 0.5 );
524- fillHistograms<true , false , false >(collision, resotracks, resotracks);
539+ const auto parentTruth = makeK1ParentTruthMap (resoParents);
540+ fillHistograms<true , false , false >(collision, resotracks, resotracks, &parentTruth);
525541 }
526542 PROCESS_SWITCH (K1AnalysisMicro, processMC, " Process Event for MC" , false );
527543
528- void processMCMicro (ResoMCCols::iterator const & collision, ResoMCMicroTracks const & tracks)
544+ void processMCMicro (ResoMCCols::iterator const & collision, ResoMCMicroTracks const & tracks, ResoMCParents const & resoParents )
529545 {
530546 // The modular producer already selected these reconstructed collisions.
531547 // Apply precisely the same reconstruction loop as the data baseline.
@@ -534,7 +550,8 @@ struct K1AnalysisMicro {
534550 }
535551 histos.fill (HIST (" MCReco/collisions" ), 0.5 );
536552 histos.fill (HIST (" MCReco/microTracks" ), 0.5 , tracks.size ());
537- fillHistograms<true , false , true >(collision, tracks, tracks);
553+ const auto parentTruth = makeK1ParentTruthMap (resoParents);
554+ fillHistograms<true , false , true >(collision, tracks, tracks, &parentTruth);
538555 }
539556 PROCESS_SWITCH (K1AnalysisMicro, processMCMicro, " Process reconstructed MC with micro v001 tables" , false );
540557
@@ -548,6 +565,9 @@ struct K1AnalysisMicro {
548565 const int charge = part.pdgCode () > 0 ? 1 : -1 ;
549566 histos.fill (HIST (" MCGen/chargeChannel" ), charge, static_cast <int >(channel));
550567 histos.fill (HIST (" MCGen/ptChannel" ), static_cast <int >(channel), part.pt ());
568+ if (channel != K1TruthChannel::None) {
569+ histos.fill (HIST (" MCGen/response" ), part.pt (), static_cast <int >(channel), charge, collision.cent ());
570+ }
551571 });
552572 }
553573 PROCESS_SWITCH (K1AnalysisMicro, processMCTrue, " Process generated K1 in selected events with v001 parents" , false );
0 commit comments