From b47325717d5ba4c2f8b0671220229cf9541660b8 Mon Sep 17 00:00:00 2001 From: Daiki Sekihata Date: Sun, 23 Nov 2025 00:11:34 +0100 Subject: [PATCH 1/4] PWGEM/Dilepton: add flexbility to keep events with minNlepton --- PWGEM/Dilepton/TableProducer/filterEoI.cxx | 20 +- .../TableProducer/skimmerPrimaryElectron.cxx | 111 +++- .../TableProducer/skimmerPrimaryMuon.cxx | 536 ++++++++++++++---- 3 files changed, 544 insertions(+), 123 deletions(-) diff --git a/PWGEM/Dilepton/TableProducer/filterEoI.cxx b/PWGEM/Dilepton/TableProducer/filterEoI.cxx index 59dfbf07e0b..2300cbfb458 100644 --- a/PWGEM/Dilepton/TableProducer/filterEoI.cxx +++ b/PWGEM/Dilepton/TableProducer/filterEoI.cxx @@ -35,13 +35,21 @@ struct filterEoI { kElectronFromDalitz = 0x8, }; Produces emeoi; - // Configurable minNElectrons{"minNElectrons", 1, "min number of e+ or e- at midrapidity"}; - // Configurable minNMuons{"minNMuons", 1, "min number of mu+ or mu- at forward rapidity"}; - // Configurable minNV0s{"minNV0s", 1, "min number of v0 photons at midrapidity"}; + Configurable inheritFromOtherTask{"inheritFromOtherTask", true, "Flag to iherit all common configurables from skimmerPrimaryElectron or skimmerPrimaryMuon"}; + Configurable minNelectron{"minNelectron", -1, "min number of electron candidates per collision"}; + Configurable minNmuon{"minNmuon", -1, "min number of muon candidates per collision"}; HistogramRegistry fRegistry{"output"}; - void init(o2::framework::InitContext&) + void init(o2::framework::InitContext& initContext) { + if (inheritFromOtherTask.value) { // Inheriting from other task + getTaskOptionValue(initContext, "skimmer-primary-electron", "minNelectron", minNelectron.value, true); + getTaskOptionValue(initContext, "skimmer-primary-muon", "minNmuon", minNmuon.value, true); + } + + LOGF(info, "minNelectron = %d", minNelectron.value); + LOGF(info, "minNmuon = %d", minNmuon.value); + auto hEventCounter = fRegistry.add("hEventCounter", "hEventCounter", kTH1D, {{8, 0.5f, 8.5f}}); hEventCounter->GetXaxis()->SetBinLabel(1, "all"); hEventCounter->GetXaxis()->SetBinLabel(2, "event with electron"); @@ -71,14 +79,14 @@ struct filterEoI { if constexpr (static_cast(system & kElectron)) { auto electrons_coll = electrons.sliceBy(perCollision_el, collision.globalIndex()); - if (electrons_coll.size() >= 1) { + if (electrons_coll.size() >= minNelectron) { does_electron_exist = true; fRegistry.fill(HIST("hEventCounter"), 2); } } if constexpr (static_cast(system & kFwdMuon)) { auto muons_coll = muons.sliceBy(perCollision_mu, collision.globalIndex()); - if (muons_coll.size() >= 1) { + if (muons_coll.size() >= minNmuon) { does_fwdmuon_exist = true; fRegistry.fill(HIST("hEventCounter"), 3); } diff --git a/PWGEM/Dilepton/TableProducer/skimmerPrimaryElectron.cxx b/PWGEM/Dilepton/TableProducer/skimmerPrimaryElectron.cxx index 65a05e25c1d..44ee0441bc6 100644 --- a/PWGEM/Dilepton/TableProducer/skimmerPrimaryElectron.cxx +++ b/PWGEM/Dilepton/TableProducer/skimmerPrimaryElectron.cxx @@ -104,6 +104,7 @@ struct skimmerPrimaryElectron { Configurable maxpt_itssa{"maxpt_itssa", 0.15, "max pt for ITSsa track"}; Configurable maxMeanITSClusterSize{"maxMeanITSClusterSize", 16, "max x cos(lambda)"}; Configurable storeOnlyTrueElectronMC{"storeOnlyTrueElectronMC", false, "Flag to store only true electron in MC"}; + Configurable minNelectron{"minNelectron", 1, "min number of electron candidates per collision"}; // configuration for PID ML Configurable usePIDML{"usePIDML", false, "Flag to use PID ML"}; @@ -176,6 +177,7 @@ struct skimmerPrimaryElectron { fRegistry.add("Track/hMeanClusterSizeITSib", "mean cluster size ITSib;p_{pv} (GeV/c); #times cos(#lambda)", kTH2F, {{1000, 0, 10}, {150, 0, 15}}, false); fRegistry.add("Track/hMeanClusterSizeITSob", "mean cluster size ITSob;p_{pv} (GeV/c); #times cos(#lambda)", kTH2F, {{1000, 0, 10}, {150, 0, 15}}, false); fRegistry.add("Track/hProbElBDT", "probability to be e from BDT;p_{in} (GeV/c);BDT score;", kTH2F, {{1000, 0, 10}, {100, 0, 1}}, false); + fRegistry.add("Track/hNe", "electron counts;N_{e} per collision", kTH1F, {{51, -0.5, 50.5}}, false); } if (usePIDML) { @@ -498,7 +500,6 @@ struct skimmerPrimaryElectron { track.beta(), track.tofNSigmaEl(), /*track.tofNSigmaPi(), track.tofNSigmaKa(), track.tofNSigmaPr(),*/ track.itsClusterSizes(), track.itsChi2NCl(), track.tofChi2(), track.detectorMap(), - // trackParCov.getTgl(), isAssociatedToMPC, false, probaEl, mcTunedTPCSignal); emprimaryelectronscov( @@ -601,6 +602,9 @@ struct skimmerPrimaryElectron { Partition posTracks = o2::aod::track::signed1Pt > 0.f; Partition negTracks = o2::aod::track::signed1Pt < 0.f; + std::map, float> mapProbEl; // map pair(collisionId, trackId) -> probaEl + std::unordered_multimap multiMapTracksPerCollision; // collisionId -> trackIds + // ---------- for data ---------- void processRec_SA(MyCollisions const& collisions, aod::BCsWithTimestamps const&, MyFilteredTracks const& tracks) @@ -624,12 +628,26 @@ struct skimmerPrimaryElectron { if (!isElectron(collision, track, probaEl)) { continue; } - - fillTrackTable(collision, track, probaEl); + mapProbEl[std::make_pair(collision.globalIndex(), track.globalIndex())] = probaEl; + multiMapTracksPerCollision.insert(std::make_pair(collision.globalIndex(), track.globalIndex())); } + } // end of collision loop + for (const auto& collision : collisions) { + int count_electrons = multiMapTracksPerCollision.count(collision.globalIndex()); + fRegistry.fill(HIST("Track/hNe"), count_electrons); + + if (count_electrons >= minNelectron) { + auto range_electrons = multiMapTracksPerCollision.equal_range(collision.globalIndex()); + for (auto it = range_electrons.first; it != range_electrons.second; it++) { + auto track = tracks.rawIteratorAt(it->second); + fillTrackTable(collision, track, mapProbEl[std::make_pair(collision.globalIndex(), track.globalIndex())]); + } + } } // end of collision loop + mapProbEl.clear(); + multiMapTracksPerCollision.clear(); stored_trackIds.clear(); stored_trackIds.shrink_to_fit(); } @@ -658,10 +676,25 @@ struct skimmerPrimaryElectron { if (!isElectron(collision, track, probaEl)) { continue; } - fillTrackTable(collision, track, probaEl); + mapProbEl[std::make_pair(collision.globalIndex(), track.globalIndex())] = probaEl; + } + } // end of collision loop + + for (const auto& collision : collisions) { + int count_electrons = multiMapTracksPerCollision.count(collision.globalIndex()); + fRegistry.fill(HIST("Track/hNe"), count_electrons); + + if (count_electrons >= minNelectron) { + auto range_electrons = multiMapTracksPerCollision.equal_range(collision.globalIndex()); + for (auto it = range_electrons.first; it != range_electrons.second; it++) { + auto track = tracks.rawIteratorAt(it->second); + fillTrackTable(collision, track, mapProbEl[std::make_pair(collision.globalIndex(), track.globalIndex())]); + } } } // end of collision loop + mapProbEl.clear(); + multiMapTracksPerCollision.clear(); stored_trackIds.clear(); stored_trackIds.shrink_to_fit(); } @@ -692,11 +725,26 @@ struct skimmerPrimaryElectron { if (!isElectron(collision, track, probaEl)) { continue; } - fillTrackTable(collision, track, probaEl); + mapProbEl[std::make_pair(collision.globalIndex(), track.globalIndex())] = probaEl; } } // end of collision loop + for (const auto& collision : collisions) { + int count_electrons = multiMapTracksPerCollision.count(collision.globalIndex()); + fRegistry.fill(HIST("Track/hNe"), count_electrons); + + if (count_electrons >= minNelectron) { + auto range_electrons = multiMapTracksPerCollision.equal_range(collision.globalIndex()); + for (auto it = range_electrons.first; it != range_electrons.second; it++) { + auto track = tracks.rawIteratorAt(it->second); + fillTrackTable(collision, track, mapProbEl[std::make_pair(collision.globalIndex(), track.globalIndex())]); + } + } + } // end of collision loop + + mapProbEl.clear(); + multiMapTracksPerCollision.clear(); stored_trackIds.clear(); stored_trackIds.shrink_to_fit(); } @@ -728,10 +776,25 @@ struct skimmerPrimaryElectron { if (!isElectron(collision, track, probaEl)) { continue; } - fillTrackTable(collision, track, probaEl); + mapProbEl[std::make_pair(collision.globalIndex(), track.globalIndex())] = probaEl; } } // end of collision loop + for (const auto& collision : collisions) { + int count_electrons = multiMapTracksPerCollision.count(collision.globalIndex()); + fRegistry.fill(HIST("Track/hNe"), count_electrons); + + if (count_electrons >= minNelectron) { + auto range_electrons = multiMapTracksPerCollision.equal_range(collision.globalIndex()); + for (auto it = range_electrons.first; it != range_electrons.second; it++) { + auto track = tracks.rawIteratorAt(it->second); + fillTrackTable(collision, track, mapProbEl[std::make_pair(collision.globalIndex(), track.globalIndex())]); + } + } + } // end of collision loop + + mapProbEl.clear(); + multiMapTracksPerCollision.clear(); stored_trackIds.clear(); stored_trackIds.shrink_to_fit(); } @@ -766,10 +829,25 @@ struct skimmerPrimaryElectron { if (!isElectron(collision, track, probaEl)) { continue; } - fillTrackTable(collision, track, probaEl); + mapProbEl[std::make_pair(collision.globalIndex(), track.globalIndex())] = probaEl; } } // end of collision loop + for (const auto& collision : collisions) { + int count_electrons = multiMapTracksPerCollision.count(collision.globalIndex()); + fRegistry.fill(HIST("Track/hNe"), count_electrons); + + if (count_electrons >= minNelectron) { + auto range_electrons = multiMapTracksPerCollision.equal_range(collision.globalIndex()); + for (auto it = range_electrons.first; it != range_electrons.second; it++) { + auto track = tracks.rawIteratorAt(it->second); + fillTrackTable(collision, track, mapProbEl[std::make_pair(collision.globalIndex(), track.globalIndex())]); + } + } + } // end of collision loop + + mapProbEl.clear(); + multiMapTracksPerCollision.clear(); stored_trackIds.clear(); stored_trackIds.shrink_to_fit(); } @@ -801,10 +879,25 @@ struct skimmerPrimaryElectron { if (!isElectron(collision, track, probaEl)) { continue; } - fillTrackTable(collision, track, probaEl); + mapProbEl[std::make_pair(collision.globalIndex(), track.globalIndex())] = probaEl; + } + } // end of collision loop + + for (const auto& collision : collisions) { + int count_electrons = multiMapTracksPerCollision.count(collision.globalIndex()); + fRegistry.fill(HIST("Track/hNe"), count_electrons); + + if (count_electrons >= minNelectron) { + auto range_electrons = multiMapTracksPerCollision.equal_range(collision.globalIndex()); + for (auto it = range_electrons.first; it != range_electrons.second; it++) { + auto track = tracks.rawIteratorAt(it->second); + fillTrackTable(collision, track, mapProbEl[std::make_pair(collision.globalIndex(), track.globalIndex())]); + } } } // end of collision loop + mapProbEl.clear(); + multiMapTracksPerCollision.clear(); stored_trackIds.clear(); stored_trackIds.shrink_to_fit(); } @@ -882,7 +975,7 @@ struct prefilterPrimaryElectron { fRegistry.add("Track/hEtaPhi", "#eta vs. #varphi;#varphi (rad.);#eta", kTH2F, {{90, 0, 2 * M_PI}, {80, -2.0f, 2.0f}}, false); fRegistry.add("Track/hTPCNsigmaEl", "loose track TPC PID", kTH2F, {{1000, 0.f, 10}, {100, -5, +5}}); fRegistry.add("Pair/before/uls/hMvsPt", "mass vs. pT;m_{ee} (GeV/c^{2});p_{T,ee} (GeV/c)", kTH2F, {{500, 0, 0.5}, {100, 0, 1}}); - fRegistry.add("Pair/before/uls/hMvsPhiV", "mass vs. phiv;#varphi_{V} (rad.);m_{ee} (GeV/c^{2})", kTH2F, {{90, 0.f, M_PI}, {100, 0, 1.0}}); + fRegistry.add("Pair/before/uls/hMvsPhiV", "mass vs. phiv;#varphi_{V} (rad.);m_{ee} (GeV/c^{2})", kTH2F, {{90, 0.f, M_PI}, {100, 0, 0.1}}); fRegistry.addClone("Pair/before/uls/", "Pair/before/lspp/"); fRegistry.addClone("Pair/before/uls/", "Pair/before/lsmm/"); fRegistry.addClone("Pair/before/", "Pair/after/"); diff --git a/PWGEM/Dilepton/TableProducer/skimmerPrimaryMuon.cxx b/PWGEM/Dilepton/TableProducer/skimmerPrimaryMuon.cxx index d03e0907811..035a52f41eb 100644 --- a/PWGEM/Dilepton/TableProducer/skimmerPrimaryMuon.cxx +++ b/PWGEM/Dilepton/TableProducer/skimmerPrimaryMuon.cxx @@ -89,6 +89,7 @@ struct skimmerPrimaryMuon { Configurable maxChi2GL{"maxChi2GL", 10, "max. chi2 for global muon"}; Configurable refitGlobalMuon{"refitGlobalMuon", true, "flag to refit global muon"}; Configurable matchingZ{"matchingZ", -77.5, "z position where matching is performed"}; + Configurable minNmuon{"minNmuon", 1, "min number of muon candidates per collision"}; o2::ccdb::CcdbApi ccdbApi; Service ccdb; @@ -166,6 +167,7 @@ struct skimmerPrimaryMuon { fRegistry.add("MFTMCHMID/hDCAxy", "DCAxy;DCA_{xy} (cm);", kTH1F, {{100, 0, 1}}, false); fRegistry.add("MFTMCHMID/hDCAxyz", "DCA xy vs. z;DCA_{xy} (cm);DCA_{z} (cm)", kTH2F, {{100, 0, 1}, {200, -0.1, 0.1}}, false); fRegistry.add("MFTMCHMID/hDCAxyinSigma", "DCAxy in sigma;DCA_{xy} (#sigma);", kTH1F, {{100, 0, 10}}, false); + fRegistry.add("MFTMCHMID/hNmu", "#mu multiplicity;N_{#mu} per collision", kTH1F, {{21, -0.5, 20.5}}, false); fRegistry.addClone("MFTMCHMID/", "MCHMID/"); fRegistry.add("MFTMCHMID/hDCAxResolutionvsPt", "DCA_{x} vs. p_{T};p_{T} (GeV/c);DCA_{x} resolution (#mum);", kTH2F, {{100, 0, 10.f}, {500, 0, 500}}, false); fRegistry.add("MFTMCHMID/hDCAyResolutionvsPt", "DCA_{y} vs. p_{T};p_{T} (GeV/c);DCA_{y} resolution (#mum);", kTH2F, {{100, 0, 10.f}, {500, 0, 500}}, false); @@ -214,19 +216,19 @@ struct skimmerPrimaryMuon { return true; } - template - void fillFwdTrackTable(TCollision const& collision, TFwdTrack fwdtrack, TMFTTracksCov const& mftCovs, const bool isAmbiguous) + template + bool fillFwdTrackTable(TCollision const& collision, TFwdTrack fwdtrack, TMFTTracksCov const& mftCovs, const bool isAmbiguous) { if (fwdtrack.trackType() == o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack && fwdtrack.chi2MatchMCHMFT() > maxMatchingChi2MCHMFT) { - return; + return false; } // Users have to decide the best match between MFT and MCH-MID at analysis level. The same global muon is repeatedly stored. if (fwdtrack.chi2MatchMCHMID() < 0.f) { // this should never happen. only for protection. - return; + return false; } if (fwdtrack.chi2() < 0.f) { // this should never happen. only for protection. - return; + return false; } o2::dataformats::GlobalFwdTrack propmuonAtPV = propagateMuon(fwdtrack, fwdtrack, collision, propagationPoint::kToVertex, matchingZ, mBz); @@ -276,12 +278,12 @@ struct skimmerPrimaryMuon { if (fwdtrack.trackType() == o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack) { // apply r-absorber cut here to minimize the number of calling propagateMuon. if (fwdtrack.rAtAbsorberEnd() < minRabsGL || maxRabs < fwdtrack.rAtAbsorberEnd()) { - return; + return false; } // apply dca cut here to minimize the number of calling propagateMuon. if (maxDCAxy < dcaXY) { - return; + return false; } auto mchtrack = fwdtrack.template matchMCHTrack_as(); // MCH-MID @@ -289,7 +291,7 @@ struct skimmerPrimaryMuon { if constexpr (isMC) { if (!mfttrack.has_mcParticle()) { - return; + return false; } } @@ -302,7 +304,7 @@ struct skimmerPrimaryMuon { // apply chi2/ndf cut here to minimize the number of calling propagateMuon. if (maxChi2GL < fwdtrack.chi2() / ndf_mchmft) { - return; + return false; } o2::dataformats::GlobalFwdTrack propmuonAtPV_Matched = propagateMuon(mchtrack, mchtrack, collision, propagationPoint::kToVertex, matchingZ, mBz); @@ -382,103 +384,106 @@ struct skimmerPrimaryMuon { } sigma_dcaXY = dcaXY / dcaXYinSigma; } else { - return; + return false; } if (!isSelected(pt, eta, rAtAbsorberEnd, pDCA, fwdtrack.chi2() / ndf_mchmft, fwdtrack.trackType(), dcaXY)) { - return; + return false; } - float dpt = (ptMatchedMCHMID - pt) / pt; - float deta = etaMatchedMCHMID - eta; - float dphi = phiMatchedMCHMID - phi; - o2::math_utils::bringToPMPi(dphi); - - float detaMP = etaMatchedMCHMIDatMP - etaMatchedMFTatMP; - float dphiMP = phiMatchedMCHMIDatMP - phiMatchedMFTatMP; - o2::math_utils::bringToPMPi(dphiMP); - - bool isAssociatedToMPC = fwdtrack.collisionId() == collision.globalIndex(); - // LOGF(info, "isAmbiguous = %d, isAssociatedToMPC = %d, fwdtrack.globalIndex() = %d, fwdtrack.collisionId() = %d, collision.globalIndex() = %d", isAmbiguous, isAssociatedToMPC, fwdtrack.globalIndex(), fwdtrack.collisionId(), collision.globalIndex()); - - emprimarymuons(collision.globalIndex(), fwdtrack.globalIndex(), fwdtrack.matchMFTTrackId(), fwdtrack.matchMCHTrackId(), fwdtrack.trackType(), - pt, eta, phi, fwdtrack.sign(), dcaX, dcaY, cXX, cYY, cXY, ptMatchedMCHMID, etaMatchedMCHMID, phiMatchedMCHMID, - etaMatchedMCHMIDatMP, phiMatchedMCHMIDatMP, etaMatchedMFTatMP, phiMatchedMFTatMP, - fwdtrack.nClusters(), pDCA, rAtAbsorberEnd, fwdtrack.chi2(), fwdtrack.chi2MatchMCHMID(), fwdtrack.chi2MatchMCHMFT(), - fwdtrack.mchBitMap(), fwdtrack.midBitMap(), fwdtrack.midBoards(), mftClusterSizesAndTrackFlags, chi2mft, isAssociatedToMPC, isAmbiguous); - - const auto& fwdcov = propmuonAtPV.getCovariances(); // covatiance matrix at PV - emprimarymuonscov( - fwdcov(0, 0), - fwdcov(0, 1), fwdcov(1, 1), - fwdcov(2, 0), fwdcov(2, 1), fwdcov(2, 2), - fwdcov(3, 0), fwdcov(3, 1), fwdcov(3, 2), fwdcov(3, 3), - fwdcov(4, 0), fwdcov(4, 1), fwdcov(4, 2), fwdcov(4, 3), fwdcov(4, 4)); - - // See definition DataFormats/Reconstruction/include/ReconstructionDataFormats/TrackFwd.h - // Covariance matrix of track parameters, ordered as follows: - // - // - // - // - // - - if (fillQAHistograms) { - fRegistry.fill(HIST("hMuonType"), fwdtrack.trackType()); - if (fwdtrack.trackType() == o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack) { - fRegistry.fill(HIST("MFTMCHMID/hPt"), pt); - fRegistry.fill(HIST("MFTMCHMID/hEtaPhi"), phi, eta); - fRegistry.fill(HIST("MFTMCHMID/hEtaPhi_MatchedMCHMID"), phiMatchedMCHMID, etaMatchedMCHMID); - fRegistry.fill(HIST("MFTMCHMID/hDeltaPt_Pt"), pt, dpt); - fRegistry.fill(HIST("MFTMCHMID/hDeltaEta_Pt"), pt, deta); - fRegistry.fill(HIST("MFTMCHMID/hDeltaPhi_Pt"), pt, dphi); - fRegistry.fill(HIST("MFTMCHMID/hDeltaEtaAtMP_Pt"), pt, detaMP); - fRegistry.fill(HIST("MFTMCHMID/hDeltaPhiAtMP_Pt"), pt, dphiMP); - fRegistry.fill(HIST("MFTMCHMID/hSign"), fwdtrack.sign()); - fRegistry.fill(HIST("MFTMCHMID/hNclusters"), fwdtrack.nClusters()); - fRegistry.fill(HIST("MFTMCHMID/hNclustersMFT"), nClustersMFT); - fRegistry.fill(HIST("MFTMCHMID/hPDCA_Rabs"), rAtAbsorberEnd, pDCA); - fRegistry.fill(HIST("MFTMCHMID/hRatAbsorberEnd"), rAtAbsorberEnd); - fRegistry.fill(HIST("MFTMCHMID/hChi2"), fwdtrack.chi2() / ndf_mchmft); - fRegistry.fill(HIST("MFTMCHMID/hChi2MFT"), chi2mft / ndf_mft); - fRegistry.fill(HIST("MFTMCHMID/hChi2MatchMCHMID"), fwdtrack.chi2MatchMCHMID()); - fRegistry.fill(HIST("MFTMCHMID/hChi2MatchMCHMFT"), fwdtrack.chi2MatchMCHMFT()); - fRegistry.fill(HIST("MFTMCHMID/hDCAxy2D"), dcaX, dcaY); - fRegistry.fill(HIST("MFTMCHMID/hDCAxy2DinSigma"), dcaX / std::sqrt(cXX), dcaY / std::sqrt(cYY)); - fRegistry.fill(HIST("MFTMCHMID/hDCAxy"), dcaXY); - fRegistry.fill(HIST("MFTMCHMID/hDCAxyz"), dcaXY, dcaZ); - fRegistry.fill(HIST("MFTMCHMID/hDCAxyinSigma"), dcaXYinSigma); - fRegistry.fill(HIST("MFTMCHMID/hDCAxResolutionvsPt"), pt, std::sqrt(cXX) * 1e+4); // convert cm to um - fRegistry.fill(HIST("MFTMCHMID/hDCAyResolutionvsPt"), pt, std::sqrt(cYY) * 1e+4); // convert cm to um - fRegistry.fill(HIST("MFTMCHMID/hDCAxyResolutionvsPt"), pt, sigma_dcaXY * 1e+4); // convert cm to um - } else if (fwdtrack.trackType() == o2::aod::fwdtrack::ForwardTrackTypeEnum::MuonStandaloneTrack) { - fRegistry.fill(HIST("MCHMID/hPt"), pt); - fRegistry.fill(HIST("MCHMID/hEtaPhi"), phi, eta); - fRegistry.fill(HIST("MCHMID/hEtaPhi_MatchedMCHMID"), phiMatchedMCHMID, etaMatchedMCHMID); - fRegistry.fill(HIST("MCHMID/hDeltaPt_Pt"), pt, dpt); - fRegistry.fill(HIST("MCHMID/hDeltaEta_Pt"), pt, deta); - fRegistry.fill(HIST("MCHMID/hDeltaPhi_Pt"), pt, dphi); - fRegistry.fill(HIST("MCHMID/hDeltaEtaAtMP_Pt"), pt, detaMP); - fRegistry.fill(HIST("MCHMID/hDeltaPhiAtMP_Pt"), pt, dphiMP); - fRegistry.fill(HIST("MCHMID/hSign"), fwdtrack.sign()); - fRegistry.fill(HIST("MCHMID/hNclusters"), fwdtrack.nClusters()); - fRegistry.fill(HIST("MCHMID/hNclustersMFT"), nClustersMFT); - fRegistry.fill(HIST("MCHMID/hPDCA_Rabs"), rAtAbsorberEnd, pDCA); - fRegistry.fill(HIST("MCHMID/hRatAbsorberEnd"), rAtAbsorberEnd); - fRegistry.fill(HIST("MCHMID/hChi2"), fwdtrack.chi2()); - fRegistry.fill(HIST("MCHMID/hChi2MFT"), chi2mft / ndf_mft); - fRegistry.fill(HIST("MCHMID/hChi2MatchMCHMID"), fwdtrack.chi2MatchMCHMID()); - fRegistry.fill(HIST("MCHMID/hChi2MatchMCHMFT"), fwdtrack.chi2MatchMCHMFT()); - fRegistry.fill(HIST("MCHMID/hDCAxy2D"), dcaX, dcaY); - fRegistry.fill(HIST("MCHMID/hDCAxy2DinSigma"), dcaX / std::sqrt(cXX), dcaY / std::sqrt(cYY)); - fRegistry.fill(HIST("MCHMID/hDCAxy"), dcaXY); - fRegistry.fill(HIST("MCHMID/hDCAxyz"), dcaXY, dcaZ); - fRegistry.fill(HIST("MCHMID/hDCAxyinSigma"), dcaXYinSigma); - fRegistry.fill(HIST("MCHMID/hDCAxResolutionvsPt"), pt, std::sqrt(cXX) * 1e+4); // convert cm to um - fRegistry.fill(HIST("MCHMID/hDCAyResolutionvsPt"), pt, std::sqrt(cYY) * 1e+4); // convert cm to um - fRegistry.fill(HIST("MCHMID/hDCAxyResolutionvsPt"), pt, sigma_dcaXY * 1e+4); // convert cm to um + if constexpr (fillTable) { + float dpt = (ptMatchedMCHMID - pt) / pt; + float deta = etaMatchedMCHMID - eta; + float dphi = phiMatchedMCHMID - phi; + o2::math_utils::bringToPMPi(dphi); + + float detaMP = etaMatchedMCHMIDatMP - etaMatchedMFTatMP; + float dphiMP = phiMatchedMCHMIDatMP - phiMatchedMFTatMP; + o2::math_utils::bringToPMPi(dphiMP); + + bool isAssociatedToMPC = fwdtrack.collisionId() == collision.globalIndex(); + // LOGF(info, "isAmbiguous = %d, isAssociatedToMPC = %d, fwdtrack.globalIndex() = %d, fwdtrack.collisionId() = %d, collision.globalIndex() = %d", isAmbiguous, isAssociatedToMPC, fwdtrack.globalIndex(), fwdtrack.collisionId(), collision.globalIndex()); + + emprimarymuons(collision.globalIndex(), fwdtrack.globalIndex(), fwdtrack.matchMFTTrackId(), fwdtrack.matchMCHTrackId(), fwdtrack.trackType(), + pt, eta, phi, fwdtrack.sign(), dcaX, dcaY, cXX, cYY, cXY, ptMatchedMCHMID, etaMatchedMCHMID, phiMatchedMCHMID, + etaMatchedMCHMIDatMP, phiMatchedMCHMIDatMP, etaMatchedMFTatMP, phiMatchedMFTatMP, + fwdtrack.nClusters(), pDCA, rAtAbsorberEnd, fwdtrack.chi2(), fwdtrack.chi2MatchMCHMID(), fwdtrack.chi2MatchMCHMFT(), + fwdtrack.mchBitMap(), fwdtrack.midBitMap(), fwdtrack.midBoards(), mftClusterSizesAndTrackFlags, chi2mft, isAssociatedToMPC, isAmbiguous); + + const auto& fwdcov = propmuonAtPV.getCovariances(); // covatiance matrix at PV + emprimarymuonscov( + fwdcov(0, 0), + fwdcov(0, 1), fwdcov(1, 1), + fwdcov(2, 0), fwdcov(2, 1), fwdcov(2, 2), + fwdcov(3, 0), fwdcov(3, 1), fwdcov(3, 2), fwdcov(3, 3), + fwdcov(4, 0), fwdcov(4, 1), fwdcov(4, 2), fwdcov(4, 3), fwdcov(4, 4)); + + // See definition DataFormats/Reconstruction/include/ReconstructionDataFormats/TrackFwd.h + // Covariance matrix of track parameters, ordered as follows: + // + // + // + // + // + + if (fillQAHistograms) { + fRegistry.fill(HIST("hMuonType"), fwdtrack.trackType()); + if (fwdtrack.trackType() == o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack) { + fRegistry.fill(HIST("MFTMCHMID/hPt"), pt); + fRegistry.fill(HIST("MFTMCHMID/hEtaPhi"), phi, eta); + fRegistry.fill(HIST("MFTMCHMID/hEtaPhi_MatchedMCHMID"), phiMatchedMCHMID, etaMatchedMCHMID); + fRegistry.fill(HIST("MFTMCHMID/hDeltaPt_Pt"), pt, dpt); + fRegistry.fill(HIST("MFTMCHMID/hDeltaEta_Pt"), pt, deta); + fRegistry.fill(HIST("MFTMCHMID/hDeltaPhi_Pt"), pt, dphi); + fRegistry.fill(HIST("MFTMCHMID/hDeltaEtaAtMP_Pt"), pt, detaMP); + fRegistry.fill(HIST("MFTMCHMID/hDeltaPhiAtMP_Pt"), pt, dphiMP); + fRegistry.fill(HIST("MFTMCHMID/hSign"), fwdtrack.sign()); + fRegistry.fill(HIST("MFTMCHMID/hNclusters"), fwdtrack.nClusters()); + fRegistry.fill(HIST("MFTMCHMID/hNclustersMFT"), nClustersMFT); + fRegistry.fill(HIST("MFTMCHMID/hPDCA_Rabs"), rAtAbsorberEnd, pDCA); + fRegistry.fill(HIST("MFTMCHMID/hRatAbsorberEnd"), rAtAbsorberEnd); + fRegistry.fill(HIST("MFTMCHMID/hChi2"), fwdtrack.chi2() / ndf_mchmft); + fRegistry.fill(HIST("MFTMCHMID/hChi2MFT"), chi2mft / ndf_mft); + fRegistry.fill(HIST("MFTMCHMID/hChi2MatchMCHMID"), fwdtrack.chi2MatchMCHMID()); + fRegistry.fill(HIST("MFTMCHMID/hChi2MatchMCHMFT"), fwdtrack.chi2MatchMCHMFT()); + fRegistry.fill(HIST("MFTMCHMID/hDCAxy2D"), dcaX, dcaY); + fRegistry.fill(HIST("MFTMCHMID/hDCAxy2DinSigma"), dcaX / std::sqrt(cXX), dcaY / std::sqrt(cYY)); + fRegistry.fill(HIST("MFTMCHMID/hDCAxy"), dcaXY); + fRegistry.fill(HIST("MFTMCHMID/hDCAxyz"), dcaXY, dcaZ); + fRegistry.fill(HIST("MFTMCHMID/hDCAxyinSigma"), dcaXYinSigma); + fRegistry.fill(HIST("MFTMCHMID/hDCAxResolutionvsPt"), pt, std::sqrt(cXX) * 1e+4); // convert cm to um + fRegistry.fill(HIST("MFTMCHMID/hDCAyResolutionvsPt"), pt, std::sqrt(cYY) * 1e+4); // convert cm to um + fRegistry.fill(HIST("MFTMCHMID/hDCAxyResolutionvsPt"), pt, sigma_dcaXY * 1e+4); // convert cm to um + } else if (fwdtrack.trackType() == o2::aod::fwdtrack::ForwardTrackTypeEnum::MuonStandaloneTrack) { + fRegistry.fill(HIST("MCHMID/hPt"), pt); + fRegistry.fill(HIST("MCHMID/hEtaPhi"), phi, eta); + fRegistry.fill(HIST("MCHMID/hEtaPhi_MatchedMCHMID"), phiMatchedMCHMID, etaMatchedMCHMID); + fRegistry.fill(HIST("MCHMID/hDeltaPt_Pt"), pt, dpt); + fRegistry.fill(HIST("MCHMID/hDeltaEta_Pt"), pt, deta); + fRegistry.fill(HIST("MCHMID/hDeltaPhi_Pt"), pt, dphi); + fRegistry.fill(HIST("MCHMID/hDeltaEtaAtMP_Pt"), pt, detaMP); + fRegistry.fill(HIST("MCHMID/hDeltaPhiAtMP_Pt"), pt, dphiMP); + fRegistry.fill(HIST("MCHMID/hSign"), fwdtrack.sign()); + fRegistry.fill(HIST("MCHMID/hNclusters"), fwdtrack.nClusters()); + fRegistry.fill(HIST("MCHMID/hNclustersMFT"), nClustersMFT); + fRegistry.fill(HIST("MCHMID/hPDCA_Rabs"), rAtAbsorberEnd, pDCA); + fRegistry.fill(HIST("MCHMID/hRatAbsorberEnd"), rAtAbsorberEnd); + fRegistry.fill(HIST("MCHMID/hChi2"), fwdtrack.chi2()); + fRegistry.fill(HIST("MCHMID/hChi2MFT"), chi2mft / ndf_mft); + fRegistry.fill(HIST("MCHMID/hChi2MatchMCHMID"), fwdtrack.chi2MatchMCHMID()); + fRegistry.fill(HIST("MCHMID/hChi2MatchMCHMFT"), fwdtrack.chi2MatchMCHMFT()); + fRegistry.fill(HIST("MCHMID/hDCAxy2D"), dcaX, dcaY); + fRegistry.fill(HIST("MCHMID/hDCAxy2DinSigma"), dcaX / std::sqrt(cXX), dcaY / std::sqrt(cYY)); + fRegistry.fill(HIST("MCHMID/hDCAxy"), dcaXY); + fRegistry.fill(HIST("MCHMID/hDCAxyz"), dcaXY, dcaZ); + fRegistry.fill(HIST("MCHMID/hDCAxyinSigma"), dcaXYinSigma); + fRegistry.fill(HIST("MCHMID/hDCAxResolutionvsPt"), pt, std::sqrt(cXX) * 1e+4); // convert cm to um + fRegistry.fill(HIST("MCHMID/hDCAyResolutionvsPt"), pt, std::sqrt(cYY) * 1e+4); // convert cm to um + fRegistry.fill(HIST("MCHMID/hDCAxyResolutionvsPt"), pt, sigma_dcaXY * 1e+4); // convert cm to um + } } } + return true; } std::unordered_map map_mfttrackcovs; @@ -515,6 +520,8 @@ struct skimmerPrimaryMuon { Preslice fwdtrackIndicesPerCollision = aod::track_association::collisionId; PresliceUnsorted fwdtrackIndicesPerFwdTrack = aod::track_association::fwdtrackId; PresliceUnsorted fwdtracksPerMCHTrack = aod::fwdtrack::matchMCHTrackId; + std::unordered_multimap multiMapSAMuonsPerCollision; // collisionId -> trackIds + std::unordered_multimap multiMapGLMuonsPerCollision; // collisionId -> trackIds void processRec_SA(MyCollisions const& collisions, MyFwdTracks const& fwdtracks, aod::MFTTracks const&, aod::BCsWithTimestamps const&) { @@ -538,10 +545,44 @@ struct skimmerPrimaryMuon { continue; } - fillFwdTrackTable(collision, fwdtrack, nullptr, false); + if (!fillFwdTrackTable(collision, fwdtrack, nullptr, false)) { + continue; + } + + if (fwdtrack.trackType() == o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack) { + multiMapGLMuonsPerCollision.insert(std::make_pair(collision.globalIndex(), fwdtrack.globalIndex())); + } + if (fwdtrack.trackType() == o2::aod::fwdtrack::ForwardTrackTypeEnum::MuonStandaloneTrack) { + multiMapSAMuonsPerCollision.insert(std::make_pair(collision.globalIndex(), fwdtrack.globalIndex())); + } + } // end of fwdtrack loop } // end of collision loop + for (const auto& collision : collisions) { + int count_samuons = multiMapSAMuonsPerCollision.count(collision.globalIndex()); + int count_glmuons = multiMapGLMuonsPerCollision.count(collision.globalIndex()); + fRegistry.fill(HIST("MCHMID/hNmu"), count_samuons); + fRegistry.fill(HIST("MFTMCHMID/hNmu"), count_glmuons); + + if (count_samuons >= minNmuon) { + auto range_samuons = multiMapSAMuonsPerCollision.equal_range(collision.globalIndex()); + for (auto it = range_samuons.first; it != range_samuons.second; it++) { + auto fwdtrack = fwdtracks.rawIteratorAt(it->second); + fillFwdTrackTable(collision, fwdtrack, nullptr, false); + } + } + if (count_glmuons >= minNmuon) { + auto range_glmuons = multiMapGLMuonsPerCollision.equal_range(collision.globalIndex()); + for (auto it = range_glmuons.first; it != range_glmuons.second; it++) { + auto fwdtrack = fwdtracks.rawIteratorAt(it->second); + fillFwdTrackTable(collision, fwdtrack, nullptr, false); + } + } + } // end of collision loop + + multiMapSAMuonsPerCollision.clear(); + multiMapGLMuonsPerCollision.clear(); map_mfttrackcovs.clear(); vec_min_chi2MatchMCHMFT.clear(); vec_min_chi2MatchMCHMFT.shrink_to_fit(); @@ -577,10 +618,44 @@ struct skimmerPrimaryMuon { continue; } - fillFwdTrackTable(collision, fwdtrack, nullptr, mapAmb[fwdtrack.globalIndex()]); + if (!fillFwdTrackTable(collision, fwdtrack, nullptr, mapAmb[fwdtrack.globalIndex()])) { + continue; + } + + if (fwdtrack.trackType() == o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack) { + multiMapGLMuonsPerCollision.insert(std::make_pair(collision.globalIndex(), fwdtrack.globalIndex())); + } + if (fwdtrack.trackType() == o2::aod::fwdtrack::ForwardTrackTypeEnum::MuonStandaloneTrack) { + multiMapSAMuonsPerCollision.insert(std::make_pair(collision.globalIndex(), fwdtrack.globalIndex())); + } + } // end of fwdtrack loop } // end of collision loop + for (const auto& collision : collisions) { + int count_samuons = multiMapSAMuonsPerCollision.count(collision.globalIndex()); + int count_glmuons = multiMapGLMuonsPerCollision.count(collision.globalIndex()); + fRegistry.fill(HIST("MCHMID/hNmu"), count_samuons); + fRegistry.fill(HIST("MFTMCHMID/hNmu"), count_glmuons); + + if (count_samuons >= minNmuon) { + auto range_samuons = multiMapSAMuonsPerCollision.equal_range(collision.globalIndex()); + for (auto it = range_samuons.first; it != range_samuons.second; it++) { + auto fwdtrack = fwdtracks.rawIteratorAt(it->second); + fillFwdTrackTable(collision, fwdtrack, nullptr, mapAmb[fwdtrack.globalIndex()]); + } + } + if (count_glmuons >= minNmuon) { + auto range_glmuons = multiMapGLMuonsPerCollision.equal_range(collision.globalIndex()); + for (auto it = range_glmuons.first; it != range_glmuons.second; it++) { + auto fwdtrack = fwdtracks.rawIteratorAt(it->second); + fillFwdTrackTable(collision, fwdtrack, nullptr, mapAmb[fwdtrack.globalIndex()]); + } + } + } // end of collision loop + + multiMapSAMuonsPerCollision.clear(); + multiMapGLMuonsPerCollision.clear(); mapAmb.clear(); map_mfttrackcovs.clear(); vec_min_chi2MatchMCHMFT.clear(); @@ -620,9 +695,44 @@ struct skimmerPrimaryMuon { continue; } - fillFwdTrackTable(collision, fwdtrack, mftCovs, mapAmb[fwdtrack.globalIndex()]); + if (!fillFwdTrackTable(collision, fwdtrack, mftCovs, mapAmb[fwdtrack.globalIndex()])) { + continue; + } + + if (fwdtrack.trackType() == o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack) { + multiMapGLMuonsPerCollision.insert(std::make_pair(collision.globalIndex(), fwdtrack.globalIndex())); + } + if (fwdtrack.trackType() == o2::aod::fwdtrack::ForwardTrackTypeEnum::MuonStandaloneTrack) { + multiMapSAMuonsPerCollision.insert(std::make_pair(collision.globalIndex(), fwdtrack.globalIndex())); + } + } // end of fwdtrack loop } // end of collision loop + + for (const auto& collision : collisions) { + int count_samuons = multiMapSAMuonsPerCollision.count(collision.globalIndex()); + int count_glmuons = multiMapGLMuonsPerCollision.count(collision.globalIndex()); + fRegistry.fill(HIST("MCHMID/hNmu"), count_samuons); + fRegistry.fill(HIST("MFTMCHMID/hNmu"), count_glmuons); + + if (count_samuons >= minNmuon) { + auto range_samuons = multiMapSAMuonsPerCollision.equal_range(collision.globalIndex()); + for (auto it = range_samuons.first; it != range_samuons.second; it++) { + auto fwdtrack = fwdtracks.rawIteratorAt(it->second); + fillFwdTrackTable(collision, fwdtrack, mftCovs, mapAmb[fwdtrack.globalIndex()]); + } + } + if (count_glmuons >= minNmuon) { + auto range_glmuons = multiMapGLMuonsPerCollision.equal_range(collision.globalIndex()); + for (auto it = range_glmuons.first; it != range_glmuons.second; it++) { + auto fwdtrack = fwdtracks.rawIteratorAt(it->second); + fillFwdTrackTable(collision, fwdtrack, mftCovs, mapAmb[fwdtrack.globalIndex()]); + } + } + } // end of collision loop + + multiMapSAMuonsPerCollision.clear(); + multiMapGLMuonsPerCollision.clear(); mapAmb.clear(); map_mfttrackcovs.clear(); vec_min_chi2MatchMCHMFT.clear(); @@ -655,9 +765,44 @@ struct skimmerPrimaryMuon { continue; } - fillFwdTrackTable(collision, fwdtrack, nullptr, false); + if (!fillFwdTrackTable(collision, fwdtrack, nullptr, false)) { + continue; + } + + if (fwdtrack.trackType() == o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack) { + multiMapGLMuonsPerCollision.insert(std::make_pair(collision.globalIndex(), fwdtrack.globalIndex())); + } + if (fwdtrack.trackType() == o2::aod::fwdtrack::ForwardTrackTypeEnum::MuonStandaloneTrack) { + multiMapSAMuonsPerCollision.insert(std::make_pair(collision.globalIndex(), fwdtrack.globalIndex())); + } + } // end of fwdtrack loop } // end of collision loop + + for (const auto& collision : collisions) { + int count_samuons = multiMapSAMuonsPerCollision.count(collision.globalIndex()); + int count_glmuons = multiMapGLMuonsPerCollision.count(collision.globalIndex()); + fRegistry.fill(HIST("MCHMID/hNmu"), count_samuons); + fRegistry.fill(HIST("MFTMCHMID/hNmu"), count_glmuons); + + if (count_samuons >= minNmuon) { + auto range_samuons = multiMapSAMuonsPerCollision.equal_range(collision.globalIndex()); + for (auto it = range_samuons.first; it != range_samuons.second; it++) { + auto fwdtrack = fwdtracks.rawIteratorAt(it->second); + fillFwdTrackTable(collision, fwdtrack, nullptr, false); + } + } + if (count_glmuons >= minNmuon) { + auto range_glmuons = multiMapGLMuonsPerCollision.equal_range(collision.globalIndex()); + for (auto it = range_glmuons.first; it != range_glmuons.second; it++) { + auto fwdtrack = fwdtracks.rawIteratorAt(it->second); + fillFwdTrackTable(collision, fwdtrack, nullptr, false); + } + } + } // end of collision loop + + multiMapSAMuonsPerCollision.clear(); + multiMapGLMuonsPerCollision.clear(); map_mfttrackcovs.clear(); vec_min_chi2MatchMCHMFT.clear(); vec_min_chi2MatchMCHMFT.shrink_to_fit(); @@ -695,9 +840,44 @@ struct skimmerPrimaryMuon { continue; } - fillFwdTrackTable(collision, fwdtrack, nullptr, mapAmb[fwdtrack.globalIndex()]); + if (!fillFwdTrackTable(collision, fwdtrack, nullptr, mapAmb[fwdtrack.globalIndex()])) { + continue; + } + + if (fwdtrack.trackType() == o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack) { + multiMapGLMuonsPerCollision.insert(std::make_pair(collision.globalIndex(), fwdtrack.globalIndex())); + } + if (fwdtrack.trackType() == o2::aod::fwdtrack::ForwardTrackTypeEnum::MuonStandaloneTrack) { + multiMapSAMuonsPerCollision.insert(std::make_pair(collision.globalIndex(), fwdtrack.globalIndex())); + } + } // end of fwdtrack loop } // end of collision loop + + for (const auto& collision : collisions) { + int count_samuons = multiMapSAMuonsPerCollision.count(collision.globalIndex()); + int count_glmuons = multiMapGLMuonsPerCollision.count(collision.globalIndex()); + fRegistry.fill(HIST("MCHMID/hNmu"), count_samuons); + fRegistry.fill(HIST("MFTMCHMID/hNmu"), count_glmuons); + + if (count_samuons >= minNmuon) { + auto range_samuons = multiMapSAMuonsPerCollision.equal_range(collision.globalIndex()); + for (auto it = range_samuons.first; it != range_samuons.second; it++) { + auto fwdtrack = fwdtracks.rawIteratorAt(it->second); + fillFwdTrackTable(collision, fwdtrack, nullptr, mapAmb[fwdtrack.globalIndex()]); + } + } + if (count_glmuons >= minNmuon) { + auto range_glmuons = multiMapGLMuonsPerCollision.equal_range(collision.globalIndex()); + for (auto it = range_glmuons.first; it != range_glmuons.second; it++) { + auto fwdtrack = fwdtracks.rawIteratorAt(it->second); + fillFwdTrackTable(collision, fwdtrack, nullptr, mapAmb[fwdtrack.globalIndex()]); + } + } + } // end of collision loop + + multiMapSAMuonsPerCollision.clear(); + multiMapGLMuonsPerCollision.clear(); mapAmb.clear(); map_mfttrackcovs.clear(); vec_min_chi2MatchMCHMFT.clear(); @@ -739,9 +919,44 @@ struct skimmerPrimaryMuon { continue; } - fillFwdTrackTable(collision, fwdtrack, mftCovs, mapAmb[fwdtrack.globalIndex()]); + if (!fillFwdTrackTable(collision, fwdtrack, mftCovs, mapAmb[fwdtrack.globalIndex()])) { + continue; + } + + if (fwdtrack.trackType() == o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack) { + multiMapGLMuonsPerCollision.insert(std::make_pair(collision.globalIndex(), fwdtrack.globalIndex())); + } + if (fwdtrack.trackType() == o2::aod::fwdtrack::ForwardTrackTypeEnum::MuonStandaloneTrack) { + multiMapSAMuonsPerCollision.insert(std::make_pair(collision.globalIndex(), fwdtrack.globalIndex())); + } + } // end of fwdtrack loop } // end of collision loop + + for (const auto& collision : collisions) { + int count_samuons = multiMapSAMuonsPerCollision.count(collision.globalIndex()); + int count_glmuons = multiMapGLMuonsPerCollision.count(collision.globalIndex()); + fRegistry.fill(HIST("MCHMID/hNmu"), count_samuons); + fRegistry.fill(HIST("MFTMCHMID/hNmu"), count_glmuons); + + if (count_samuons >= minNmuon) { + auto range_samuons = multiMapSAMuonsPerCollision.equal_range(collision.globalIndex()); + for (auto it = range_samuons.first; it != range_samuons.second; it++) { + auto fwdtrack = fwdtracks.rawIteratorAt(it->second); + fillFwdTrackTable(collision, fwdtrack, mftCovs, mapAmb[fwdtrack.globalIndex()]); + } + } + if (count_glmuons >= minNmuon) { + auto range_glmuons = multiMapGLMuonsPerCollision.equal_range(collision.globalIndex()); + for (auto it = range_glmuons.first; it != range_glmuons.second; it++) { + auto fwdtrack = fwdtracks.rawIteratorAt(it->second); + fillFwdTrackTable(collision, fwdtrack, mftCovs, mapAmb[fwdtrack.globalIndex()]); + } + } + } // end of collision loop + + multiMapSAMuonsPerCollision.clear(); + multiMapGLMuonsPerCollision.clear(); mapAmb.clear(); map_mfttrackcovs.clear(); vec_min_chi2MatchMCHMFT.clear(); @@ -775,9 +990,44 @@ struct skimmerPrimaryMuon { continue; } - fillFwdTrackTable(collision, fwdtrack, nullptr, false); + if (!fillFwdTrackTable(collision, fwdtrack, nullptr, false)) { + continue; + } + + if (fwdtrack.trackType() == o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack) { + multiMapGLMuonsPerCollision.insert(std::make_pair(collision.globalIndex(), fwdtrack.globalIndex())); + } + if (fwdtrack.trackType() == o2::aod::fwdtrack::ForwardTrackTypeEnum::MuonStandaloneTrack) { + multiMapSAMuonsPerCollision.insert(std::make_pair(collision.globalIndex(), fwdtrack.globalIndex())); + } + } // end of fwdtrack loop } // end of collision loop + + for (const auto& collision : collisions) { + int count_samuons = multiMapSAMuonsPerCollision.count(collision.globalIndex()); + int count_glmuons = multiMapGLMuonsPerCollision.count(collision.globalIndex()); + fRegistry.fill(HIST("MCHMID/hNmu"), count_samuons); + fRegistry.fill(HIST("MFTMCHMID/hNmu"), count_glmuons); + + if (count_samuons >= minNmuon) { + auto range_samuons = multiMapSAMuonsPerCollision.equal_range(collision.globalIndex()); + for (auto it = range_samuons.first; it != range_samuons.second; it++) { + auto fwdtrack = fwdtracks.rawIteratorAt(it->second); + fillFwdTrackTable(collision, fwdtrack, nullptr, false); + } + } + if (count_glmuons >= minNmuon) { + auto range_glmuons = multiMapGLMuonsPerCollision.equal_range(collision.globalIndex()); + for (auto it = range_glmuons.first; it != range_glmuons.second; it++) { + auto fwdtrack = fwdtracks.rawIteratorAt(it->second); + fillFwdTrackTable(collision, fwdtrack, nullptr, false); + } + } + } // end of collision loop + + multiMapSAMuonsPerCollision.clear(); + multiMapGLMuonsPerCollision.clear(); map_mfttrackcovs.clear(); vec_min_chi2MatchMCHMFT.clear(); vec_min_chi2MatchMCHMFT.shrink_to_fit(); @@ -818,9 +1068,44 @@ struct skimmerPrimaryMuon { continue; } - fillFwdTrackTable(collision, fwdtrack, nullptr, mapAmb[fwdtrack.globalIndex()]); + if (!fillFwdTrackTable(collision, fwdtrack, nullptr, mapAmb[fwdtrack.globalIndex()])) { + continue; + } + + if (fwdtrack.trackType() == o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack) { + multiMapGLMuonsPerCollision.insert(std::make_pair(collision.globalIndex(), fwdtrack.globalIndex())); + } + if (fwdtrack.trackType() == o2::aod::fwdtrack::ForwardTrackTypeEnum::MuonStandaloneTrack) { + multiMapSAMuonsPerCollision.insert(std::make_pair(collision.globalIndex(), fwdtrack.globalIndex())); + } + } // end of fwdtrack loop } // end of collision loop + + for (const auto& collision : collisions) { + int count_samuons = multiMapSAMuonsPerCollision.count(collision.globalIndex()); + int count_glmuons = multiMapGLMuonsPerCollision.count(collision.globalIndex()); + fRegistry.fill(HIST("MCHMID/hNmu"), count_samuons); + fRegistry.fill(HIST("MFTMCHMID/hNmu"), count_glmuons); + + if (count_samuons >= minNmuon) { + auto range_samuons = multiMapSAMuonsPerCollision.equal_range(collision.globalIndex()); + for (auto it = range_samuons.first; it != range_samuons.second; it++) { + auto fwdtrack = fwdtracks.rawIteratorAt(it->second); + fillFwdTrackTable(collision, fwdtrack, nullptr, mapAmb[fwdtrack.globalIndex()]); + } + } + if (count_glmuons >= minNmuon) { + auto range_glmuons = multiMapGLMuonsPerCollision.equal_range(collision.globalIndex()); + for (auto it = range_glmuons.first; it != range_glmuons.second; it++) { + auto fwdtrack = fwdtracks.rawIteratorAt(it->second); + fillFwdTrackTable(collision, fwdtrack, nullptr, mapAmb[fwdtrack.globalIndex()]); + } + } + } // end of collision loop + + multiMapSAMuonsPerCollision.clear(); + multiMapGLMuonsPerCollision.clear(); mapAmb.clear(); map_mfttrackcovs.clear(); vec_min_chi2MatchMCHMFT.clear(); @@ -865,9 +1150,44 @@ struct skimmerPrimaryMuon { continue; } - fillFwdTrackTable(collision, fwdtrack, mftCovs, mapAmb[fwdtrack.globalIndex()]); + if (!fillFwdTrackTable(collision, fwdtrack, mftCovs, mapAmb[fwdtrack.globalIndex()])) { + continue; + } + + if (fwdtrack.trackType() == o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack) { + multiMapGLMuonsPerCollision.insert(std::make_pair(collision.globalIndex(), fwdtrack.globalIndex())); + } + if (fwdtrack.trackType() == o2::aod::fwdtrack::ForwardTrackTypeEnum::MuonStandaloneTrack) { + multiMapSAMuonsPerCollision.insert(std::make_pair(collision.globalIndex(), fwdtrack.globalIndex())); + } + } // end of fwdtrack loop } // end of collision loop + + for (const auto& collision : collisions) { + int count_samuons = multiMapSAMuonsPerCollision.count(collision.globalIndex()); + int count_glmuons = multiMapGLMuonsPerCollision.count(collision.globalIndex()); + fRegistry.fill(HIST("MCHMID/hNmu"), count_samuons); + fRegistry.fill(HIST("MFTMCHMID/hNmu"), count_glmuons); + + if (count_samuons >= minNmuon) { + auto range_samuons = multiMapSAMuonsPerCollision.equal_range(collision.globalIndex()); + for (auto it = range_samuons.first; it != range_samuons.second; it++) { + auto fwdtrack = fwdtracks.rawIteratorAt(it->second); + fillFwdTrackTable(collision, fwdtrack, mftCovs, mapAmb[fwdtrack.globalIndex()]); + } + } + if (count_glmuons >= minNmuon) { + auto range_glmuons = multiMapGLMuonsPerCollision.equal_range(collision.globalIndex()); + for (auto it = range_glmuons.first; it != range_glmuons.second; it++) { + auto fwdtrack = fwdtracks.rawIteratorAt(it->second); + fillFwdTrackTable(collision, fwdtrack, mftCovs, mapAmb[fwdtrack.globalIndex()]); + } + } + } // end of collision loop + + multiMapSAMuonsPerCollision.clear(); + multiMapGLMuonsPerCollision.clear(); mapAmb.clear(); map_mfttrackcovs.clear(); vec_min_chi2MatchMCHMFT.clear(); From 60eb6aa10805cb8926751e7d243521d734a17ec8 Mon Sep 17 00:00:00 2001 From: Daiki Sekihata Date: Sun, 23 Nov 2025 13:25:24 +0100 Subject: [PATCH 2/4] Update skimmerPrimaryElectron.cxx --- PWGEM/Dilepton/TableProducer/skimmerPrimaryElectron.cxx | 1 + 1 file changed, 1 insertion(+) diff --git a/PWGEM/Dilepton/TableProducer/skimmerPrimaryElectron.cxx b/PWGEM/Dilepton/TableProducer/skimmerPrimaryElectron.cxx index 44ee0441bc6..8fc79da8d34 100644 --- a/PWGEM/Dilepton/TableProducer/skimmerPrimaryElectron.cxx +++ b/PWGEM/Dilepton/TableProducer/skimmerPrimaryElectron.cxx @@ -37,6 +37,7 @@ #include "Math/Vector4D.h" +#include #include #include #include From 0036ae02f65886dfd9d3fe790a86b5fdae6a1cd8 Mon Sep 17 00:00:00 2001 From: Daiki Sekihata Date: Mon, 24 Nov 2025 10:37:02 +0100 Subject: [PATCH 3/4] Change minNelectron from 1 to 0 --- PWGEM/Dilepton/TableProducer/skimmerPrimaryElectron.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/PWGEM/Dilepton/TableProducer/skimmerPrimaryElectron.cxx b/PWGEM/Dilepton/TableProducer/skimmerPrimaryElectron.cxx index 8fc79da8d34..49b18cfb2c0 100644 --- a/PWGEM/Dilepton/TableProducer/skimmerPrimaryElectron.cxx +++ b/PWGEM/Dilepton/TableProducer/skimmerPrimaryElectron.cxx @@ -105,7 +105,7 @@ struct skimmerPrimaryElectron { Configurable maxpt_itssa{"maxpt_itssa", 0.15, "max pt for ITSsa track"}; Configurable maxMeanITSClusterSize{"maxMeanITSClusterSize", 16, "max x cos(lambda)"}; Configurable storeOnlyTrueElectronMC{"storeOnlyTrueElectronMC", false, "Flag to store only true electron in MC"}; - Configurable minNelectron{"minNelectron", 1, "min number of electron candidates per collision"}; + Configurable minNelectron{"minNelectron", 0, "min number of electron candidates per collision"}; // configuration for PID ML Configurable usePIDML{"usePIDML", false, "Flag to use PID ML"}; From f866a7b93b40eb94e0dd2f8af2d1d5887fbb4ef4 Mon Sep 17 00:00:00 2001 From: Daiki Sekihata Date: Mon, 24 Nov 2025 10:37:31 +0100 Subject: [PATCH 4/4] Change minNmuon default value from 1 to 0 --- PWGEM/Dilepton/TableProducer/skimmerPrimaryMuon.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/PWGEM/Dilepton/TableProducer/skimmerPrimaryMuon.cxx b/PWGEM/Dilepton/TableProducer/skimmerPrimaryMuon.cxx index 035a52f41eb..baa297bec1a 100644 --- a/PWGEM/Dilepton/TableProducer/skimmerPrimaryMuon.cxx +++ b/PWGEM/Dilepton/TableProducer/skimmerPrimaryMuon.cxx @@ -89,7 +89,7 @@ struct skimmerPrimaryMuon { Configurable maxChi2GL{"maxChi2GL", 10, "max. chi2 for global muon"}; Configurable refitGlobalMuon{"refitGlobalMuon", true, "flag to refit global muon"}; Configurable matchingZ{"matchingZ", -77.5, "z position where matching is performed"}; - Configurable minNmuon{"minNmuon", 1, "min number of muon candidates per collision"}; + Configurable minNmuon{"minNmuon", 0, "min number of muon candidates per collision"}; o2::ccdb::CcdbApi ccdbApi; Service ccdb;