From fcd4dfe984652f65e5af030fceaf5f5950c54935 Mon Sep 17 00:00:00 2001 From: zhangbiao-phy <52267892+zhangbiao-phy@users.noreply.github.com> Date: Tue, 19 Jul 2022 02:12:54 +0800 Subject: [PATCH 01/31] add the selection for the global track without DCA (#1014) --- PWGHF/TableProducer/HFTrackIndexSkimsCreator.cxx | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/PWGHF/TableProducer/HFTrackIndexSkimsCreator.cxx b/PWGHF/TableProducer/HFTrackIndexSkimsCreator.cxx index 632ecab78dc..4761630a68f 100644 --- a/PWGHF/TableProducer/HFTrackIndexSkimsCreator.cxx +++ b/PWGHF/TableProducer/HFTrackIndexSkimsCreator.cxx @@ -248,6 +248,7 @@ struct HfTagSelTracks { // quality cut Configurable doCutQuality{"doCutQuality", true, "apply quality cuts"}; Configurable useIsGlobalTrack{"useIsGlobalTrack", false, "check isGlobalTrack status for tracks, for Run3 studies"}; + Configurable useIsGlobalTrackWoDCA{"useIsGlobalTrackWoDCA", false, "check isGlobalTrackWoDCA status for tracks, for Run3 studies"}; Configurable tpcNClsFound{"tpcNClsFound", 70, ">= min. number of TPC clusters needed"}; // pT bins for single-track cuts Configurable> pTBinsTrack{"pTBinsTrack", std::vector{hf_cuts_single_track::pTBinsTrack_v}, "track pT bin limits for 2-prong DCAXY pT-depentend cut"}; @@ -698,6 +699,10 @@ struct HfTagSelTracks { if (track.isGlobalTrack() != (uint8_t) true) { hasGoodQuality = false; } + } else if (useIsGlobalTrackWoDCA) { + if (track.isGlobalTrackWoDCA() != (uint8_t) true) { + hasGoodQuality = false; + } } else { UChar_t clustermap = track.itsClusterMap(); if (!(track.tpcNClsFound() >= tpcNClsFound.value && // is this the number of TPC clusters? It should not be used From e6a6acee3ec6433a2a16906276a01a0d6fdc0b72 Mon Sep 17 00:00:00 2001 From: Fabrizio Date: Mon, 18 Jul 2022 20:27:34 +0200 Subject: [PATCH 02/31] PWGHF: Fix typo (#1015) --- PWGHF/Tasks/HFMCValidation.cxx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/PWGHF/Tasks/HFMCValidation.cxx b/PWGHF/Tasks/HFMCValidation.cxx index 81bc7bab57f..2bbc105a45d 100644 --- a/PWGHF/Tasks/HFMCValidation.cxx +++ b/PWGHF/Tasks/HFMCValidation.cxx @@ -242,13 +242,13 @@ struct ValidationRecLevel { std::array, nCharmHadrons> histDeltaPt, histDeltaPx, histDeltaPy, histDeltaPz, histDeltaSecondaryVertexX, histDeltaSecondaryVertexY, histDeltaSecondaryVertexZ, histDeltaDecayLength; std::array, 3>, 2>, nCharmHadrons> histPtDau, histEtaDau, histImpactParameterDau; std::array, 2>, nCharmHadrons> histPtReco; - std::array, 2> histOriginTracks; + std::array, 2> histOriginTracks; HistogramRegistry registry{"registry", {}}; void init(o2::framework::InitContext&) { - histOriginTracks[0] = registry.add("histOriginNonAssociatedTracks", ";origin;#it{p}_{T}^{reco} (GeV/#it{c})", HistType::kTH2F, {{4, -1.5, 2.5}, {50, 0., 10.}}); - histOriginTracks[1] = registry.add("histOriginAssociatedTracks", ";origin;#it{p}_{T}^{reco} (GeV/#it{c})", HistType::kTH2F, {{4, -1.5, 2.5}, {50, 0., 10.}}); + histOriginTracks[0] = registry.add("histOriginNonAssociatedTracks", ";origin;#it{p}_{T}^{reco} (GeV/#it{c})", HistType::kTH2F, {{4, -1.5, 2.5}, {50, 0., 10.}}); + histOriginTracks[1] = registry.add("histOriginAssociatedTracks", ";origin;#it{p}_{T}^{reco} (GeV/#it{c})", HistType::kTH2F, {{4, -1.5, 2.5}, {50, 0., 10.}}); for (std::size_t iHist{0}; iHist < histOriginTracks.size(); ++iHist) { histOriginTracks[iHist]->GetXaxis()->SetBinLabel(1, "no MC particle"); histOriginTracks[iHist]->GetXaxis()->SetBinLabel(2, "no quark"); From a82b9b1772fa61aa83d732c70b7d4efa2fcf487b Mon Sep 17 00:00:00 2001 From: Maja Kabus Date: Tue, 19 Jul 2022 09:47:31 +0200 Subject: [PATCH 03/31] Event mixing: Update binning policy, add example for binning with lambda (#973) --- .../femtoDreamPairTaskTrackTrack.cxx | 2 +- .../FemtoDream/femtoDreamPairTaskTrackV0.cxx | 2 +- PWGCF/Tasks/correlations.cxx | 2 +- Tutorials/src/eventMixing.cxx | 59 +++++++++++++++---- Tutorials/src/eventMixingValidation.cxx | 6 +- Tutorials/src/tracksCombinations.cxx | 4 +- 6 files changed, 57 insertions(+), 18 deletions(-) diff --git a/PWGCF/FemtoDream/femtoDreamPairTaskTrackTrack.cxx b/PWGCF/FemtoDream/femtoDreamPairTaskTrackTrack.cxx index 3170e6fa53b..e717a2b5e5c 100644 --- a/PWGCF/FemtoDream/femtoDreamPairTaskTrackTrack.cxx +++ b/PWGCF/FemtoDream/femtoDreamPairTaskTrackTrack.cxx @@ -94,7 +94,7 @@ struct femtoDreamPairTaskTrackTrack { ConfigurableAxis CfgMultBins{"CfgMultBins", {VARIABLE_WIDTH, 0.0f, 20.0f, 40.0f, 60.0f, 80.0f, 100.0f, 200.0f, 99999.f}, "Mixing bins - multiplicity"}; ConfigurableAxis CfgVtxBins{"CfgVtxBins", {VARIABLE_WIDTH, -10.0f, -8.f, -6.f, -4.f, -2.f, 0.f, 2.f, 4.f, 6.f, 8.f, 10.f}, "Mixing bins - z-vertex"}; - BinningPolicy colBinning{{CfgVtxBins, CfgMultBins}, true}; + ColumnBinningPolicy colBinning{{CfgVtxBins, CfgMultBins}, true}; ConfigurableAxis CfgkstarBins{"CfgkstarBins", {1500, 0., 6.}, "binning kstar"}; ConfigurableAxis CfgkTBins{"CfgkTBins", {150, 0., 9.}, "binning kT"}; diff --git a/PWGCF/FemtoDream/femtoDreamPairTaskTrackV0.cxx b/PWGCF/FemtoDream/femtoDreamPairTaskTrackV0.cxx index 06932b46273..3acde27db2c 100644 --- a/PWGCF/FemtoDream/femtoDreamPairTaskTrackV0.cxx +++ b/PWGCF/FemtoDream/femtoDreamPairTaskTrackV0.cxx @@ -186,7 +186,7 @@ struct femtoDreamPairTaskTrackV0 { void processMixedEvent(o2::aod::FemtoDreamCollisions& cols, o2::aod::FemtoDreamParticles& parts) { - BinningPolicy colBinning{{CfgVtxBins, CfgMultBins}, true}; + ColumnBinningPolicy colBinning{{CfgVtxBins, CfgMultBins}, true}; for (auto& [collision1, collision2] : soa::selfCombinations(colBinning, 5, -1, cols, cols)) { diff --git a/PWGCF/Tasks/correlations.cxx b/PWGCF/Tasks/correlations.cxx index 2e6a6c60593..7ea1195848e 100644 --- a/PWGCF/Tasks/correlations.cxx +++ b/PWGCF/Tasks/correlations.cxx @@ -115,7 +115,7 @@ struct CorrelationTask { using aodCollisions = soa::Filtered>; using derivedCollisions = soa::Filtered; - using BinningType = BinningPolicy; + using BinningType = ColumnBinningPolicy; void init(o2::framework::InitContext&) { diff --git a/Tutorials/src/eventMixing.cxx b/Tutorials/src/eventMixing.cxx index d684b119b99..5eaed191c00 100644 --- a/Tutorials/src/eventMixing.cxx +++ b/Tutorials/src/eventMixing.cxx @@ -38,7 +38,7 @@ DECLARE_SOA_TABLE(Hashes, "AOD", "HASH", hash::Bin); struct MixedEvents { std::vector xBins{VARIABLE_WIDTH, -0.064, -0.062, -0.060, 0.066, 0.068, 0.070, 0.072}; std::vector yBins{VARIABLE_WIDTH, -0.320, -0.301, -0.300, 0.330, 0.340, 0.350, 0.360}; - using BinningType = BinningPolicy; + using BinningType = ColumnBinningPolicy; BinningType binningOnPositions{{xBins, yBins}, true}; // true is for 'ignore overflows' (true by default) SameKindPair pair{binningOnPositions, 5, -1}; // indicates that 5 events should be mixed and under/overflow (-1) to be ignored @@ -68,7 +68,7 @@ struct MixedEvents { struct MixedEventsInsideProcess { std::vector xBins{VARIABLE_WIDTH, -0.064, -0.062, -0.060, 0.066, 0.068, 0.070, 0.072}; std::vector yBins{VARIABLE_WIDTH, -0.320, -0.301, -0.300, 0.330, 0.340, 0.350, 0.360}; - using BinningType = BinningPolicy; + using BinningType = ColumnBinningPolicy; BinningType binningOnPositions{{xBins, yBins}, true}; // true is for 'ignore overflows' (true by default) void process(aod::Collisions& collisions, aod::Tracks& tracks) @@ -103,7 +103,7 @@ struct MixedEventsFilteredTracks { std::vector xBins{VARIABLE_WIDTH, -0.064, -0.062, -0.060, 0.066, 0.068, 0.070, 0.072}; std::vector yBins{VARIABLE_WIDTH, -0.320, -0.301, -0.300, 0.330, 0.340, 0.350, 0.360}; - using BinningType = BinningPolicy; + using BinningType = ColumnBinningPolicy; BinningType binningOnPositions{{xBins, yBins}, true}; // true is for 'ignore overflows' (true by default) SameKindPair pair{binningOnPositions, 5, -1}; // indicates that 5 events should be mixed and under/overflow (-1) to be ignored @@ -134,7 +134,7 @@ struct MixedEventsJoinedCollisions { using aodCollisions = soa::Join; std::vector xBins{VARIABLE_WIDTH, -0.064, -0.062, -0.060, 0.066, 0.068, 0.070, 0.072}; std::vector yBins{VARIABLE_WIDTH, -0.320, -0.301, -0.300, 0.330, 0.340, 0.350, 0.360}; - using BinningType = BinningPolicy; + using BinningType = ColumnBinningPolicy; BinningType binningOnPositions{{xBins, yBins}, true}; // true is for 'ignore overflows' (true by default) SameKindPair pair{binningOnPositions, 5, -1}; // indicates that 5 events should be mixed and under/overflow (-1) to be ignored @@ -165,7 +165,7 @@ struct MixedEventsDynamicColumns { using aodCollisions = soa::Join; std::vector zBins{7, -7, 7}; std::vector multBins{VARIABLE_WIDTH, 0, 5, 10, 20, 30, 40, 50, 100.1}; - using BinningType = BinningPolicy>; + using BinningType = ColumnBinningPolicy>; BinningType corrBinning{{zBins, multBins}, true}; // true is for 'ignore overflows' (true by default) SameKindPair pair{corrBinning, 5, -1}; // indicates that 5 events should be mixed and under/overflow (-1) to be ignored @@ -195,7 +195,7 @@ struct MixedEventsDynamicColumns { struct MixedEventsVariousKinds { std::vector xBins{VARIABLE_WIDTH, -0.064, -0.062, -0.060, 0.066, 0.068, 0.070, 0.072}; std::vector yBins{VARIABLE_WIDTH, -0.320, -0.301, -0.300, 0.330, 0.340, 0.350, 0.360}; - using BinningType = BinningPolicy; + using BinningType = ColumnBinningPolicy; BinningType binningOnPositions{{xBins, yBins}, true}; // true is for 'ignore overflows' (true by default) Pair pair{binningOnPositions, 5, -1}; // indicates that 5 events should be mixed and under/overflow (-1) to be ignored @@ -228,7 +228,7 @@ struct MixedEventsTriple { std::vector xBins{VARIABLE_WIDTH, -0.064, -0.062, -0.060, 0.066, 0.068, 0.070, 0.072}; std::vector yBins{VARIABLE_WIDTH, -0.320, -0.301, -0.300, 0.330, 0.340, 0.350, 0.360}; std::vector zBins{7, -7, 7}; - using BinningType = BinningPolicy; + using BinningType = ColumnBinningPolicy; BinningType binningOnPositions{{xBins, yBins, zBins}, true}; // true is for 'ignore overflows' (true by default) SameKindTriple triple{binningOnPositions, 5, -1}; // indicates that 5 events should be mixed and under/overflow (-1) to be ignored @@ -259,7 +259,7 @@ struct MixedEventsTripleVariousKinds { std::vector xBins{VARIABLE_WIDTH, -0.064, -0.062, -0.060, 0.066, 0.068, 0.070, 0.072}; std::vector yBins{VARIABLE_WIDTH, -0.320, -0.301, -0.300, 0.330, 0.340, 0.350, 0.360}; std::vector zBins{7, -7, 7}; - using BinningType = BinningPolicy; + using BinningType = ColumnBinningPolicy; BinningType binningOnPositions{{xBins, yBins, zBins}, true}; // true is for 'ignore overflows' (true by default) Triple triple{binningOnPositions, 5, -1}; // indicates that 5 events should be mixed and under/overflow (-1) to be ignored @@ -356,7 +356,6 @@ struct MixedEventsWithHashTask { }; struct MixedEventsPartitionedTracks { - Filter trackFilter = (aod::track::x > -0.8f) && (aod::track::x < 0.8f) && (aod::track::y > 1.0f); using myTracks = soa::Filtered; @@ -365,7 +364,7 @@ struct MixedEventsPartitionedTracks { std::vector xBins{VARIABLE_WIDTH, -0.064, -0.062, -0.060, 0.066, 0.068, 0.070, 0.072}; std::vector yBins{VARIABLE_WIDTH, -0.320, -0.301, -0.300, 0.330, 0.340, 0.350, 0.360}; - using BinningType = BinningPolicy; + using BinningType = ColumnBinningPolicy; BinningType binningOnPositions{{xBins, yBins}, true}; // true is for 'ignore overflows' (true by default) SameKindPair pair{binningOnPositions, 5, -1}; // indicates that 5 events should be mixed and under/overflow (-1) to be ignored @@ -400,6 +399,45 @@ struct MixedEventsPartitionedTracks { } }; +struct MixedEventsLambdaBinning { + ConfigurableAxis axisVertex{"axisVertex", {14, -7, 7}, "vertex axis for histograms"}; + ConfigurableAxis axisMultiplicity{"axisMultiplicity", {VARIABLE_WIDTH, 0.0, 2.750, 5.250, 7.750, 12.750, 17.750, 22.750, 27.750, 32.750, 37.750, 42.750, 47.750, 52.750, 57.750, 62.750, 67.750, 72.750, 77.750, 82.750, 87.750, 92.750, 97.750, 250.1}, "multiplicity axis for histograms"}; + + void process(aod::Collisions& collisions, aod::Tracks& tracks) + { + LOGF(info, "Input data Collisions %d, Tracks %d ", collisions.size(), tracks.size()); + + auto getTracksSize = + [&tracks](aod::Collision const& col) { + auto associatedTracks = tracks.sliceByCached(o2::aod::track::collisionId, col.globalIndex()); // it's cached, so slicing/grouping happens only once + return associatedTracks.size(); + }; + + using BinningType = FlexibleBinningPolicy, aod::collision::PosZ, decltype(getTracksSize)>; + BinningType binningWithLambda{{getTracksSize}, {axisVertex, axisMultiplicity}, true}; + + auto tracksTuple = std::make_tuple(tracks); + SameKindPair pair{binningWithLambda, 5, -1, collisions, tracksTuple}; // indicates that 5 events should be mixed and under/overflow (-1) to be ignored + + int count = 0; + for (auto& [c1, tracks1, c2, tracks2] : pair) { + LOGF(info, "Mixed event collisions: (%d, %d) z: (%.3f, %.3f), tracks size (%d, %d)", c1.globalIndex(), c2.globalIndex(), c1.posZ(), c2.posZ(), tracks1.size(), tracks2.size()); + count++; + if (count == 100) + break; + + // Example of using tracks from mixed events -- iterate over all track pairs from the two collisions + int trackCount = 0; + for (auto& [t1, t2] : combinations(CombinationsFullIndexPolicy(tracks1, tracks2))) { + LOGF(info, "Mixed event tracks pair: (%d, %d) from events (%d, %d), track event: (%d, %d)", t1.index(), t2.index(), c1.index(), c2.index(), t1.collision().index(), t2.collision().index()); + trackCount++; + if (trackCount == 10) + break; + } + } + } +}; + WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) { return WorkflowSpec{ @@ -414,5 +452,6 @@ WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) adaptAnalysisTask(cfgc), adaptAnalysisTask(cfgc), adaptAnalysisTask(cfgc), + adaptAnalysisTask(cfgc), }; } diff --git a/Tutorials/src/eventMixingValidation.cxx b/Tutorials/src/eventMixingValidation.cxx index 06d7d5ae054..4260b67a508 100644 --- a/Tutorials/src/eventMixingValidation.cxx +++ b/Tutorials/src/eventMixingValidation.cxx @@ -32,7 +32,7 @@ struct MixedEventsEmptyTables { std::vector xBins{VARIABLE_WIDTH, -0.064, -0.062, -0.060, 0.066, 0.068, 0.070, 0.072}; std::vector yBins{VARIABLE_WIDTH, -0.320, -0.301, -0.300, 0.330, 0.340, 0.350, 0.360}; - using BinningType = BinningPolicy; + using BinningType = ColumnBinningPolicy; BinningType binningOnPositions{{xBins, yBins}, true}; // true is for 'ignore overflows' (true by default) SameKindPair pair{binningOnPositions, 5, -1}; // indicates that 5 events should be mixed and under/overflow (-1) to be ignored @@ -62,7 +62,7 @@ struct MixedEventsEmptyTables { struct MixedEventsJoinedTracks { std::vector xBins{VARIABLE_WIDTH, -0.064, -0.062, -0.060, 0.066, 0.068, 0.070, 0.072}; std::vector yBins{VARIABLE_WIDTH, -0.320, -0.301, -0.300, 0.330, 0.340, 0.350, 0.360}; - using BinningType = BinningPolicy; + using BinningType = ColumnBinningPolicy; BinningType binningOnPositions{{xBins, yBins}, true}; // true is for 'ignore overflows' (true by default) SameKindPair pair{binningOnPositions, 5, -1}; // indicates that 5 events should be mixed and under/overflow (-1) to be ignored @@ -93,7 +93,7 @@ struct MixedEventsJoinedTracks { // struct MixedEventsBadSubscription { // std::vector xBins{VARIABLE_WIDTH, -0.064, -0.062, -0.060, 0.066, 0.068, 0.070, 0.072}; // std::vector yBins{VARIABLE_WIDTH, -0.320, -0.301, -0.300, 0.330, 0.340, 0.350, 0.360}; -// using BinningType = BinningPolicy; +// using BinningType = ColumnBinningPolicy; // BinningType binningOnPositions{{xBins, yBins}, true}; // true is for 'ignore overflows' (true by default) // SameKindPair pair{binningOnPositions, 5, -1}; // indicates that 5 events should be mixed and under/overflow (-1) to be ignored // diff --git a/Tutorials/src/tracksCombinations.cxx b/Tutorials/src/tracksCombinations.cxx index fc1d04ca26d..67ed35d2307 100644 --- a/Tutorials/src/tracksCombinations.cxx +++ b/Tutorials/src/tracksCombinations.cxx @@ -51,7 +51,7 @@ struct TrackCombinations { struct BinnedTrackCombinations { std::vector xBins{VARIABLE_WIDTH, -0.064, -0.062, -0.060, 0.066, 0.068, 0.070, 0.072}; std::vector yBins{VARIABLE_WIDTH, -0.320, -0.301, -0.300, 0.330, 0.340, 0.350, 0.360}; - BinningPolicy trackBinning{{xBins, yBins}, true}; + ColumnBinningPolicy trackBinning{{xBins, yBins}, true}; void process(aod::Tracks const& tracks) { @@ -73,7 +73,7 @@ struct ConfigurableBinnedCollisionCombinations { void process(soa::Join const& collisions) { - using BinningType = BinningPolicy>; + using BinningType = ColumnBinningPolicy>; BinningType colBinning{{axisVertex, axisMultiplicity}, true}; int count = 0; From 74c2f14ac0fb69ae844a3c445418308756903793 Mon Sep 17 00:00:00 2001 From: Fabrizio Date: Tue, 19 Jul 2022 11:12:57 +0200 Subject: [PATCH 04/31] Fix typo (#1017) --- EventFiltering/PWGHF/HFFilter.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/EventFiltering/PWGHF/HFFilter.cxx b/EventFiltering/PWGHF/HFFilter.cxx index 65cbafb6a30..fa32ea04cd5 100644 --- a/EventFiltering/PWGHF/HFFilter.cxx +++ b/EventFiltering/PWGHF/HFFilter.cxx @@ -859,7 +859,7 @@ struct HfFilter { // Main struct for HF triggers continue; } - if (!std::accumulate(isCharmTagged.begin(), isCharmTagged.end(), 0)) { + if (std::accumulate(isCharmTagged.begin(), isCharmTagged.end(), 0)) { n3Prongs++; } // end multiple 3-prong selection From 9275993d5ed0b491f04be6e73bbf440cda39f0c4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mario=20Kr=C3=BCger?= Date: Tue, 19 Jul 2022 11:45:59 +0200 Subject: [PATCH 05/31] PWGLF: use track selection without kinematic cuts (#1018) --- PWGLF/Tasks/spectraCharged.cxx | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/PWGLF/Tasks/spectraCharged.cxx b/PWGLF/Tasks/spectraCharged.cxx index d05e8a7993f..abbd1ec29b4 100644 --- a/PWGLF/Tasks/spectraCharged.cxx +++ b/PWGLF/Tasks/spectraCharged.cxx @@ -250,13 +250,9 @@ bool chargedSpectra::initTrack(const T& track) if (track.pt() <= ptMinCut || track.pt() >= ptMaxCut) { return false; } - // TODO: with Filters we could skip this in data, but not in MC (maybe add IS_MC template paramter so we can skip it in data via if constexpr) - if (!track.isGlobalTrack() || (isRun3 && track.trackType() != o2::aod::track::Track)) { + if (!track.isGlobalTrackWoPtEta()) { return false; - // MEMO: current version of the track selection cuts too harshly (to be studied why) and therefore many events have multMeas==0 - // as temporary workaround to look at unselected tracks use the commented out condition instead } - return true; } From e2f2256c4984a18f525213d0f6462def2bdc028e Mon Sep 17 00:00:00 2001 From: DelloStritto <47105254+DelloStritto@users.noreply.github.com> Date: Tue, 19 Jul 2022 14:19:00 +0200 Subject: [PATCH 06/31] PWGHF: Adding Bayesian PID selections in the Lc->pKpi selector task (#977) --- Common/Core/TrackSelectorPID.h | 80 ++++++++++++++++++- PWGHF/TableProducer/HFLcCandidateSelector.cxx | 59 ++++++++++++-- PWGHF/Tasks/taskLc.cxx | 12 ++- 3 files changed, 140 insertions(+), 11 deletions(-) diff --git a/Common/Core/TrackSelectorPID.h b/Common/Core/TrackSelectorPID.h index 6c0267c3bab..ccb6ae05c4b 100644 --- a/Common/Core/TrackSelectorPID.h +++ b/Common/Core/TrackSelectorPID.h @@ -31,8 +31,8 @@ class TrackSelectorPID /// Standard constructor with PDG code initialisation explicit TrackSelectorPID(int pdg) - : mPdg(std::abs(pdg)) { + setPDG(pdg); } /// Default destructor @@ -46,7 +46,36 @@ class TrackSelectorPID PIDAccepted }; - void setPDG(int pdg) { mPdg = std::abs(pdg); } + void setPDG(int pdg) + { + mPdg = std::abs(pdg); + switch (mPdg) { + case kElectron: { + mSpecies = track::PID::Electron; + break; + } + case kMuonMinus: { + mSpecies = track::PID::Muon; + break; + } + case kPiPlus: { + mSpecies = track::PID::Pion; + break; + } + case kKPlus: { + mSpecies = track::PID::Kaon; + break; + } + case kProton: { + mSpecies = track::PID::Proton; + break; + } + default: { + LOGF(error, "ERROR: Species not implemented for PDG %d", mPdg); + assert(false); + } + } + } // TPC @@ -477,8 +506,51 @@ class TrackSelectorPID return isSelRICH || isSelTOF; } + /// Set pT range where Bayes PID is applicable. + void setRangePtBayes(float ptMin, float ptMax) + { + mPtBayesMin = ptMin; + mPtBayesMax = ptMax; + } + + /// Checks if track is OK for Bayesian PID. + /// \param track track + /// \return true if track is OK for Bayesian PID + template + bool isValidTrackBayesPID(const T& track) + { + auto pt = track.pt(); + return (mPtBayesMin <= pt && pt <= mPtBayesMax); + } + + /// Bayesian maximum probability algorithm. + template + bool isSelectedTrackBayesPID(const T& track) + { + // Get index of the most probable species for a given track. + return track.bayesID() == mSpecies; + } + + /// Returns status of Bayesian PID selection for a given track. + /// \param track track + /// \return Bayesian selection status (see TrackSelectorPID::Status) + template + int getStatusTrackBayesPID(const T& track) + { + if (isValidTrackBayesPID(track)) { + if (isSelectedTrackBayesPID(track)) { + return Status::PIDAccepted; // accepted + } else { + return Status::PIDRejected; // rejected + } + } else { + return Status::PIDNotApplicable; // PID not applicable + } + } + private: uint mPdg = kPiPlus; ///< PDG code of the expected particle + uint mSpecies = track::PID::Pion; ///< Expected species of the track // TPC float mPtTPCMin = 0.; ///< minimum pT for TPC PID [GeV/c] @@ -503,6 +575,10 @@ class TrackSelectorPID float mNSigmaRICHMax = 3.; ///< maximum number of RICH σ float mNSigmaRICHMinCondTOF = -1000.; ///< minimum number of RICH σ if combined with TOF float mNSigmaRICHMaxCondTOF = 1000.; ///< maximum number of RICH σ if combined with TOF + + // Bayesian + float mPtBayesMin = 0.; ///< minimum pT for Bayesian PID [GeV/c] + float mPtBayesMax = 100.; ///< maximum pT for Bayesian PID [GeV/c] }; #endif // O2_ANALYSIS_TRACKSELECTORPID_H_ diff --git a/PWGHF/TableProducer/HFLcCandidateSelector.cxx b/PWGHF/TableProducer/HFLcCandidateSelector.cxx index 808c877cdd3..0a9ebac436c 100644 --- a/PWGHF/TableProducer/HFLcCandidateSelector.cxx +++ b/PWGHF/TableProducer/HFLcCandidateSelector.cxx @@ -33,7 +33,7 @@ struct HFLcCandidateSelector { Configurable d_pTCandMin{"d_pTCandMin", 0., "Lower bound of candidate pT"}; Configurable d_pTCandMax{"d_pTCandMax", 36., "Upper bound of candidate pT"}; - Configurable d_FilterPID{"d_FilterPID", true, "Bool to use or not the PID at filtering level"}; + Configurable d_FilterPID{"d_FilterPID", true, "Bool to use or not the PID based on nSigma cut at filtering level"}; // TPC Configurable d_pidTPCMinpT{"d_pidTPCMinpT", 0.1, "Lower bound of track pT for TPC PID"}; Configurable d_pidTPCMaxpT{"d_pidTPCMaxpT", 1., "Upper bound of track pT for TPC PID"}; @@ -45,6 +45,10 @@ struct HFLcCandidateSelector { Configurable d_pidTOFMaxpT{"d_pidTOFMaxpT", 2.5, "Upper bound of track pT for TOF PID"}; Configurable d_nSigmaTOF{"d_nSigmaTOF", 3., "Nsigma cut on TOF only"}; Configurable d_nSigmaTOFCombined{"d_nSigmaTOFCombined", 5., "Nsigma cut on TOF combined with TPC"}; + // Bayesian + Configurable d_BayesPID{"d_BayesPID", true, "Bool to use or not the PID based on Bayesian probability cut at filtering level"}; + Configurable d_pidBayesMinpT{"d_pidBayesMinpT", 0., "Lower bound of track pT for Bayesian PID"}; + Configurable d_pidBayesMaxpT{"d_pidBayesMaxpT", 100, "Upper bound of track pT for Bayesian PID"}; // topological cuts Configurable> pTBins{"pTBins", std::vector{hf_cuts_lc_topkpi::pTBins_v}, "pT bin limits"}; Configurable> cuts{"Lc_to_p_K_pi_cuts", {hf_cuts_lc_topkpi::cuts[0], npTBins, nCutVars, pTBinLabels, cutVarLabels}, "Lc candidate selection per pT bin"}; @@ -132,7 +136,9 @@ struct HFLcCandidateSelector { return true; } - void process(aod::HfCandProng3 const& candidates, aod::BigTracksPID const&) + using TrksPID = soa::Join; + + void process(aod::HfCandProng3 const& candidates, TrksPID const&) { TrackSelectorPID selectorPion(kPiPlus); selectorPion.setRangePtTPC(d_pidTPCMinpT, d_pidTPCMaxpT); @@ -141,6 +147,7 @@ struct HFLcCandidateSelector { selectorPion.setRangePtTOF(d_pidTOFMinpT, d_pidTOFMaxpT); selectorPion.setRangeNSigmaTOF(-d_nSigmaTOF, d_nSigmaTOF); selectorPion.setRangeNSigmaTOFCondTPC(-d_nSigmaTOFCombined, d_nSigmaTOFCombined); + selectorPion.setRangePtBayes(d_pidBayesMinpT, d_pidBayesMaxpT); TrackSelectorPID selectorKaon(selectorPion); selectorKaon.setPDG(kKPlus); @@ -160,9 +167,9 @@ struct HFLcCandidateSelector { continue; } - auto trackPos1 = candidate.index0_as(); // positive daughter (negative for the antiparticles) - auto trackNeg = candidate.index1_as(); // negative daughter (positive for the antiparticles) - auto trackPos2 = candidate.index2_as(); // positive daughter (negative for the antiparticles) + auto trackPos1 = candidate.index0_as(); // positive daughter (negative for the antiparticles) + auto trackNeg = candidate.index1_as(); // negative daughter (positive for the antiparticles) + auto trackPos2 = candidate.index2_as(); // positive daughter (negative for the antiparticles) /* // daughter track validity selection @@ -192,6 +199,8 @@ struct HFLcCandidateSelector { auto pidLcpKpi = -1; auto pidLcpiKp = -1; + auto pidBayesLcpKpi = -1; + auto pidBayesLcpiKp = -1; if (!d_FilterPID) { // PID non applied @@ -225,15 +234,51 @@ struct HFLcCandidateSelector { } } + if (!d_BayesPID) { + // PID non applied + pidBayesLcpKpi = 1; + pidBayesLcpiKp = 1; + } else { + int pidBayesTrackPos1Proton = selectorProton.getStatusTrackBayesPID(trackPos1); + int pidBayesTrackPos2Proton = selectorProton.getStatusTrackBayesPID(trackPos2); + int pidBayesTrackPos1Pion = selectorPion.getStatusTrackBayesPID(trackPos1); + int pidBayesTrackPos2Pion = selectorPion.getStatusTrackBayesPID(trackPos2); + int pidBayesTrackNegKaon = selectorKaon.getStatusTrackBayesPID(trackNeg); + + if (pidBayesTrackPos1Proton == TrackSelectorPID::Status::PIDAccepted && + pidBayesTrackNegKaon == TrackSelectorPID::Status::PIDAccepted && + pidBayesTrackPos2Pion == TrackSelectorPID::Status::PIDAccepted) { + pidBayesLcpKpi = 1; // accept LcpKpi + } else if (pidBayesTrackPos1Proton == TrackSelectorPID::Status::PIDRejected || + pidBayesTrackNegKaon == TrackSelectorPID::Status::PIDRejected || + pidBayesTrackPos2Pion == TrackSelectorPID::Status::PIDRejected) { + pidBayesLcpKpi = 0; // exclude LcpKpi + } + if (pidBayesTrackPos2Proton == TrackSelectorPID::Status::PIDAccepted && + pidBayesTrackNegKaon == TrackSelectorPID::Status::PIDAccepted && + pidBayesTrackPos1Pion == TrackSelectorPID::Status::PIDAccepted) { + pidBayesLcpiKp = 1; // accept LcpiKp + } else if (pidBayesTrackPos1Pion == TrackSelectorPID::Status::PIDRejected || + pidBayesTrackNegKaon == TrackSelectorPID::Status::PIDRejected || + pidBayesTrackPos2Proton == TrackSelectorPID::Status::PIDRejected) { + pidBayesLcpiKp = 0; // exclude LcpiKp + } + } + if (pidLcpKpi == 0 && pidLcpiKp == 0) { hfSelLcCandidate(statusLcpKpi, statusLcpiKp); continue; } - if ((pidLcpKpi == -1 || pidLcpKpi == 1) && topolLcpKpi) { + if (pidBayesLcpKpi == 0 && pidBayesLcpiKp == 0) { + hfSelLcCandidate(statusLcpKpi, statusLcpiKp); + continue; + } + + if ((pidLcpKpi == -1 || pidLcpKpi == 1) && (pidBayesLcpKpi == -1 || pidBayesLcpKpi == 1) && topolLcpKpi) { statusLcpKpi = 1; // identified as LcpKpi } - if ((pidLcpiKp == -1 || pidLcpiKp == 1) && topolLcpiKp) { + if ((pidLcpiKp == -1 || pidLcpiKp == 1) && (pidBayesLcpiKp == -1 || pidBayesLcpiKp == 1) && topolLcpiKp) { statusLcpiKp = 1; // identified as LcpiKp } diff --git a/PWGHF/Tasks/taskLc.cxx b/PWGHF/Tasks/taskLc.cxx index a79c30973bb..c263e026f48 100644 --- a/PWGHF/Tasks/taskLc.cxx +++ b/PWGHF/Tasks/taskLc.cxx @@ -42,6 +42,10 @@ struct TaskLc { {"hMultiplicity", "multiplicity;multiplicity;entries", {HistType::kTH1F, {{10000, 0., 10000.}}}}, {"hCPARecSig", "3-prong candidates (matched);cosine of pointing angle;entries", {HistType::kTH1F, {{110, -1.1, 1.1}}}}, {"hCPARecBg", "3-prong candidates (unmatched);cosine of pointing angle;entries", {HistType::kTH1F, {{110, -1.1, 1.1}}}}, + {"hDecLengthRecSig", "3-prong candidates (matched);decay length (cm);entries", {HistType::kTH1F, {{200, 0, 1.0}}}}, + {"hDecLengthRecBg", "3-prong candidates (unmatched);decay length (cm);entries", {HistType::kTH1F, {{200, 0, 1.0}}}}, + {"hDca2RecSig", "3-prong candidates (matched);prong Chi2PCA to sec. vertex (cm);entries", {HistType::kTH1F, {{100, 0, 0.5}}}}, + {"hDca2RecBg", "3-prong candidates (unmatched);prong Chi2PCA to sec. vertex (cm);entries", {HistType::kTH1F, {{100, 0, 0.5}}}}, {"hEtaRecSig", "3-prong candidates (matched);#it{#eta};entries", {HistType::kTH1F, {{100, -2., 2.}}}}, {"hEtaRecBg", "3-prong candidates (unmatched);#it{#eta};entries", {HistType::kTH1F, {{100, -2., 2.}}}}, {"hEtaGen", "MC particles (matched);#it{#eta};entries", {HistType::kTH1F, {{100, -2., 2.}}}}}}; @@ -66,7 +70,7 @@ struct TaskLc { registry.add("hSelectionStatus", "3-prong candidates;selection status;entries", {HistType::kTH2F, {{5, -0.5, 4.5}, {vbins, "#it{p}_{T} (GeV/#it{c})"}}}); registry.add("hImpParErr", "3-prong candidates;impact parameter error (cm);entries", {HistType::kTH2F, {{100, -1., 1.}, {vbins, "#it{p}_{T} (GeV/#it{c})"}}}); registry.add("hDecLenErr", "3-prong candidates;decay length error (cm);entries", {HistType::kTH2F, {{100, 0., 1.}, {vbins, "#it{p}_{T} (GeV/#it{c})"}}}); - registry.add("hDCA2", "3-prong candidates;prong Chi2PCA to sec. vertex (cm);entries", {HistType::kTH2F, {{100, 0., 0.5}, {vbins, "#it{p}_{T} (GeV/#it{c})"}}}); + registry.add("hDca2", "3-prong candidates;prong Chi2PCA to sec. vertex (cm);entries", {HistType::kTH2F, {{100, 0., 0.5}, {vbins, "#it{p}_{T} (GeV/#it{c})"}}}); registry.add("hPtRecSig", "3-prong candidates (matched);#it{p}_{T}^{rec.} (GeV/#it{c});entries", {HistType::kTH1F, {{360, 0., 36.}}}); registry.add("hPtRecSigPrompt", "3-prong candidates (matched, prompt);#it{p}_{T}^{rec.} (GeV/#it{c});entries", {HistType::kTH1F, {{360, 0., 36.}}}); @@ -126,7 +130,7 @@ struct TaskLc { registry.fill(HIST("hImpParErr"), candidate.errorImpactParameter1(), candidate.pt()); registry.fill(HIST("hImpParErr"), candidate.errorImpactParameter2(), candidate.pt()); registry.fill(HIST("hDecLenErr"), candidate.errorDecayLength(), candidate.pt()); - registry.fill(HIST("hDecLenErr"), candidate.chi2PCA(), candidate.pt()); + registry.fill(HIST("hDca2"), candidate.chi2PCA(), candidate.pt()); } } @@ -156,10 +160,14 @@ struct TaskLc { registry.fill(HIST("hPtRecSigNonPrompt"), ptRec); // rec. level pT, non-prompt } registry.fill(HIST("hCPARecSig"), candidate.cpa()); + registry.fill(HIST("hDecLengthRecSig"), candidate.decayLength()); + registry.fill(HIST("hDca2RecSig"), candidate.chi2PCA()); registry.fill(HIST("hEtaRecSig"), candidate.eta()); } else { registry.fill(HIST("hPtRecBg"), candidate.pt()); registry.fill(HIST("hCPARecBg"), candidate.cpa()); + registry.fill(HIST("hDecLengthRecBg"), candidate.decayLength()); + registry.fill(HIST("hDca2RecBg"), candidate.chi2PCA()); registry.fill(HIST("hEtaRecBg"), candidate.eta()); } } From 184501f6c98ab50a63cfc794fa58fea4238a5674 Mon Sep 17 00:00:00 2001 From: aimeric-landou <46970521+aimeric-landou@users.noreply.github.com> Date: Tue, 19 Jul 2022 19:46:52 +0100 Subject: [PATCH 07/31] V0 workflows - fix finder for run3 and fix feeddown in analyser and add collision Z selection (#1013) * lambdakzerofinder - add process switch for run2 vs run3 * V0 analysis - add process_switch checks in init() * lambdakzeroanalysisMC - fix feeddown, add col Z cut Co-authored-by: alandou --- PWGLF/TableProducer/lambdakzerobuilder.cxx | 57 ++++++----- PWGLF/TableProducer/lambdakzerofinder.cxx | 49 +++++++++- PWGLF/Tasks/cascadeanalysis.cxx | 27 ++++-- PWGLF/Tasks/lambdakzeroanalysis.cxx | 31 +++--- PWGLF/Tasks/lambdakzeroanalysisMC.cxx | 107 ++++++++++++++++++--- 5 files changed, 207 insertions(+), 64 deletions(-) diff --git a/PWGLF/TableProducer/lambdakzerobuilder.cxx b/PWGLF/TableProducer/lambdakzerobuilder.cxx index 30a9c944aff..9859158521c 100644 --- a/PWGLF/TableProducer/lambdakzerobuilder.cxx +++ b/PWGLF/TableProducer/lambdakzerobuilder.cxx @@ -66,7 +66,7 @@ using namespace o2::framework; using namespace o2::framework::expressions; using std::array; -//use parameters + cov mat non-propagated, aux info + (extension propagated) +// use parameters + cov mat non-propagated, aux info + (extension propagated) using FullTracksExt = soa::Join; using FullTracksExtMC = soa::Join; using FullTracksExtIU = soa::Join; @@ -98,8 +98,8 @@ struct lambdakzeroBuilder { int mRunNumber; float d_bz; - float maxSnp; //max sine phi for propagation - float maxStep; //max step size (cm) for propagation + float maxSnp; // max sine phi for propagation + float maxStep; // max step size (cm) for propagation // for debugging #ifdef MY_DEBUG @@ -141,8 +141,8 @@ struct lambdakzeroBuilder { // using namespace analysis::lambdakzerobuilder; mRunNumber = 0; d_bz = 0; - maxSnp = 0.85f; //could be changed later - maxStep = 2.00f; //could be changed later + maxSnp = 0.85f; // could be changed later + maxStep = 2.00f; // could be changed later ccdb->setURL("http://alice-ccdb.cern.ch"); ccdb->setCaching(true); @@ -160,6 +160,13 @@ struct lambdakzeroBuilder { o2::base::Propagator::initFieldFromGRP(grpo); o2::base::Propagator::Instance()->setMatLUT(lut); } + + if (doprocessRun3 && doprocessRun2) { + LOGF(fatal, "processRun3 and processRun2 are both set to true; try again with only one of them set to true"); + } + if (!doprocessRun3 && !doprocessRun2) { + LOGF(fatal, "processRun3 nor processRun2 are both set to false; try again with only one of them set to false"); + } } float getMagneticField(uint64_t timestamp) @@ -226,7 +233,7 @@ struct lambdakzeroBuilder { #endif MY_DEBUG_MSG(isK0SfromLc, LOG(info) << "V0 builder: found K0S from Lc, posTrack --> " << labelPos << ", negTrack --> " << labelNeg); - //value 0.5: any considered V0 + // value 0.5: any considered V0 registry.fill(HIST("hV0Criteria"), 0.5); if (isRun2) { if (!(V0.posTrack_as().trackType() & o2::aod::track::TPCrefit)) { @@ -240,7 +247,7 @@ struct lambdakzeroBuilder { continue; // TPC refit } } - //Passes TPC refit + // Passes TPC refit registry.fill(HIST("hV0Criteria"), 1.5); if (V0.posTrack_as().tpcNClsCrossedRows() < mincrossedrows) { MY_DEBUG_MSG(isK0SfromLc, LOG(info) << "posTrack " << labelPos << " has " << V0.posTrack_as().tpcNClsCrossedRows() << " crossed rows, cut at " << mincrossedrows); @@ -252,7 +259,7 @@ struct lambdakzeroBuilder { v0dataLink(-1); continue; } - //passes crossed rows + // passes crossed rows registry.fill(HIST("hV0Criteria"), 2.5); if (fabs(V0.posTrack_as().dcaXY()) < dcapostopv) { MY_DEBUG_MSG(isK0SfromLc, LOG(info) << "posTrack " << labelPos << " has dcaXY " << V0.posTrack_as().dcaXY() << " , cut at " << dcanegtopv); @@ -265,7 +272,7 @@ struct lambdakzeroBuilder { continue; } MY_DEBUG_MSG(isK0SfromLc, LOG(info) << "Filling good indices: posTrack --> " << labelPos << ", negTrack --> " << labelNeg); - //passes DCAxy + // passes DCAxy registry.fill(HIST("hV0Criteria"), 3.5); // Candidate building part @@ -290,7 +297,7 @@ struct lambdakzeroBuilder { continue; } - //passes diff coll check + // passes diff coll check registry.fill(HIST("hV0Criteria"), 4.5); // Act on copies for minimization @@ -305,7 +312,7 @@ struct lambdakzeroBuilder { continue; } - //passes V0 fitter minimization successfully + // passes V0 fitter minimization successfully registry.fill(HIST("hV0Criteria"), 5.5); double finalXpos = fitter.getTrack(0).getX(); @@ -331,7 +338,7 @@ struct lambdakzeroBuilder { continue; } - //Passes step 2 of V0 fitter + // Passes step 2 of V0 fitter registry.fill(HIST("hV0Criteria"), 6.5); pTrack.getPxPyPzGlo(pvec0); @@ -351,7 +358,7 @@ struct lambdakzeroBuilder { continue; } - //Passes DCA between daughters check + // Passes DCA between daughters check registry.fill(HIST("hV0Criteria"), 7.5); auto V0CosinePA = RecoDecay::cpa(array{collision.posX(), collision.posY(), collision.posZ()}, array{pos[0], pos[1], pos[2]}, array{pvec0[0] + pvec1[0], pvec0[1] + pvec1[1], pvec0[2] + pvec1[2]}); @@ -361,7 +368,7 @@ struct lambdakzeroBuilder { continue; } - //Passes CosPA check + // Passes CosPA check registry.fill(HIST("hV0Criteria"), 8.5); auto V0radius = RecoDecay::sqrtSumOfSquares(pos[0], pos[1]); // probably find better name to differentiate the cut from the variable @@ -371,7 +378,7 @@ struct lambdakzeroBuilder { continue; } - //Passes radius check + // Passes radius check registry.fill(HIST("hV0Criteria"), 9.5); MY_DEBUG_MSG(isK0SfromLc, LOG(info) << "in builder 1, keeping K0S candidate: posTrack --> " << labelPos << ", negTrack --> " << labelNeg); @@ -428,7 +435,7 @@ struct lambdakzeroBuilder { #endif MY_DEBUG_MSG(isK0SfromLc, LOG(info) << "V0 builder: found K0S from Lc, posTrack --> " << labelPos << ", negTrack --> " << labelNeg); - //value 0.5: any considered V0 + // value 0.5: any considered V0 registry.fill(HIST("hV0Criteria"), 0.5); if (isRun2) { if (!(V0.posTrack_as().trackType() & o2::aod::track::TPCrefit)) { @@ -442,7 +449,7 @@ struct lambdakzeroBuilder { continue; // TPC refit } } - //Passes TPC refit + // Passes TPC refit registry.fill(HIST("hV0Criteria"), 1.5); if (V0.posTrack_as().tpcNClsCrossedRows() < mincrossedrows) { MY_DEBUG_MSG(isK0SfromLc, LOG(info) << "posTrack " << labelPos << " has " << V0.posTrack_as().tpcNClsCrossedRows() << " crossed rows, cut at " << mincrossedrows); @@ -454,7 +461,7 @@ struct lambdakzeroBuilder { v0dataLink(-1); continue; } - //passes crossed rows + // passes crossed rows registry.fill(HIST("hV0Criteria"), 2.5); if (fabs(V0.posTrack_as().dcaXY()) < dcapostopv) { MY_DEBUG_MSG(isK0SfromLc, LOG(info) << "posTrack " << labelPos << " has dcaXY " << V0.posTrack_as().dcaXY() << " , cut at " << dcanegtopv); @@ -467,7 +474,7 @@ struct lambdakzeroBuilder { continue; } MY_DEBUG_MSG(isK0SfromLc, LOG(info) << "Filling good indices: posTrack --> " << labelPos << ", negTrack --> " << labelNeg); - //passes DCAxy + // passes DCAxy registry.fill(HIST("hV0Criteria"), 3.5); // Candidate building part @@ -492,7 +499,7 @@ struct lambdakzeroBuilder { continue; } - //passes diff coll check + // passes diff coll check registry.fill(HIST("hV0Criteria"), 4.5); // Act on copies for minimization @@ -507,7 +514,7 @@ struct lambdakzeroBuilder { continue; } - //passes V0 fitter minimization successfully + // passes V0 fitter minimization successfully registry.fill(HIST("hV0Criteria"), 5.5); double finalXpos = fitter.getTrack(0).getX(); @@ -533,7 +540,7 @@ struct lambdakzeroBuilder { continue; } - //Passes step 2 of V0 fitter + // Passes step 2 of V0 fitter registry.fill(HIST("hV0Criteria"), 6.5); pTrack.getPxPyPzGlo(pvec0); @@ -553,7 +560,7 @@ struct lambdakzeroBuilder { continue; } - //Passes DCA between daughters check + // Passes DCA between daughters check registry.fill(HIST("hV0Criteria"), 7.5); auto V0CosinePA = RecoDecay::cpa(array{collision.posX(), collision.posY(), collision.posZ()}, array{pos[0], pos[1], pos[2]}, array{pvec0[0] + pvec1[0], pvec0[1] + pvec1[1], pvec0[2] + pvec1[2]}); @@ -563,7 +570,7 @@ struct lambdakzeroBuilder { continue; } - //Passes CosPA check + // Passes CosPA check registry.fill(HIST("hV0Criteria"), 8.5); auto V0radius = RecoDecay::sqrtSumOfSquares(pos[0], pos[1]); // probably find better name to differentiate the cut from the variable @@ -573,7 +580,7 @@ struct lambdakzeroBuilder { continue; } - //Passes radius check + // Passes radius check registry.fill(HIST("hV0Criteria"), 9.5); MY_DEBUG_MSG(isK0SfromLc, LOG(info) << "in builder 1, keeping K0S candidate: posTrack --> " << labelPos << ", negTrack --> " << labelNeg); diff --git a/PWGLF/TableProducer/lambdakzerofinder.cxx b/PWGLF/TableProducer/lambdakzerofinder.cxx index 784dcfc9724..64b3eac95ac 100644 --- a/PWGLF/TableProducer/lambdakzerofinder.cxx +++ b/PWGLF/TableProducer/lambdakzerofinder.cxx @@ -251,7 +251,7 @@ struct lambdakzerofinder { } }; -struct lambdakzerofinderQA { +struct lambdakzerofinderQa { // Basic checks // Selection criteria Configurable v0cospa{"v0cospa", 0.998, "V0 CosPA"}; // double -> N.B. dcos(x)/dx = 0 at x=0) @@ -277,11 +277,51 @@ struct lambdakzerofinderQA { }, }; + void init(InitContext const&) + { + if (doprocessRun3 && doprocessRun2) { + LOGF(fatal, "processRun3 and processRun2 are both set to true; try again with only one of them set to true"); + } + if (!doprocessRun3 && !doprocessRun2) { + LOGF(fatal, "processRun3 nor processRun2 are both set to false; try again with only one of them set to false"); + } + } + Filter preFilterV0 = nabs(aod::v0data::dcapostopv) > dcapostopv&& nabs(aod::v0data::dcanegtopv) > dcanegtopv&& aod::v0data::dcaV0daughters < dcav0dau; /// Connect to V0Data: newly indexed, note: V0Datas table incompatible with standard V0 table! - void process(soa::Join::iterator const& collision, - soa::Filtered const& fullV0s) + void processRun3(soa::Join::iterator const& collision, + soa::Filtered const& fullV0s) + { + if (!collision.sel8()) { + return; + } + + Long_t lNCand = 0; + for (auto& v0 : fullV0s) { + if (v0.v0radius() > v0radius && v0.v0cosPA(collision.posX(), collision.posY(), collision.posZ()) > v0cospa) { + registry.fill(HIST("hV0Radius"), v0.v0radius()); + registry.fill(HIST("hV0CosPA"), v0.v0cosPA(collision.posX(), collision.posY(), collision.posZ())); + registry.fill(HIST("hDCAPosToPV"), v0.dcapostopv()); + registry.fill(HIST("hDCANegToPV"), v0.dcanegtopv()); + registry.fill(HIST("hDCAV0Dau"), v0.dcaV0daughters()); + + if (TMath::Abs(v0.yLambda()) < 0.5) { + registry.fill(HIST("h3dMassLambda"), collision.centFV0A(), v0.pt(), v0.mLambda()); + registry.fill(HIST("h3dMassAntiLambda"), collision.centFV0A(), v0.pt(), v0.mAntiLambda()); + } + if (TMath::Abs(v0.yK0Short()) < 0.5) { + registry.fill(HIST("h3dMassK0Short"), collision.centFV0A(), v0.pt(), v0.mK0Short()); + } + lNCand++; + } + } + registry.fill(HIST("hCandPerEvent"), lNCand); + } + PROCESS_SWITCH(lambdakzerofinderQa, processRun3, "Process Run 3 data", true); + + void processRun2(soa::Join::iterator const& collision, + soa::Filtered const& fullV0s) { if (!collision.alias()[kINT7]) { return; @@ -311,6 +351,7 @@ struct lambdakzerofinderQA { } registry.fill(HIST("hCandPerEvent"), lNCand); } + PROCESS_SWITCH(lambdakzerofinderQa, processRun2, "Process Run 2 data", false); }; /// Extends the v0data table with expression columns @@ -324,6 +365,6 @@ WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) return WorkflowSpec{ adaptAnalysisTask(cfgc, TaskName{"lf-lambdakzeroprefilter"}), adaptAnalysisTask(cfgc, TaskName{"lf-lambdakzerofinder"}), - adaptAnalysisTask(cfgc, TaskName{"lf-lambdakzerofinderQA"}), + adaptAnalysisTask(cfgc, TaskName{"lf-lambdakzerofinderQA"}), adaptAnalysisTask(cfgc, TaskName{"lf-lambdakzeroinitializer"})}; } diff --git a/PWGLF/Tasks/cascadeanalysis.cxx b/PWGLF/Tasks/cascadeanalysis.cxx index 38d1972dcaf..f3f74e9694f 100644 --- a/PWGLF/Tasks/cascadeanalysis.cxx +++ b/PWGLF/Tasks/cascadeanalysis.cxx @@ -53,7 +53,7 @@ using namespace o2::framework::expressions; using std::array; struct cascadeQa { - //Basic checks + // Basic checks HistogramRegistry registry{ "registry", { @@ -79,14 +79,14 @@ struct cascadeQa { void process(aod::Collision const& collision, aod::CascDataExt const& Cascades) { for (auto& casc : Cascades) { - if (casc.sign() < 0) { //FIXME: could be done better... + if (casc.sign() < 0) { // FIXME: could be done better... registry.fill(HIST("hMassXiMinus"), casc.mXi()); registry.fill(HIST("hMassOmegaMinus"), casc.mOmega()); } else { registry.fill(HIST("hMassXiPlus"), casc.mXi()); registry.fill(HIST("hMassOmegaPlus"), casc.mOmega()); } - //The basic eleven! + // The basic eleven! registry.fill(HIST("hV0Radius"), casc.v0radius()); registry.fill(HIST("hCascRadius"), casc.cascradius()); registry.fill(HIST("hV0CosPA"), casc.v0cosPA(collision.posX(), collision.posY(), collision.posZ())); @@ -119,11 +119,18 @@ struct cascadeAnalysis { registry.add("h3dMassXiPlus", "h3dMassXiPlus", {HistType::kTH3F, {centAxis, ptAxis, massAxisXi}}); registry.add("h3dMassOmegaMinus", "h3dMassOmegaMinus", {HistType::kTH3F, {centAxis, ptAxis, massAxisOmega}}); registry.add("h3dMassOmegaPlus", "h3dMassOmegaPlus", {HistType::kTH3F, {centAxis, ptAxis, massAxisOmega}}); + + if (doprocessRun3 && doprocessRun2) { + LOGF(fatal, "processRun3 and processRun2 are both set to true; try again with only one of them set to true"); + } + if (!doprocessRun3 && !doprocessRun2) { + LOGF(fatal, "processRun3 nor processRun2 are both set to false; try again with only one of them set to false"); + } } - //Selection criteria - Configurable v0cospa{"v0cospa", 0.999, "V0 CosPA"}; //double -> N.B. dcos(x)/dx = 0 at x=0) - Configurable casccospa{"casccospa", 0.999, "Casc CosPA"}; //double -> N.B. dcos(x)/dx = 0 at x=0) + // Selection criteria + Configurable v0cospa{"v0cospa", 0.999, "V0 CosPA"}; // double -> N.B. dcos(x)/dx = 0 at x=0) + Configurable casccospa{"casccospa", 0.999, "Casc CosPA"}; // double -> N.B. dcos(x)/dx = 0 at x=0) Configurable dcav0dau{"dcav0dau", 1.0, "DCA V0 Daughters"}; Configurable dcacascdau{"dcacascdau", .3, "DCA Casc Daughters"}; Configurable dcanegtopv{"dcanegtopv", .1, "DCA Neg To PV"}; @@ -145,13 +152,13 @@ struct cascadeAnalysis { return; } for (auto& casc : Cascades) { - //FIXME: dynamic columns cannot be filtered on? + // FIXME: dynamic columns cannot be filtered on? if (casc.v0radius() > v0radius && casc.cascradius() > cascradius && casc.v0cosPA(collision.posX(), collision.posY(), collision.posZ()) > v0cospa && casc.casccosPA(collision.posX(), collision.posY(), collision.posZ()) > casccospa && casc.dcav0topv(collision.posX(), collision.posY(), collision.posZ()) > dcav0topv) { - if (casc.sign() < 0) { //FIXME: could be done better... + if (casc.sign() < 0) { // FIXME: could be done better... if (TMath::Abs(casc.yXi()) < 0.5) { registry.fill(HIST("h3dMassXiMinus"), 0., casc.pt(), casc.mXi()); } @@ -180,13 +187,13 @@ struct cascadeAnalysis { return; } for (auto& casc : Cascades) { - //FIXME: dynamic columns cannot be filtered on? + // FIXME: dynamic columns cannot be filtered on? if (casc.v0radius() > v0radius && casc.cascradius() > cascradius && casc.v0cosPA(collision.posX(), collision.posY(), collision.posZ()) > v0cospa && casc.casccosPA(collision.posX(), collision.posY(), collision.posZ()) > casccospa && casc.dcav0topv(collision.posX(), collision.posY(), collision.posZ()) > dcav0topv) { - if (casc.sign() < 0) { //FIXME: could be done better... + if (casc.sign() < 0) { // FIXME: could be done better... if (TMath::Abs(casc.yXi()) < 0.5) { registry.fill(HIST("h3dMassXiMinus"), collision.centRun2V0M(), casc.pt(), casc.mXi()); } diff --git a/PWGLF/Tasks/lambdakzeroanalysis.cxx b/PWGLF/Tasks/lambdakzeroanalysis.cxx index 3c97d6e9841..3323a117d09 100644 --- a/PWGLF/Tasks/lambdakzeroanalysis.cxx +++ b/PWGLF/Tasks/lambdakzeroanalysis.cxx @@ -55,7 +55,7 @@ using std::array; using MyTracks = soa::Join; struct lambdakzeroQa { - //Basic checks + // Basic checks HistogramRegistry registry{ "registry", { @@ -120,10 +120,17 @@ struct lambdakzeroAnalysis { registry.add("h3dMassK0ShortDca", "h3dMassK0ShortDca", {HistType::kTH3F, {dcaAxis, ptAxis, massAxisK0Short}}); registry.add("h3dMassLambdaDca", "h3dMassLambdaDca", {HistType::kTH3F, {dcaAxis, ptAxis, massAxisLambda}}); registry.add("h3dMassAntiLambdaDca", "h3dMassAntiLambdaDca", {HistType::kTH3F, {dcaAxis, ptAxis, massAxisLambda}}); + + if (doprocessRun3 && doprocessRun2) { + LOGF(fatal, "processRun3 and processRun2 are both set to true; try again with only one of them set to true"); + } + if (!doprocessRun3 && !doprocessRun2) { + LOGF(fatal, "processRun3 nor processRun2 are both set to false; try again with only one of them set to false"); + } } - //Selection criteria - Configurable v0cospa{"v0cospa", 0.995, "V0 CosPA"}; //double -> N.B. dcos(x)/dx = 0 at x=0) + // Selection criteria + Configurable v0cospa{"v0cospa", 0.995, "V0 CosPA"}; // double -> N.B. dcos(x)/dx = 0 at x=0) Configurable dcav0dau{"dcav0dau", 1.0, "DCA V0 Daughters"}; Configurable dcanegtopv{"dcanegtopv", .1, "DCA Neg To PV"}; Configurable dcapostopv{"dcapostopv", .1, "DCA Pos To PV"}; @@ -149,14 +156,14 @@ struct lambdakzeroAnalysis { registry.fill(HIST("hSelectedEventCounter"), 0.5); for (auto& v0 : fullV0s) { - //FIXME: could not find out how to filter cosPA and radius variables (dynamic columns) + // FIXME: could not find out how to filter cosPA and radius variables (dynamic columns) if (v0.v0radius() > v0radius && v0.v0cosPA(collision.posX(), collision.posY(), collision.posZ()) > v0cospa) { if (TMath::Abs(v0.yLambda()) < rapidity) { if (v0.distovertotmom(collision.posX(), collision.posY(), collision.posZ()) * RecoDecay::getMassPDG(kLambda0) < lifetimecut->get("lifetimecutLambda")) { // Lambda - if (TMath::Abs(v0.posTrack_as().tpcNSigmaPr()) < TpcPidNsigmaCut) { //previous 900Gev pp analysis had nSigma< 5 for pt<0.7Gev and tpcNSigmaStorePi<3 for pt>0.7GeV; and no cut on K0S - registry.fill(HIST("h3dMassLambda"), 0., v0.pt(), v0.mLambda()); //collision.centV0M() instead of 0. once available + if (TMath::Abs(v0.posTrack_as().tpcNSigmaPr()) < TpcPidNsigmaCut) { // previous 900Gev pp analysis had nSigma< 5 for pt<0.7Gev and tpcNSigmaStorePi<3 for pt>0.7GeV; and no cut on K0S + registry.fill(HIST("h3dMassLambda"), 0., v0.pt(), v0.mLambda()); // collision.centV0M() instead of 0. once available registry.fill(HIST("hArmenterosPostAnalyserCuts"), v0.alpha(), v0.qtarm()); if (saveDcaHist == 1) { registry.fill(HIST("h3dMassLambdaDca"), v0.dcaV0daughters(), v0.pt(), v0.mLambda()); @@ -164,7 +171,7 @@ struct lambdakzeroAnalysis { } // AntiLambda - if (TMath::Abs(v0.negTrack_as().tpcNSigmaPr()) < TpcPidNsigmaCut) { //previous 900Gev pp analysis had nSigma< 5 for pt<0.7Gev and tpcNSigmaStorePi<3 for pt>0.7GeV; and no cut on K0S + if (TMath::Abs(v0.negTrack_as().tpcNSigmaPr()) < TpcPidNsigmaCut) { // previous 900Gev pp analysis had nSigma< 5 for pt<0.7Gev and tpcNSigmaStorePi<3 for pt>0.7GeV; and no cut on K0S registry.fill(HIST("h3dMassAntiLambda"), 0., v0.pt(), v0.mAntiLambda()); registry.fill(HIST("hArmenterosPostAnalyserCuts"), v0.alpha(), v0.qtarm()); if (saveDcaHist == 1) { @@ -174,7 +181,7 @@ struct lambdakzeroAnalysis { } } - //K0Short + // K0Short if (TMath::Abs(v0.yK0Short()) < rapidity) { if (v0.distovertotmom(collision.posX(), collision.posY(), collision.posZ()) * RecoDecay::getMassPDG(kK0Short) < lifetimecut->get("lifetimecutK0S")) { if ((v0.qtarm() > paramArmenterosCut * TMath::Abs(v0.alpha())) || !boolArmenterosCut) { @@ -202,13 +209,13 @@ struct lambdakzeroAnalysis { registry.fill(HIST("hSelectedEventCounter"), 0.5); for (auto& v0 : fullV0s) { - //FIXME: could not find out how to filter cosPA and radius variables (dynamic columns) + // FIXME: could not find out how to filter cosPA and radius variables (dynamic columns) if (v0.v0radius() > v0radius && v0.v0cosPA(collision.posX(), collision.posY(), collision.posZ()) > v0cospa) { if (TMath::Abs(v0.yLambda()) < rapidity) { if (v0.distovertotmom(collision.posX(), collision.posY(), collision.posZ()) * RecoDecay::getMassPDG(kLambda0) < lifetimecut->get("lifetimecutLambda")) { // Lambda - if (TMath::Abs(v0.posTrack_as().tpcNSigmaPr()) < TpcPidNsigmaCut) { //previous 900Gev pp analysis had nSigma< 5 for pt<0.7Gev and tpcNSigmaStorePi<3 for pt>0.7GeV; and no cut on K0S + if (TMath::Abs(v0.posTrack_as().tpcNSigmaPr()) < TpcPidNsigmaCut) { // previous 900Gev pp analysis had nSigma< 5 for pt<0.7Gev and tpcNSigmaStorePi<3 for pt>0.7GeV; and no cut on K0S registry.fill(HIST("h3dMassLambda"), collision.centRun2V0M(), v0.pt(), v0.mLambda()); registry.fill(HIST("hArmenterosPostAnalyserCuts"), v0.alpha(), v0.qtarm()); if (saveDcaHist == 1) { @@ -217,7 +224,7 @@ struct lambdakzeroAnalysis { } // AntiLambda - if (TMath::Abs(v0.negTrack_as().tpcNSigmaPr()) < TpcPidNsigmaCut) { //previous 900Gev pp analysis had nSigma< 5 for pt<0.7Gev and tpcNSigmaStorePi<3 for pt>0.7GeV; and no cut on K0S + if (TMath::Abs(v0.negTrack_as().tpcNSigmaPr()) < TpcPidNsigmaCut) { // previous 900Gev pp analysis had nSigma< 5 for pt<0.7Gev and tpcNSigmaStorePi<3 for pt>0.7GeV; and no cut on K0S registry.fill(HIST("h3dMassAntiLambda"), collision.centRun2V0M(), v0.pt(), v0.mAntiLambda()); registry.fill(HIST("hArmenterosPostAnalyserCuts"), v0.alpha(), v0.qtarm()); if (saveDcaHist == 1) { @@ -227,7 +234,7 @@ struct lambdakzeroAnalysis { } } - //K0Short + // K0Short if (TMath::Abs(v0.yK0Short()) < rapidity) { if (v0.distovertotmom(collision.posX(), collision.posY(), collision.posZ()) * RecoDecay::getMassPDG(kK0Short) < lifetimecut->get("lifetimecutK0S")) { if ((v0.qtarm() > paramArmenterosCut * v0.alpha()) || !boolArmenterosCut) { diff --git a/PWGLF/Tasks/lambdakzeroanalysisMC.cxx b/PWGLF/Tasks/lambdakzeroanalysisMC.cxx index 0c558e21097..a52c7e7870a 100644 --- a/PWGLF/Tasks/lambdakzeroanalysisMC.cxx +++ b/PWGLF/Tasks/lambdakzeroanalysisMC.cxx @@ -56,7 +56,7 @@ using std::array; using MyTracks = soa::Join; struct lambdakzeroQa { - //Basic checks + // Basic checks HistogramRegistry registry{ "registry", { @@ -69,6 +69,8 @@ struct lambdakzeroQa { {"hDCANegToPV", "hDCANegToPV", {HistType::kTH1F, {{1000, -10.0f, 10.0f, "cm"}}}}, {"hDCAV0Dau", "hDCAV0Dau", {HistType::kTH1F, {{1000, 0.0f, 10.0f, "cm^{2}"}}}}, {"hArmenterosPreAnalyserCuts", "hArmenterosPreAnalyserCuts", {HistType::kTH2F, {{1000, -1.0f, 1.0f, "#alpha"}, {1000, 0.0f, 0.30f, "#it{Q}_{T}"}}}}, + + {"hCollisionZ", "hCollisionZ", {HistType::kTH1F, {{3000, -30.0f, 30.0f, "cm"}}}}, }, }; @@ -84,6 +86,7 @@ struct lambdakzeroQa { void process(aod::Collision const& collision, aod::V0Datas const& fullV0s, aod::McParticles const& mcParticles, MyTracks const& tracks) { + registry.fill(HIST("hCollisionZ"), collision.posZ()); for (auto& v0 : fullV0s) { registry.fill(HIST("hMassK0Short"), v0.mK0Short()); registry.fill(HIST("hMassLambda"), v0.mLambda()); @@ -125,10 +128,10 @@ struct lambdakzeroAnalysisMc { HistogramRegistry registry{ "registry", { - {"h3dMassK0Short", "h3dMassK0Short", {HistType::kTH3F, {{20, 0.0f, 100.0f, "Cent (%)"}, {200, 0.0f, 10.0f, "#it{p}_{T} (GeV/c)"}, {200, 0.450f, 0.550f, "Inv. Mass (GeV/c^{2})"}}}}, + {"h3dMassK0Short", "h3dMassK0Short", {HistType::kTH3F, {{20, 0.0f, 100.0f, "Cent (%)"}, {200, 0.0f, 10.0f, "#it{p}_{T} (GeV/c)"}, {400, 0.400f, 0.600f, "Inv. Mass (GeV/c^{2})"}}}}, {"h3dMassLambda", "h3dMassLambda", {HistType::kTH3F, {{20, 0.0f, 100.0f, "Cent (%)"}, {200, 0.0f, 10.0f, "#it{p}_{T} (GeV/c)"}, {200, 1.015f, 1.215f, "Inv. Mass (GeV/c^{2})"}}}}, {"h3dMassAntiLambda", "h3dMassAntiLambda", {HistType::kTH3F, {{20, 0.0f, 100.0f, "Cent (%)"}, {200, 0.0f, 10.0f, "#it{p}_{T} (GeV/c)"}, {200, 1.015f, 1.215f, "Inv. Mass (GeV/c^{2})"}}}}, - {"h3dMassK0Short_MC_truePt", "h3dMassK0Short_MC_truePt", {HistType::kTH3F, {{20, 0.0f, 100.0f, "Cent (%)"}, {200, 0.0f, 10.0f, "#it{p}_{T} (GeV/c)"}, {200, 0.450f, 0.550f, "Inv. Mass (GeV/c^{2})"}}}}, + {"h3dMassK0Short_MC_truePt", "h3dMassK0Short_MC_truePt", {HistType::kTH3F, {{20, 0.0f, 100.0f, "Cent (%)"}, {200, 0.0f, 10.0f, "#it{p}_{T} (GeV/c)"}, {400, 0.400f, 0.600f, "Inv. Mass (GeV/c^{2})"}}}}, {"h3dMassLambda_MC_truePt", "h3dMassLambda_MC_truePt", {HistType::kTH3F, {{20, 0.0f, 100.0f, "Cent (%)"}, {200, 0.0f, 10.0f, "#it{p}_{T} (GeV/c)"}, {200, 1.015f, 1.215f, "Inv. Mass (GeV/c^{2})"}}}}, {"h3dMassAntiLambda_MC_truePt", "h3dMassAntiLambda_MC_truePt", {HistType::kTH3F, {{20, 0.0f, 100.0f, "Cent (%)"}, {200, 0.0f, 10.0f, "#it{p}_{T} (GeV/c)"}, {200, 1.015f, 1.215f, "Inv. Mass (GeV/c^{2})"}}}}, {"MCmomID_Lambda", "MCmomID_Lambda", {HistType::kTH1I, {{4000000, 0, 4000000}}}}, @@ -139,6 +142,7 @@ struct lambdakzeroAnalysisMc { {"hLambdaFeedDownMatrix", "hLambdaFeedDownMatrix", {HistType::kTH2F, {{200, 0.0f, 10.0f, "#it{p}_{T}^{#Lambda} (GeV/c)"}, {200, 0.0f, 10.0f, "#it{p}_{T}^{#Omega-} (GeV/c)"}}}}, {"hAntiLambdaFeedDownMatrix", "hAntiLambdaFeedDownMatrix", {HistType::kTH2F, {{200, 0.0f, 10.0f, "#it{p}_{T}^{#bar{#Lambda}} (GeV/c)"}, {200, 0.0f, 10.0f, "#it{p}_{T}^{#Omega+} (GeV/c)"}}}}, + {"hSel8Counter", "hSel8Counter", {HistType::kTH1F, {{1, 0.0f, 1.0f}}}}, {"hSelectedEventCounter", "hSelectedEventCounter", {HistType::kTH1F, {{1, 0.0f, 1.0f}}}}, {"hArmenterosPostAnalyserCuts", "hArmenterosPostAnalyserCuts", {HistType::kTH2F, {{1000, -1.0f, 1.0f, "#alpha"}, {1000, 0.0f, 0.30f, "#it{Q}_{T}"}}}}, @@ -149,11 +153,12 @@ struct lambdakzeroAnalysisMc { ConfigurableAxis dcaBinning{"dca-binning", {200, 0.0f, 1.0f}, ""}; ConfigurableAxis ptBinning{"pt-binning", {200, 0.0f, 10.0f}, ""}; - ConfigurableAxis massK0Shortbinning{"K0S-mass-binning", {200, 0.450f, 0.550f}, ""}; + ConfigurableAxis massK0Shortbinning{"K0S-mass-binning", {400, 0.400f, 0.600f}, ""}; ConfigurableAxis massLambdabinning{"Lambda-mass-binning", {200, 1.015f, 1.215f}, ""}; void init(InitContext const&) { + AxisSpec dcaAxis = {dcaBinning, "DCA (cm)"}; AxisSpec ptAxis = {ptBinning, "#it{p}_{T} (GeV/c)"}; AxisSpec massAxisK0Short = {massK0Shortbinning, "Inv. Mass (GeV/c^{2})"}; @@ -174,10 +179,17 @@ struct lambdakzeroAnalysisMc { registry.get(HIST("V0loopFiltersCounts"))->GetXaxis()->SetBinLabel(8, "K0S Rapidity"); registry.get(HIST("V0loopFiltersCounts"))->GetXaxis()->SetBinLabel(9, "K0S lifetime cut"); registry.get(HIST("V0loopFiltersCounts"))->GetXaxis()->SetBinLabel(10, "K0S Armenteros cut"); + + if (doprocessRun3 && doprocessRun2) { + LOGF(fatal, "processRun3 and processRun2 are both set to true; try again with only one of them set to true"); + } + if (!doprocessRun3 && !doprocessRun2) { + LOGF(fatal, "processRun3 nor processRun2 are both set to false; try again with only one of them set to false"); + } } - //Selection criteria - Configurable v0cospa{"v0cospa", 0.995, "V0 CosPA"}; //double -> N.B. dcos(x)/dx = 0 at x=0) + // Selection criteria + Configurable v0cospa{"v0cospa", 0.995, "V0 CosPA"}; // double -> N.B. dcos(x)/dx = 0 at x=0) Configurable dcav0dau{"dcav0dau", 1.0, "DCA V0 Daughters"}; Configurable dcanegtopv{"dcanegtopv", .1, "DCA Neg To PV"}; Configurable dcapostopv{"dcapostopv", .1, "DCA Pos To PV"}; @@ -188,6 +200,7 @@ struct lambdakzeroAnalysisMc { Configurable boolArmenterosCut{"boolArmenterosCut", true, "cut on Armenteros-Podolanski graph"}; Configurable paramArmenterosCut{"paramArmenterosCut", 0.2, "parameter Armenteros Cut"}; Configurable eventSelection{"eventSelection", true, "event selection"}; + Configurable eventSelection_posZ{"eventSelection_posZ", true, "event selection count post poZ cut"}; Configurable hasItsTest{"hasItsTest", false, "hasItsTest"}; @@ -202,6 +215,11 @@ struct lambdakzeroAnalysisMc { if (eventSelection && !collision.sel8()) { return; } + registry.fill(HIST("hSel8Counter"), 0.5); + + if (eventSelection_posZ && abs(collision.posZ()) > 10.f) { // 10cm + return; + } registry.fill(HIST("hSelectedEventCounter"), 0.5); for (auto& v0 : fullV0s) { @@ -215,6 +233,7 @@ struct lambdakzeroAnalysisMc { if (!reconegtrack.has_mcParticle() || !recopostrack.has_mcParticle()) { continue; } + auto mcnegtrack = reconegtrack.mcParticle_as(); auto mcpostrack = recopostrack.mcParticle_as(); @@ -223,8 +242,8 @@ struct lambdakzeroAnalysisMc { if (v0.distovertotmom(collision.posX(), collision.posY(), collision.posZ()) * RecoDecay::getMassPDG(kLambda0) < lifetimecut->get("lifetimecutLambda")) { registry.fill(HIST("V0loopFiltersCounts"), 4.5); - //Lambda - if (TMath::Abs(v0.posTrack_as().tpcNSigmaPr()) < TpcPidNsigmaCut) { //previous 900Gev pp analysis had nSigma< 5 for pt<0.7Gev and tpcNSigmaStorePr<3 for pt>0.7GeV; and no cut on K0S + // Lambda + if (TMath::Abs(v0.posTrack_as().tpcNSigmaPr()) < TpcPidNsigmaCut) { // previous 900Gev pp analysis had nSigma< 5 for pt<0.7Gev and tpcNSigmaStorePr<3 for pt>0.7GeV; and no cut on K0S registry.fill(HIST("V0loopFiltersCounts"), 5.5); // registry.fill(HIST("h3dMassLambda"), collision.centV0M(), v0.pt(), v0.mLambda()); registry.fill(HIST("h3dMassLambda"), 0., v0.pt(), v0.mLambda()); @@ -240,7 +259,7 @@ struct lambdakzeroAnalysisMc { if (particleMotherOfNeg.has_mothers()) { auto particleGrandMothersOfNegTable = particleMotherOfNeg.mothers_as(); auto particleGrandMotherOfNeg = particleGrandMothersOfNegTable[0]; - if (particleGrandMotherOfNeg.pdgCode() == 3312) { + if (particleGrandMotherOfNeg.pdgCode() == 3312 || particleGrandMotherOfNeg.pdgCode() == 3322) { registry.fill(HIST("hLambdaFeedDownMatrix"), particleMotherOfNeg.pt(), particleGrandMotherOfNeg.pt()); } } @@ -257,7 +276,7 @@ struct lambdakzeroAnalysisMc { } // AntiLambda - if (TMath::Abs(v0.negTrack_as().tpcNSigmaPr()) < TpcPidNsigmaCut) { //previous 900Gev pp analysis had nSigma< 5 for pt<0.7Gev and tpcNSigmaStorePr<3 for pt>0.7GeV; and no cut on K0S + if (TMath::Abs(v0.negTrack_as().tpcNSigmaPr()) < TpcPidNsigmaCut) { // previous 900Gev pp analysis had nSigma< 5 for pt<0.7Gev and tpcNSigmaStorePr<3 for pt>0.7GeV; and no cut on K0S registry.fill(HIST("V0loopFiltersCounts"), 5.5); // registry.fill(HIST("h3dMassLambda"), collision.centV0M(), v0.pt(), v0.mLambda()); registry.fill(HIST("h3dMassAntiLambda"), 0., v0.pt(), v0.mAntiLambda()); @@ -273,7 +292,7 @@ struct lambdakzeroAnalysisMc { if (particleMotherOfNeg.has_mothers()) { auto particleGrandMothersOfNegTable = particleMotherOfNeg.mothers_as(); auto particleGrandMotherOfNeg = particleGrandMothersOfNegTable[0]; - if (particleGrandMotherOfNeg.pdgCode() == -3312) { + if (particleGrandMotherOfNeg.pdgCode() == -3312 || particleGrandMotherOfNeg.pdgCode() == -3322) { registry.fill(HIST("hAntiLambdaFeedDownMatrix"), particleMotherOfNeg.pt(), particleGrandMotherOfNeg.pt()); } } @@ -331,6 +350,11 @@ struct lambdakzeroAnalysisMc { if (eventSelection && !collision.sel7()) { return; } + registry.fill(HIST("hSel8Counter"), 0.5); + + if (eventSelection_posZ && abs(collision.posZ()) > 10.f) { // 10cm + return; + } registry.fill(HIST("hSelectedEventCounter"), 0.5); for (auto& v0 : fullV0s) { @@ -408,7 +432,7 @@ struct lambdakzeroAnalysisMc { }; struct lambdakzeroParticleCountMc { - //Basic checks + // Basic checks HistogramRegistry registry{ "registry", { @@ -419,9 +443,17 @@ struct lambdakzeroParticleCountMc { {"hLambdaCount_PtDiff", "hLambdaCount_PtDiff", {HistType::kTH1F, {{200, 0.0f, 10.0f}}}}, {"hAntiLambdaCount_PtDiff", "hAntiLambdaCount_PtDiff", {HistType::kTH1F, {{200, 0.0f, 10.0f}}}}, + {"hXsiPlusCount", "hXsiPlusCount", {HistType::kTH1F, {{2, 0.0f, 2.0f}}}}, + {"hXsiMinusCount", "hXsiMinusCount", {HistType::kTH1F, {{2, 0.0f, 2.0f}}}}, + {"hXsi0Count", "hXsi0Count", {HistType::kTH1F, {{2, 0.0f, 2.0f}}}}, + {"hAntiXsi0Count", "hAntiXsi0Count", {HistType::kTH1F, {{2, 0.0f, 2.0f}}}}, + {"hXsiPlusCount_PtDiff", "hXsiPlusCount_PtDiff", {HistType::kTH1F, {{200, 0.0f, 10.0f}}}}, + {"hXsiMinusCount_PtDiff", "hXsiMinusCount_PtDiff", {HistType::kTH1F, {{200, 0.0f, 10.0f}}}}, + {"hXsi0Count_PtDiff", "hXsi0Count_PtDiff", {HistType::kTH1F, {{200, 0.0f, 10.0f}}}}, + {"hAntiXsi0Count_PtDiff", "hAntiXsi0Count_PtDiff", {HistType::kTH1F, {{200, 0.0f, 10.0f}}}}, + {"hSelAndRecoMcCollCounter", "hSelAndRecoMcCollCounter", {HistType::kTH1F, {{1, 0.0f, 1.0f}}}}, {"hTotalMcCollCounter", "hTotalMcCollCounter", {HistType::kTH1F, {{1, 0.0f, 1.0f}}}}, - }, }; @@ -437,6 +469,7 @@ struct lambdakzeroParticleCountMc { Configurable rapidityMCcut{"rapidityMCcut", 0.5, "rapidity cut MC count"}; Configurable eventSelectionMC{"eventSelectionMC", true, "event selection MC count"}; + Configurable eventSelectionMC_posZ{"eventSelectionMC_posZ", true, "event selection MC count post poZ cut"}; void process(aod::McCollision const& mcCollision, aod::McParticles const& mcParticles, const soa::SmallGroups>& collisions) { @@ -452,6 +485,10 @@ struct lambdakzeroParticleCountMc { const auto evtReconstructedAndSelected = std::find(SelectedEvents.begin(), SelectedEvents.end(), mcCollision.globalIndex()) != SelectedEvents.end(); + if (eventSelectionMC_posZ && abs(mcCollision.posZ()) > 10.f) { // 10cm + return; + } + registry.fill(HIST("hTotalMcCollCounter"), 0.5); if (!evtReconstructedAndSelected) { // Check that the event is reconstructed and that the reconstructed events pass the selection return; @@ -497,6 +534,50 @@ struct lambdakzeroParticleCountMc { } } } + if (mcparticle.pdgCode() == 3312) { + registry.fill(HIST("hXsiMinusCount"), 0.5); + for (auto& mcparticleDaughter0 : mcparticle.daughters_as()) { + for (auto& mcparticleDaughter1 : mcparticle.daughters_as()) { + if (mcparticleDaughter0.pdgCode() == -211 && mcparticleDaughter1.pdgCode() == 3122) { + registry.fill(HIST("hXsiMinusCount"), 1.5); + registry.fill(HIST("hXsiMinusCount_PtDiff"), mcparticle.pt()); + } + } + } + } + if (mcparticle.pdgCode() == -3312) { + registry.fill(HIST("hXsiPlusCount"), 0.5); + for (auto& mcparticleDaughter0 : mcparticle.daughters_as()) { + for (auto& mcparticleDaughter1 : mcparticle.daughters_as()) { + if (mcparticleDaughter0.pdgCode() == 211 && mcparticleDaughter1.pdgCode() == -3122) { + registry.fill(HIST("hXsiPlusCount"), 1.5); + registry.fill(HIST("hXsiPlusCount_PtDiff"), mcparticle.pt()); + } + } + } + } + if (mcparticle.pdgCode() == 3322) { + registry.fill(HIST("hXsi0Count"), 0.5); + for (auto& mcparticleDaughter0 : mcparticle.daughters_as()) { + for (auto& mcparticleDaughter1 : mcparticle.daughters_as()) { + if (mcparticleDaughter0.pdgCode() == 111 && mcparticleDaughter1.pdgCode() == 3122) { // right + registry.fill(HIST("hXsi0Count"), 1.5); + registry.fill(HIST("hXsi0Count_PtDiff"), mcparticle.pt()); + } + } + } + } + if (mcparticle.pdgCode() == -3322) { + registry.fill(HIST("hAntiXsi0Count"), 0.5); + for (auto& mcparticleDaughter0 : mcparticle.daughters_as()) { + for (auto& mcparticleDaughter1 : mcparticle.daughters_as()) { + if (mcparticleDaughter0.pdgCode() == 111 && mcparticleDaughter1.pdgCode() == -3122) { + registry.fill(HIST("hAntiXsi0Count"), 1.5); + registry.fill(HIST("hAntiXsi0Count_PtDiff"), mcparticle.pt()); + } + } + } + } } } } From 08a17117a797631629754977f176dfa23ccb9d1b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=B2=20Jacazio?= Date: Tue, 19 Jul 2022 22:18:43 +0200 Subject: [PATCH 08/31] QA Efficiency: Extend available track cuts (#1024) * Extend track cuts * Fix --- DPG/Tasks/qaEfficiency.cxx | 29 +++++++++++++++++++++++++---- 1 file changed, 25 insertions(+), 4 deletions(-) diff --git a/DPG/Tasks/qaEfficiency.cxx b/DPG/Tasks/qaEfficiency.cxx index 98e9d9d31b2..bfcd7c0a895 100644 --- a/DPG/Tasks/qaEfficiency.cxx +++ b/DPG/Tasks/qaEfficiency.cxx @@ -63,8 +63,8 @@ struct QaEfficiency { Configurable doTr{"do-tr", false, "Flag to run with the PDG code of tritons"}; Configurable doHe{"do-he", false, "Flag to run with the PDG code of helium 3"}; Configurable doAl{"do-al", false, "Flag to run with the PDG code of helium 4"}; - // Track only selection - Configurable applyTrackSelection{"applyTrackSelection", false, "Flag to use the standard track selection when selecting numerator and denominator"}; + // Track only selection, options to select only specific tracks + Configurable trackSelection{"trackSelection", 1, "Track selection: 0 -> No Cut, 1 -> kGlobalTrack, 2 -> kGlobalTrackWoPtEta, 3 -> kGlobalTrackWoDCA, 4 -> kQualityTracks, 5 -> kInAcceptanceTracks"}; // Event selection Configurable nMinNumberOfContributors{"nMinNumberOfContributors", 2, "Minimum required number of contributors to the primary vertex"}; Configurable vertexZMin{"vertex-z-min", -10.f, "Minimum position of the generated vertez in Z (cm)"}; @@ -1094,6 +1094,27 @@ struct QaEfficiency { isCollisionSelected(collision); } + // Function to apply track selection + template + bool isTrackSelected(trackType track) + { + switch (trackSelection.value) { + case 0: + return true; + case 1: + return track.isGlobalTrack(); + case 2: + return track.isGlobalTrackWoPtEta(); + case 3: + return track.isGlobalTrackWoDCA(); + case 4: + return track.isQualityTrack(); + case 5: + return track.isInAcceptanceTrack(); + } + return false; + } + // MC process void processMC(const o2::aod::McParticles& mcParticles, const o2::soa::Join& collisions, @@ -1165,7 +1186,7 @@ struct QaEfficiency { } histos.fill(HIST("MC/trackSelection"), 10); - if (applyTrackSelection && !track.isGlobalTrack()) { // Check general cuts + if (!isTrackSelected(track)) { // Check general cuts continue; } histos.fill(HIST("MC/trackSelection"), 11); @@ -1347,7 +1368,7 @@ struct QaEfficiency { continue; } histos.fill(HIST("Data/trackSelection"), 4); - if (applyTrackSelection) { // Check general cuts + if (trackSelection.value > 0) { // Check general cuts if (!track.passedTrackType()) { continue; } From d8e246670644720fcef01887d541420a9b7c8318 Mon Sep 17 00:00:00 2001 From: lauraser <45659867+lauraser@users.noreply.github.com> Date: Wed, 20 Jul 2022 10:02:26 +0200 Subject: [PATCH 09/31] make the rejection of tracks not propagated to PV optional (#1023) Co-authored-by: lserksny --- PWGCF/FemtoDream/FemtoDreamTrackSelection.h | 11 +++++++++-- PWGCF/FemtoDream/FemtoDreamV0Selection.h | 9 +++++++++ PWGCF/FemtoDream/femtoDreamProducerTaskV0Only.cxx | 4 +++- 3 files changed, 21 insertions(+), 3 deletions(-) diff --git a/PWGCF/FemtoDream/FemtoDreamTrackSelection.h b/PWGCF/FemtoDream/FemtoDreamTrackSelection.h index a4f575e976e..34459e08f4b 100644 --- a/PWGCF/FemtoDream/FemtoDreamTrackSelection.h +++ b/PWGCF/FemtoDream/FemtoDreamTrackSelection.h @@ -59,7 +59,8 @@ enum TrackContainerPosition { class FemtoDreamTrackSelection : public FemtoDreamObjectSelection { public: - FemtoDreamTrackSelection() : nPtMinSel(0), + FemtoDreamTrackSelection() : nRejectNotPropagatedTracks(false), + nPtMinSel(0), nPtMaxSel(0), nEtaSel(0), nTPCnMinSel(0), @@ -193,7 +194,13 @@ class FemtoDreamTrackSelection : public FemtoDreamObjectSelection 0 && std::abs(dca) < dcaMin) { return false; } - if (std::abs(dca) > 1e3) { + if (nRejectNotPropagatedTracks && std::abs(dca) > 1e3) { return false; } diff --git a/PWGCF/FemtoDream/FemtoDreamV0Selection.h b/PWGCF/FemtoDream/FemtoDreamV0Selection.h index 59928e3a029..76e2e36f2bb 100644 --- a/PWGCF/FemtoDream/FemtoDreamV0Selection.h +++ b/PWGCF/FemtoDream/FemtoDreamV0Selection.h @@ -165,6 +165,15 @@ class FemtoDreamV0Selection : public FemtoDreamObjectSelection ConfEvtOfflineCheck{"ConfEvtOfflineCheck", false, "Evt sel: check for offline selection"}; Configurable ConfStoreV0{"ConfStoreV0", true, "True: store V0 table"}; - + Configurable ConfRejectNotPropagatedTracks{"ConfRejectNotPropagatedTracks", false, "True: reject not propagated tracks"}; FemtoDreamV0Selection v0Cuts; /// \todo Labeled array (see Track-Track task) @@ -152,6 +152,8 @@ struct femtoDreamProducerTaskV0Only { v0Cuts.setChildPIDSpecies(femtoDreamV0Selection::kNegTrack, ConfV0DaughTPIDspecies); v0Cuts.init(&qaRegistry); v0Cuts.setInvMassLimits(ConfInvMassLowLimit, ConfInvMassUpLimit); + v0Cuts.setChildRejectNotPropagatedTracks(femtoDreamV0Selection::kPosTrack, ConfRejectNotPropagatedTracks); + v0Cuts.setChildRejectNotPropagatedTracks(femtoDreamV0Selection::kNegTrack, ConfRejectNotPropagatedTracks); } } From c717e1d4207c6ccd7fde2662e013cb89b00832b0 Mon Sep 17 00:00:00 2001 From: Evgeny Kryshen Date: Wed, 20 Jul 2022 11:23:01 +0300 Subject: [PATCH 10/31] Added evsel QA for periods with INT1 minbias condition (#991) --- Common/CCDB/EventSelectionParams.cxx | 2 +- Common/TableProducer/eventSelection.cxx | 14 ++++++++------ Common/Tasks/eventSelectionQa.cxx | 20 +++++++++++++++----- 3 files changed, 24 insertions(+), 12 deletions(-) diff --git a/Common/CCDB/EventSelectionParams.cxx b/Common/CCDB/EventSelectionParams.cxx index 2a1f62c49ce..7c90632d272 100644 --- a/Common/CCDB/EventSelectionParams.cxx +++ b/Common/CCDB/EventSelectionParams.cxx @@ -45,7 +45,7 @@ const char* selectionLabels[kNsel] = { "kNoInconsistentVtx", "kNoPileupInMultBins", "kNoPilupMV", - "kNoPileupTPC" + "kNoPileupTPC", "kIsTriggerTVX", "kIsINT1"}; } diff --git a/Common/TableProducer/eventSelection.cxx b/Common/TableProducer/eventSelection.cxx index 9e88120cc7f..4d0f3f35814 100644 --- a/Common/TableProducer/eventSelection.cxx +++ b/Common/TableProducer/eventSelection.cxx @@ -162,6 +162,7 @@ struct BcSelectionTask { selection[kNoPileupMV] = (eventCuts & 1 << aod::kPileUpMV) > 0; selection[kNoPileupTPC] = (eventCuts & 1 << aod::kTPCPileUp) > 0; selection[kIsTriggerTVX] = bc.has_ft0() ? (bc.ft0().triggerMask() & BIT(o2::ft0::Triggers::bitVertex)) > 0 : 0; + selection[kIsINT1] = bbV0A || bbV0C || ofSPD > 0; int32_t foundFT0 = bc.has_ft0() ? bc.ft0().globalIndex() : -1; int32_t foundFV0 = bc.has_fv0a() ? bc.fv0a().globalIndex() : -1; @@ -383,16 +384,17 @@ struct EventSelectionTask { sel7 &= applySelection[i] ? selection[i] : 1; } - // TODO apply other cuts for sel8 - // TODO introduce sel1 etc? // TODO introduce array of sel[0]... sel[8] or similar? - bool sel8 = selection[kIsBBT0A] & selection[kIsBBT0C]; + bool sel8 = selection[kIsBBT0A] & selection[kIsBBT0C]; // TODO apply other cuts for sel8 + bool sel1 = selection[kIsINT1] & selection[kNoBGV0A] & selection[kNoBGV0C] & selection[kNoTPCLaserWarmUp] & selection[kNoTPCHVdip]; - // fill counters + // INT1 (SPDFO>0 | V0A | V0C) mimimum bias trigger logic used in pp2010 and pp2011 + bool isINT1period = bc.runNumber() <= 136377 || (bc.runNumber() >= 144871 && bc.runNumber() <= 159582); - if (isMC || alias[kINT7]) { + // fill counters + if (isMC || (!isINT1period && alias[kINT7]) || (isINT1period && alias[kINT1])) { histos.get(HIST("hColCounterAll"))->Fill(Form("%d", bc.runNumber()), 1); - if (sel7) { + if ((!isINT1period && sel7) || (isINT1period && sel1)) { histos.get(HIST("hColCounterAcc"))->Fill(Form("%d", bc.runNumber()), 1); } } diff --git a/Common/Tasks/eventSelectionQa.cxx b/Common/Tasks/eventSelectionQa.cxx index 2e6300dc7f9..558422a7d6c 100644 --- a/Common/Tasks/eventSelectionQa.cxx +++ b/Common/Tasks/eventSelectionQa.cxx @@ -227,6 +227,7 @@ struct EventSelectionQaTask { aod::FT0s const& ft0s, aod::FDDs const& fdds) { + bool isINT1period = 0; if (!applySelection) { auto first_bc = bcs.iteratorAt(0); EventSelectionParams* par = ccdb->getForTimeStamp("EventSelection/EventSelectionParams", first_bc.timestamp()); @@ -234,6 +235,7 @@ struct EventSelectionQaTask { for (int i = 0; i < kNsel; i++) { histos.get(HIST("hSelMask"))->SetBinContent(i + 1, applySelection[i]); } + isINT1period = first_bc.runNumber() <= 136377 || (first_bc.runNumber() >= 144871 && first_bc.runNumber() <= 159582); } // bc-based event selection qa @@ -245,19 +247,24 @@ struct EventSelectionQaTask { // collision-based event selection qa for (auto& col : cols) { + auto selection = col.selection(); + bool sel1 = selection[kIsINT1] & selection[kNoBGV0A] & selection[kNoBGV0C] & selection[kNoTPCLaserWarmUp] & selection[kNoTPCHVdip]; + for (int iAlias = 0; iAlias < kNaliases; iAlias++) { if (!col.alias()[iAlias]) { continue; } histos.fill(HIST("hColCounterAll"), iAlias, 1); - if (!col.sel7()) { - continue; + if ((!isINT1period && col.sel7()) || (isINT1period && sel1)) { + histos.fill(HIST("hColCounterAcc"), iAlias, 1); } - histos.fill(HIST("hColCounterAcc"), iAlias, 1); } + bool mb = isMC; + mb |= !isINT1period && col.alias()[kINT7]; + mb |= isINT1period && col.alias()[kINT1]; // further checks just on minimum bias triggers - if (!isMC && !col.alias()[kINT7]) { + if (!mb) { continue; } for (int i = 0; i < kNsel; i++) { @@ -354,7 +361,10 @@ struct EventSelectionQaTask { histos.fill(HIST("hV0C012vsTklCol"), nTracklets, multRingV0C012); // filling plots for accepted events - if (!col.sel7()) { + bool accepted = 0; + accepted |= !isINT1period & col.sel7(); + accepted |= isINT1period & sel1; + if (!accepted) { continue; } From 1a49c9c82abb8e2bb3df7183bd16ed9dceb92b71 Mon Sep 17 00:00:00 2001 From: dsekihat Date: Wed, 20 Jul 2022 10:30:48 +0200 Subject: [PATCH 11/31] PWGDQ/Tasks: update on v0selector (#1003) * PWGDQ/Tasks/v0selector: add process switch * PWGDQ/Tasks: update v0selector to get magnetic field from CCDB --- PWGDQ/Tasks/v0selector.cxx | 166 +++++++++++++++++++++++++++---------- 1 file changed, 121 insertions(+), 45 deletions(-) diff --git a/PWGDQ/Tasks/v0selector.cxx b/PWGDQ/Tasks/v0selector.cxx index b4ef53046cc..62677010654 100644 --- a/PWGDQ/Tasks/v0selector.cxx +++ b/PWGDQ/Tasks/v0selector.cxx @@ -31,6 +31,10 @@ #include "Common/Core/RecoDecay.h" #include "DetectorsVertexing/DCAFitterN.h" #include "PWGDQ/DataModel/ReducedInfoTables.h" +#include "DetectorsBase/Propagator.h" +#include "DetectorsBase/GeometryManager.h" +#include "DataFormatsParameters/GRPObject.h" +#include #include #include @@ -230,7 +234,7 @@ struct v0selector { }; // Configurables - Configurable d_bz{"d_bz", -5.0, "bz field"}; + Configurable d_bz_input{"d_bz", -999, "bz field, -999 is automatic"}; Configurable v0cospa{"v0cospa", 0.998, "V0 CosPA"}; // double -> N.B. dcos(x)/dx = 0 at x=0) Configurable dcav0dau{"dcav0dau", 0.3, "DCA V0 Daughters"}; Configurable v0Rmin{"v0Rmin", 0.0, "v0Rmin"}; @@ -239,27 +243,66 @@ struct v0selector { Configurable dcamax{"dcamax", 1e+10, "dcamax"}; Configurable mincrossedrows{"mincrossedrows", 70, "min crossed rows"}; Configurable maxchi2tpc{"maxchi2tpc", 4.0, "max chi2/NclsTPC"}; + int mRunNumber; + float d_bz; + Service ccdb; - // aod::Collision gives you tracks matched with collision. - // aod::Collisions gives you all tracks. - // void process(aod::Collisions const& collision, FullTracksExt const& tracks, aod::V0s const& V0s) - // void process(FullTracksExt const& tracks, aod::Collisions const& collision, aod::V0s const& V0s) - // void process(FullTracksExt const& tracks, aod::Collisions const&, aod::V0s const& V0s) - void process(aod::Collisions const&, FullTracksExt const& tracks, aod::V0s const& V0s, aod::Cascades const& Cascades) - // void process(FullTracksExt const& tracks, soa::Join::iterator const& collision, aod::V0s const& V0s) + void init(InitContext& context) { - registry.fill(HIST("hEventCounter"), 0.5); + // using namespace analysis::lambdakzerobuilder; + mRunNumber = 0; + d_bz = 0; + + ccdb->setURL("http://alice-ccdb.cern.ch"); + ccdb->setCaching(true); + ccdb->setLocalObjectValidityChecking(); + + auto lut = o2::base::MatLayerCylSet::rectifyPtrFromFile(ccdb->get("GLO/Param/MatLUT")); + + if (!o2::base::GeometryManager::isGeometryLoaded()) { + ccdb->get("GLO/Config/GeometryAligned"); + /* it seems this is needed at this level for the material LUT to work properly */ + /* but what happens if the run changes while doing the processing? */ + constexpr long run3grp_timestamp = (1619781650000 + 1619781529000) / 2; + + o2::parameters::GRPObject* grpo = ccdb->getForTimeStamp("GLO/GRP/GRP", run3grp_timestamp); + o2::base::Propagator::initFieldFromGRP(grpo); + o2::base::Propagator::Instance()->setMatLUT(lut); + } + } + + float getMagneticField(uint64_t timestamp) + { + // TODO done only once (and not per run). Will be replaced by CCDBConfigurable + static o2::parameters::GRPObject* grpo = nullptr; + if (grpo == nullptr) { + grpo = ccdb->getForTimeStamp("GLO/GRP/GRP", timestamp); + if (grpo == nullptr) { + LOGF(fatal, "GRP object not found for timestamp %llu", timestamp); + return 0; + } + LOGF(info, "Retrieved GRP for timestamp %llu with magnetic field of %d kG", timestamp, grpo->getNominalL3Field()); + } + float output = grpo->getNominalL3Field(); + return output; + } + + void CheckAndUpdate(Int_t lRunNumber, uint64_t lTimeStamp) + { + if (lRunNumber != mRunNumber) { + if (d_bz_input < -990) { + // Fetch magnetic field from ccdb for current collision + d_bz = getMagneticField(lTimeStamp); + } else { + d_bz = d_bz_input; + } + mRunNumber = lRunNumber; + } + } - // Define o2 fitter, 2-prong - o2::vertexing::DCAFitterN<2> fitter; - fitter.setBz(d_bz); - fitter.setPropagateToPCA(true); - fitter.setMaxR(200.); - fitter.setMinParamChange(1e-3); - fitter.setMinRelChi2Change(0.9); - fitter.setMaxDZIni(1e9); - fitter.setMaxChi2(1e9); - fitter.setUseAbsDCA(true); // use d_UseAbsDCA once we want to use the weighted DCA + void process(aod::Collisions const&, aod::BCsWithTimestamps const&, FullTracksExt const& tracks, aod::V0s const& V0s, aod::Cascades const& Cascades) + { + registry.fill(HIST("hEventCounter"), 0.5); std::map pidmap; @@ -313,6 +356,18 @@ struct v0selector { continue; } auto const& collision = V0.posTrack_as().collision(); + auto bc = collision.bc_as(); + CheckAndUpdate(bc.runNumber(), bc.timestamp()); + // Define o2 fitter, 2-prong + o2::vertexing::DCAFitterN<2> fitter; + fitter.setBz(d_bz); + fitter.setPropagateToPCA(true); + fitter.setMaxR(200.); + fitter.setMinParamChange(1e-3); + fitter.setMinRelChi2Change(0.9); + fitter.setMaxDZIni(1e9); + fitter.setMaxChi2(1e9); + fitter.setUseAbsDCA(true); // use d_UseAbsDCA once we want to use the weighted DCA if (V0.collisionId() != collision.globalIndex()) { continue; @@ -428,17 +483,6 @@ struct v0selector { } // end of V0 loop - // next, cascade, Omega -> LK - o2::vertexing::DCAFitterN<2> fitterCasc; - fitterCasc.setBz(d_bz); - fitterCasc.setPropagateToPCA(true); - fitterCasc.setMaxR(200.); - fitterCasc.setMinParamChange(1e-3); - fitterCasc.setMinRelChi2Change(0.9); - fitterCasc.setMaxDZIni(1e9); - fitterCasc.setMaxChi2(1e9); - fitterCasc.setUseAbsDCA(true); - // cascade loop for (auto& casc : Cascades) { registry.fill(HIST("hCascCandidate"), 0.5); @@ -468,6 +512,30 @@ struct v0selector { continue; } + auto bc = collision.bc_as(); + CheckAndUpdate(bc.runNumber(), bc.timestamp()); + // Define o2 fitter, 2-prong + o2::vertexing::DCAFitterN<2> fitterV0; + fitterV0.setBz(d_bz); + fitterV0.setPropagateToPCA(true); + fitterV0.setMaxR(200.); + fitterV0.setMinParamChange(1e-3); + fitterV0.setMinRelChi2Change(0.9); + fitterV0.setMaxDZIni(1e9); + fitterV0.setMaxChi2(1e9); + fitterV0.setUseAbsDCA(true); // use d_UseAbsDCA once we want to use the weighted DCA + + // next, cascade, Omega -> LK + o2::vertexing::DCAFitterN<2> fitterCasc; + fitterCasc.setBz(d_bz); + fitterCasc.setPropagateToPCA(true); + fitterCasc.setMaxR(200.); + fitterCasc.setMinParamChange(1e-3); + fitterCasc.setMinRelChi2Change(0.9); + fitterCasc.setMaxDZIni(1e9); + fitterCasc.setMaxChi2(1e9); + fitterCasc.setUseAbsDCA(true); + std::array pos = {0.}; std::array pvecpos = {0.}; std::array pvecneg = {0.}; @@ -485,18 +553,18 @@ struct v0selector { nTrack = getTrackParCov(casc.v0_as().posTrack_as()); } - int nCand = fitter.process(pTrack, nTrack); + int nCand = fitterV0.process(pTrack, nTrack); if (nCand != 0) { - fitter.propagateTracksToVertex(); + fitterV0.propagateTracksToVertex(); } else { continue; } - const auto& v0vtx = fitter.getPCACandidate(); + const auto& v0vtx = fitterV0.getPCACandidate(); for (int i = 0; i < 3; i++) { pos[i] = v0vtx[i]; } - auto V0dca = fitter.getChi2AtPCACandidate(); // distance between 2 legs. + auto V0dca = fitterV0.getChi2AtPCACandidate(); // distance between 2 legs. registry.fill(HIST("hDCAV0Dau_Casc"), V0dca); // if (V0dca > 1.0) { // continue; @@ -509,16 +577,16 @@ struct v0selector { // Covariance matrix calculation const int momInd[6] = {9, 13, 14, 18, 19, 20}; // cov matrix elements for momentum component - fitter.getTrack(0).getPxPyPzGlo(pvecpos); - fitter.getTrack(1).getPxPyPzGlo(pvecneg); - fitter.getTrack(0).getCovXYZPxPyPzGlo(cov0); - fitter.getTrack(1).getCovXYZPxPyPzGlo(cov1); + fitterV0.getTrack(0).getPxPyPzGlo(pvecpos); + fitterV0.getTrack(1).getPxPyPzGlo(pvecneg); + fitterV0.getTrack(0).getCovXYZPxPyPzGlo(cov0); + fitterV0.getTrack(1).getCovXYZPxPyPzGlo(cov1); for (int i = 0; i < 6; i++) { int j = momInd[i]; covV0[j] = cov0[j] + cov1[j]; } - auto covVtxV0 = fitter.calcPCACovMatrix(); + auto covVtxV0 = fitterV0.calcPCACovMatrix(); covV0[0] = covVtxV0(0, 0); covV0[1] = covVtxV0(1, 0); covV0[2] = covVtxV0(1, 1); @@ -652,7 +720,7 @@ struct trackPIDQA { }, }; - void process(soa::Join::iterator const& collision, soa::Join const& tracks) + void processQA(soa::Join::iterator const& collision, soa::Join const& tracks) { registry.fill(HIST("hEventCounter"), 1.0); // all @@ -660,15 +728,15 @@ struct trackPIDQA { // return; //} // registry.fill(HIST("hEventCounter"), 2.0); //INT7 - - if (abs(collision.posZ()) > 10.0) { + if (collision.numContrib() < 0.5) { return; } - registry.fill(HIST("hEventCounter"), 3.0); //|Zvtx| < 10 cm - if (collision.numContrib() < 0.5) { + registry.fill(HIST("hEventCounter"), 3.0); // Ncontrib > 0 + + if (abs(collision.posZ()) > 10.0) { return; } - registry.fill(HIST("hEventCounter"), 4.0); // accepted + registry.fill(HIST("hEventCounter"), 4.0); //|Zvtx| < 10 cm for (auto& track : tracks) { if (!track.has_collision()) { @@ -733,6 +801,14 @@ struct trackPIDQA { } // end of track loop } // end of process + + void processDummy(soa::Join::iterator const& collision) + { + // do nothing + } + + PROCESS_SWITCH(trackPIDQA, processQA, "Run PID QA for barrel tracks", true); + PROCESS_SWITCH(trackPIDQA, processDummy, "Dummy function", false); }; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) From 0ce73eb40d860d3286ae863542e3363204f4498c Mon Sep 17 00:00:00 2001 From: Mattia Faggin Date: Wed, 20 Jul 2022 19:03:23 +0200 Subject: [PATCH 12/31] DPG: dEdx residuals from splines LHC22cd (lite). (#1028) Co-authored-by: Mattia Faggin --- DPG/Tasks/qaEventTrackLite.cxx | 124 ++++++++++++++++++++++++++++++++- 1 file changed, 122 insertions(+), 2 deletions(-) diff --git a/DPG/Tasks/qaEventTrackLite.cxx b/DPG/Tasks/qaEventTrackLite.cxx index cb80ce26235..48423742a8f 100644 --- a/DPG/Tasks/qaEventTrackLite.cxx +++ b/DPG/Tasks/qaEventTrackLite.cxx @@ -30,6 +30,10 @@ #include "Common/DataModel/TrackSelectionTables.h" #include "Common/Core/TrackSelection.h" #include "Common/Core/TrackSelectionDefaults.h" +#include "DataFormatsTPC/BetheBlochAleph.h" +#include "ReconstructionDataFormats/PID.h" + +#include "TF1.h" using namespace o2; using namespace o2::framework; @@ -67,6 +71,10 @@ struct qaEventTrackLite { Configurable nCrossedRowsTpcOverFindableClustersTpcMin{"nCrossedRowsTpcOverFindableClustersTpcMin", -1, "Minimum ratio between TPC crossed rows and findable clusters"}; Configurable chi2TpcMin{"chi2TpcMin", -1001.f, "Max TPC chi2"}; Configurable chi2TpcMax{"chi2TpcMax", 1000.f, "Max TPC chi2"}; + Configurable tpcSplinesPeriod{"tpcSplinesPeriod", std::string(""), "Period of used TPC dEdx splines"}; + Configurable b_tpcResProton{"b_tpcResProton", false, "Do TPC dEdx residuals around proton hypothesis"}; + Configurable b_tpcResKaon{"b_tpcResKaon", false, "Do TPC dEdx residuals around kaon hypothesis"}; + Configurable b_tpcResPion{"b_tpcResPion", false, "Do TPC dEdx residuals around pion hypothesis"}; // TOF selections Configurable chi2TofMin{"chi2TofMin", -1001.f, "Max TOF chi2"}; Configurable lengthMin{"lengthMin", -1001.f, "Min length"}; @@ -109,6 +117,70 @@ struct qaEventTrackLite { Configurable pdgCodeSel{"pdgCodeSel", 2, "pdgCode based particle selection, 1 defines pi,K,p,mu,e, 2 all final-state charged particles including light (hyper)nuclei"}; Configurable checkPdgAtReco{"checkPdgAtReco", false, "check pdg code also at reco levo for data-like reference"}; + // TPC dEdx splines + struct BBAleph { + + // --- data members --- + double mMip = 0; + std::vector mBetheBlockAleph = {0., 0., 0., 0., 0.}; + double mChargeFactor = 0; + bool initBBok = false; + + // --- functions --- + double operator()(double* x, double* par) + { + /// === Parameters === + /// [0]: mass + /// [1]: charge + /// + /// From A. Kalteyer: + /// const float bethe = mMIP + /// * o2::tpc::BetheBlochAleph(track.tpcInnerParam() / o2::track::pid_constants::sMasses[id] + /// , mBetheBlochParams[0], mBetheBlochParams[1], mBetheBlochParams[2], mBetheBlochParams[3], mBetheBlochParams[4]) + /// * std::pow((float)o2::track::pid_constants::sCharges[id], mChargeFactor); + /// + return initBBok ? mMip * o2::tpc::BetheBlochAleph(x[0] / par[0], mBetheBlockAleph[0], mBetheBlockAleph[1], mBetheBlockAleph[2], mBetheBlockAleph[3], mBetheBlockAleph[4]) * std::pow(par[1], mChargeFactor) : 0.; + } + void setUpBetheBlockAleph(std::string str_case) + { + if (str_case.find("LHC22c") != std::string::npos) { + // From A. Kalteyer (2022 Jul 18) + mMip = 52.35295; + mChargeFactor = 4.382516; + mBetheBlockAleph[0] = 0.038508328324810444; + mBetheBlockAleph[1] = 20.173734667349745; + mBetheBlockAleph[2] = 7.811839314098901e-10; + mBetheBlockAleph[3] = 2.3572347501513162; + mBetheBlockAleph[4] = 3.896773574265881; + initBBok = true; + } else if (str_case.find("LHC22d") != std::string::npos) { + // From A. Kalteyer (2022 Jul 18) + mMip = 52.35295; + mChargeFactor = 4.382516; + mBetheBlockAleph[0] = 0.0370972540453123; + mBetheBlockAleph[1] = 21.29155104648775; + mBetheBlockAleph[2] = 1.2702695962030138e-10; + mBetheBlockAleph[3] = 2.3297081952872936; + mBetheBlockAleph[4] = 4.1832594396288725; + initBBok = true; + } else { + LOG(info) << "===> WARNING: no Bethe Block parameters defined for " << str_case << ". Ignoring it." << std::endl; + return; + } + LOG(info) << "=== Bethe Block Alep parametrization loaded for period " << str_case << ":" << std::endl; + LOG(info) << "mMip = " << mMip << std::endl; + LOG(info) << "mChargeFactor = " << mChargeFactor << std::endl; + LOG(info) << "mBetheBlockAleph[0] = " << mBetheBlockAleph[0] << std::endl; + LOG(info) << "mBetheBlockAleph[1] = " << mBetheBlockAleph[1] << std::endl; + LOG(info) << "mBetheBlockAleph[2] = " << mBetheBlockAleph[2] << std::endl; + LOG(info) << "mBetheBlockAleph[3] = " << mBetheBlockAleph[3] << std::endl; + LOG(info) << "mBetheBlockAleph[4] = " << mBetheBlockAleph[4] << std::endl; + LOG(info) << "initBBok = " << initBBok << std::endl; + } + }; + BBAleph betheBlock; + TF1 funcBBpion, funcBBkaon, funcBBproton; // TPC dEdx splines + void init(InitContext const&) { const AxisSpec axisPt{binsPt, "#it{p}_{T} (GeV/c)"}; @@ -116,6 +188,9 @@ struct qaEventTrackLite { const AxisSpec axisEta{binsEta, "#it{#eta}"}; const AxisSpec axisPhi{binsPhi, "#it{#phi} (rad)"}; + // TPC dEdx splines + betheBlock.setUpBetheBlockAleph(tpcSplinesPeriod); + // kine histograms histos.add("Tracks/VertexPositionZ", "", kTH1D, {{100, -20.f, 20.f, "Vertex Z (cm)"}}); histos.add("Tracks/VertexPositionZvsEta", "", kTH2D, {axisEta, {100, -20.f, 20.f, "Vertex Z (cm)"}}); @@ -150,6 +225,35 @@ struct qaEventTrackLite { histos.add("Tracks/TPC/TPCnClstvsEtavsPt", "profile2D;", kTProfile2D, {axisEta, axisPt}); histos.add("Tracks/TPC/dEdxvsP", "", kTH2D, {{5000, 0, 10, "#it{p} (GeV/#it{c})"}, {500, 0, 1000, "d#it{E}/d#it{x} (a.u.)"}}); histos.add("Tracks/TPC/dEdxvsPvsEta", "", kTH3D, {{5000, 0, 10, "#it{p} (GeV/#it{c})"}, {20, -2, 2, "#it{#eta}"}, {500, 0, 1000, "d#it{E}/d#it{x} (a.u.)"}}); + if (betheBlock.initBBok) { + if (b_tpcResProton) { + // Bethe-Block parametrization proton + funcBBproton = TF1("funcBBproton", betheBlock, 0.1, 20, 3); + funcBBproton.SetParameter(0, o2::track::pid_constants::sMasses[o2::track::PID::Proton]); // mass + funcBBproton.SetParameter(1, o2::track::pid_constants::sCharges[o2::track::PID::Proton]); // electric charge (units of e) + // histograms of residuals + histos.add("Tracks/TPC/dEdxvsPproton", "", kTH2D, {{5000, 0, 10, "#it{p} (GeV/#it{c})"}, {500, -100, 100, "d#it{E}/d#it{x}-d#it{E}/d#it{x}|_{proton} (a.u.)"}}); + histos.add("Tracks/TPC/dEdxvsPprotonvsEta", "", kTH3D, {{5000, 0, 10, "#it{p} (GeV/#it{c})"}, {20, -2, 2, "#it{#eta}"}, {500, -100, 100, "d#it{E}/d#it{x}-d#it{E}/d#it{x}|_{proton} (a.u.)"}}); + } + if (b_tpcResKaon) { + // Bethe-Block parametrization kaon + funcBBkaon = TF1("funcBBkaon", betheBlock, 0.1, 20, 3); + funcBBkaon.SetParameter(0, o2::track::pid_constants::sMasses[o2::track::PID::Kaon]); // mass + funcBBkaon.SetParameter(1, o2::track::pid_constants::sCharges[o2::track::PID::Kaon]); // electric charge (units of e) + // histograms of residuals + histos.add("Tracks/TPC/dEdxvsPkaon", "", kTH2D, {{5000, 0, 10, "#it{p} (GeV/#it{c})"}, {500, -100, 100, "d#it{E}/d#it{x}-d#it{E}/d#it{x}|_{kaon} (a.u.)"}}); + histos.add("Tracks/TPC/dEdxvsPkaonvsEta", "", kTH3D, {{5000, 0, 10, "#it{p} (GeV/#it{c})"}, {20, -2, 2, "#it{#eta}"}, {500, -100, 100, "d#it{E}/d#it{x}-d#it{E}/d#it{x}|_{kaon} (a.u.)"}}); + } + if (b_tpcResPion) { + // Bethe-Block parametrization pion + funcBBpion = TF1("funcBBpion", betheBlock, 0.1, 20, 3); + funcBBpion.SetParameter(0, o2::track::pid_constants::sMasses[o2::track::PID::Pion]); // mass + funcBBpion.SetParameter(1, o2::track::pid_constants::sCharges[o2::track::PID::Pion]); // electric charge (units of e) + // histograms of residuals + histos.add("Tracks/TPC/dEdxvsPpion", "", kTH2D, {{5000, 0, 10, "#it{p} (GeV/#it{c})"}, {500, -100, 100, "d#it{E}/d#it{x}-d#it{E}/d#it{x}|_{pion} (a.u.)"}}); + histos.add("Tracks/TPC/dEdxvsPpionvsEta", "", kTH3D, {{5000, 0, 10, "#it{p} (GeV/#it{c})"}, {20, -2, 2, "#it{#eta}"}, {500, -100, 100, "d#it{E}/d#it{x}-d#it{E}/d#it{x}|_{pion} (a.u.)"}}); + } + } // trd histograms histos.add("Tracks/TRD/trdChi2", "chi2 in TRD", kTH1D, {{100, 0, 10, "chi2 / cluster TRD"}}); // tof histograms @@ -277,8 +381,24 @@ struct qaEventTrackLite { histos.fill(HIST("Tracks/TPC/tpcNClsFoundvsPt"), track.pt(), track.tpcNClsFound()); histos.fill(HIST("Tracks/TPC/tpcCrossedRowsvsPt"), track.pt(), track.tpcNClsCrossedRows()); histos.fill(HIST("Tracks/TPC/tpcCrossedRowsOverFindableClsvsPt"), track.pt(), track.tpcCrossedRowsOverFindableCls()); - histos.fill(HIST("Tracks/TPC/dEdxvsP"), track.pt() / (sin(2 * atan2(1, exp(track.eta())))), track.tpcSignal()); - histos.fill(HIST("Tracks/TPC/dEdxvsPvsEta"), track.pt() / (sin(2 * atan2(1, exp(track.eta())))), track.eta(), track.tpcSignal()); + const double p = track.pt() / (sin(2 * atan2(1, exp(track.eta())))); + histos.fill(HIST("Tracks/TPC/dEdxvsP"), p, track.tpcSignal()); + histos.fill(HIST("Tracks/TPC/dEdxvsPvsEta"), p, track.eta(), track.tpcSignal()); + if (betheBlock.initBBok) { + auto tpcdEdxRes = [&](TF1 func) { return track.tpcSignal() - func.Eval(p); }; + if (b_tpcResProton) { + histos.fill(HIST("Tracks/TPC/dEdxvsPproton"), p, tpcdEdxRes(funcBBproton)); + histos.fill(HIST("Tracks/TPC/dEdxvsPprotonvsEta"), p, track.eta(), tpcdEdxRes(funcBBproton)); + } + if (b_tpcResKaon) { + histos.fill(HIST("Tracks/TPC/dEdxvsPkaon"), p, tpcdEdxRes(funcBBkaon)); + histos.fill(HIST("Tracks/TPC/dEdxvsPkaonvsEta"), p, track.eta(), tpcdEdxRes(funcBBkaon)); + } + if (b_tpcResPion) { + histos.fill(HIST("Tracks/TPC/dEdxvsPpion"), p, tpcdEdxRes(funcBBpion)); + histos.fill(HIST("Tracks/TPC/dEdxvsPpionvsEta"), p, track.eta(), tpcdEdxRes(funcBBpion)); + } + } histos.fill(HIST("Tracks/TRD/trdChi2"), track.trdChi2()); histos.fill(HIST("Tracks/TOF/tofChi2"), track.tofChi2()); if (track.hasTPC()) { From 2bb4ff3242db18cee9db9c20ad3bbe40f2998ccb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mario=20Kr=C3=BCger?= Date: Wed, 20 Jul 2022 19:36:35 +0200 Subject: [PATCH 13/31] PWGLF: fix typos in configurable names (#1031) --- PWGLF/Tasks/spectraCharged.cxx | 26 ++++++++++---------------- 1 file changed, 10 insertions(+), 16 deletions(-) diff --git a/PWGLF/Tasks/spectraCharged.cxx b/PWGLF/Tasks/spectraCharged.cxx index abbd1ec29b4..16c460ade4e 100644 --- a/PWGLF/Tasks/spectraCharged.cxx +++ b/PWGLF/Tasks/spectraCharged.cxx @@ -37,23 +37,18 @@ struct chargedSpectra { HistogramRegistry histos; Service pdg; - // TODO: can we derive this from config context resp from meta data in the file to avoid having to specify this option? - Configurable isMC{"isMC", false, "option to flag mc"}; - Configurable isRun3{"isRun3", true, "Is Run3 dataset"}; // TODO: derive this from metadata once possible to get rid of the flag - // task settings that can be steered via hyperloop - Configurable maxMultMeas{"measMult", 100, "max measured multiplicity."}; - Configurable maxMultTrue{"measTrue", 100, "max true multiplicity."}; - - // TODO: better use 2d configurables here - Configurable etaCut{"etaCut", 0.8f, "Eta cut."}; - Configurable ptMinCut{"ptMinCut", 0.15f, "Pt min cut."}; - Configurable ptMaxCut{"ptMaxCut", 10.f, "Pt max cut."}; + Configurable isRun3{"isRun3", true, "is Run3 dataset"}; // TODO: derive this from metadata once possible to get rid of the flag + Configurable maxMultMeas{"maxMultMeas", 100, "max measured multiplicity"}; + Configurable maxMultTrue{"maxMultTrue", 100, "max true multiplicity"}; + Configurable etaCut{"etaCut", 0.8f, "eta cut"}; + Configurable ptMinCut{"ptMinCut", 0.15f, "pt min cut"}; + Configurable ptMaxCut{"ptMaxCut", 10.f, "pt max cut"}; // helper struct to store transient properties struct varContainer { - uint32_t multMeas{0}; - uint32_t multTrue{0}; + uint32_t multMeas{0u}; + uint32_t multTrue{0u}; bool isAcceptedEvent{false}; bool isAcceptedEventMC{false}; bool isChargedPrimary{false}; @@ -138,7 +133,7 @@ void chargedSpectra::init(InitContext const&) histos.add("multDist_evt_meas", "", kTH1D, {multMeasAxis}); // measured event distribution (contains contamination from events not in specified class or with wrong vertex position) histos.add("multPtSpec_trk_meas", "", kTH2D, {multMeasAxis, ptMeasAxis}); // measured tracks (contains contamination from secondary particles, particles smeared into acceptance and tracks originating from background events as defined above ) - if (isMC) { + if (doprocessMC) { const AxisSpec ptTrueAxis{ptBinEdges, "#it{p}_{T} (GeV/c)", "pt_true"}; @@ -274,7 +269,7 @@ void chargedSpectra::initEvent(const C& collision, const T& tracks) vars.isAcceptedEvent = false; if (std::abs(collision.posZ()) < 10.f) { if (isRun3 ? collision.sel8() : collision.sel7()) { - if ((isRun3 || isMC) ? true : collision.alias()[kINT7]) { + if ((isRun3 || doprocessMC) ? true : collision.alias()[kINT7]) { vars.isAcceptedEvent = true; } } @@ -296,7 +291,6 @@ void chargedSpectra::initEventMC(const C& collision, const P& particles) } ++vars.multTrue; } - // TODO: also determine event class and check if true z vtx positin is good vars.isAcceptedEventMC = ((std::abs(collision.posZ()) < 10.f) && (vars.multTrue > 0)); } From f303a18d50bf7f469bba811e0d3d56abc3ebad4d Mon Sep 17 00:00:00 2001 From: sarahherrmann <83958698+sarahherrmann@users.noreply.github.com> Date: Wed, 20 Jul 2022 21:49:32 +0200 Subject: [PATCH 14/31] Changed the boundaries of Zvtx Axis (#1030) * Z vtx cut as a configurable * changed the boundaries of Zvtx Axis --- PWGMM/Mult/Tasks/dndeta-mft.cxx | 23 ++++++++++++----------- PWGMM/Mult/Tasks/effpt-mft.cxx | 7 ++++--- 2 files changed, 16 insertions(+), 14 deletions(-) diff --git a/PWGMM/Mult/Tasks/dndeta-mft.cxx b/PWGMM/Mult/Tasks/dndeta-mft.cxx index 17b93cd7ce5..12a3cc9405a 100644 --- a/PWGMM/Mult/Tasks/dndeta-mft.cxx +++ b/PWGMM/Mult/Tasks/dndeta-mft.cxx @@ -33,6 +33,7 @@ using namespace o2::framework::expressions; AxisSpec PtAxis = {1001, -0.005, 10.005}; AxisSpec DeltaZAxis = {61, -6.1, 6.1}; AxisSpec MultAxis = {301, -0.5, 300.5}; +AxisSpec ZAxis = {301, -30.1, 30.1}; using MFTTracksLabeled = soa::Join; @@ -47,12 +48,12 @@ struct PseudorapidityDensityMFT { HistogramRegistry registry{ "registry", { - {"EventsNtrkZvtx", "; N_{trk}; Z_{vtx}; events", {HistType::kTH2F, {{301, -0.5, 300.5}, {201, -20.1, 20.1}}}}, // - {"TracksEtaZvtx", "; #eta; Z_{vtx}; tracks", {HistType::kTH2F, {{18, -4.6, -1.}, {201, -20.1, 20.1}}}}, // - {"TracksPhiEta", "; #varphi; #eta; tracks", {HistType::kTH2F, {{600, 0, 2 * M_PI}, {18, -4.6, -1.}}}}, // - {"TracksPtEta", " ; p_{T} (GeV/c); #eta", {HistType::kTH2F, {PtAxis, {18, -4.6, -1.}}}}, // - {"EventSelection", ";status;events", {HistType::kTH1F, {{7, 0.5, 7.5}}}} // - } // + {"EventsNtrkZvtx", "; N_{trk}; Z_{vtx}; events", {HistType::kTH2F, {{301, -0.5, 300.5}, ZAxis}}}, // + {"TracksEtaZvtx", "; #eta; Z_{vtx}; tracks", {HistType::kTH2F, {{18, -4.6, -1.}, ZAxis}}}, // + {"TracksPhiEta", "; #varphi; #eta; tracks", {HistType::kTH2F, {{600, 0, 2 * M_PI}, {18, -4.6, -1.}}}}, // + {"TracksPtEta", " ; p_{T} (GeV/c); #eta", {HistType::kTH2F, {PtAxis, {18, -4.6, -1.}}}}, // + {"EventSelection", ";status;events", {HistType::kTH1F, {{7, 0.5, 7.5}}}} // + } // }; void init(InitContext&) @@ -68,16 +69,16 @@ struct PseudorapidityDensityMFT { x->SetBinLabel(7, "BCs with pile-up/splitting"); if (doprocessGen) { - registry.add({"EventsNtrkZvtxGen", "; N_{trk}; Z_{vtx}; events", {HistType::kTH2F, {{301, -0.5, 300.5}, {201, -20.1, 20.1}}}}); - registry.add({"EventsNtrkZvtxGen_t", "; N_{trk}; Z_{vtx}; events", {HistType::kTH2F, {{301, -0.5, 300.5}, {201, -20.1, 20.1}}}}); - registry.add({"TracksEtaZvtxGen", "; #eta; Z_{vtx}; tracks", {HistType::kTH2F, {{18, -4.6, -1.}, {201, -20.1, 20.1}}}}); - registry.add({"TracksEtaZvtxGen_t", "; #eta; Z_{vtx}; tracks", {HistType::kTH2F, {{18, -4.6, -1.}, {201, -20.1, 20.1}}}}); + registry.add({"EventsNtrkZvtxGen", "; N_{trk}; Z_{vtx}; events", {HistType::kTH2F, {{301, -0.5, 300.5}, ZAxis}}}); + registry.add({"EventsNtrkZvtxGen_t", "; N_{trk}; Z_{vtx}; events", {HistType::kTH2F, {{301, -0.5, 300.5}, ZAxis}}}); + registry.add({"TracksEtaZvtxGen", "; #eta; Z_{vtx}; tracks", {HistType::kTH2F, {{18, -4.6, -1.}, ZAxis}}}); + registry.add({"TracksEtaZvtxGen_t", "; #eta; Z_{vtx}; tracks", {HistType::kTH2F, {{18, -4.6, -1.}, ZAxis}}}); registry.add({"TracksPhiEtaGen", "; #varphi; #eta; tracks", {HistType::kTH2F, {{600, 0, 2 * M_PI}, {18, -4.6, -1.}}}}); registry.add({"TracksToPartPtEta", " ; p_{T} (GeV/c); #eta", {HistType::kTH2F, {PtAxis, {18, -4.6, -1.}}}}); // registry.add({"TracksPtEtaGen", " ; p_{T} (GeV/c); #eta", {HistType::kTH2F, {PtAxis, {18, -4.6, -1.}}}}); registry.add({"TracksPtEtaGen_t", " ; p_{T} (GeV/c); #eta", {HistType::kTH2F, {PtAxis, {18, -4.6, -1.}}}}); registry.add({"EventEfficiency", "; status; events", {HistType::kTH1F, {{5, 0.5, 5.5}}}}); - registry.add({"NotFoundEventZvtx", " ; Z_{vtx}", {HistType::kTH1F, {{201, -20.1, 20.1}}}}); + registry.add({"NotFoundEventZvtx", " ; Z_{vtx}", {HistType::kTH1F, {ZAxis}}}); registry.add({"EventsZposDiff", " ; Z_{rec} - Z_{gen} (cm)", {HistType::kTH1F, {DeltaZAxis}}}); registry.add({"EventsSplitMult", " ; N_{gen}", {HistType::kTH1F, {MultAxis}}}); diff --git a/PWGMM/Mult/Tasks/effpt-mft.cxx b/PWGMM/Mult/Tasks/effpt-mft.cxx index 6cbe7d8461a..8a46ea74f7e 100644 --- a/PWGMM/Mult/Tasks/effpt-mft.cxx +++ b/PWGMM/Mult/Tasks/effpt-mft.cxx @@ -39,6 +39,7 @@ struct EffPtMFT { Configurable useEvSel{"useEvSel", true, "use event selection"}; ConfigurableAxis PtAxis{"PtAxis", {1001, -0.0005, 1.0005}, "pt axis for histograms"}; + Configurable zMax{"zMax", 5., "value for Zvtx cut"}; HistogramRegistry registry{ "registry", @@ -64,7 +65,7 @@ struct EffPtMFT { { if (!useEvSel || (useEvSel && collision.sel8())) { - if ((collision.posZ() < 5) && (collision.posZ() > -5)) { + if ((collision.posZ() < zMax) && (collision.posZ() > -zMax)) { for (auto& track : tracks) { registry.fill(HIST("TracksPtEta"), track.pt(), track.eta()); @@ -88,7 +89,7 @@ struct EffPtMFT { } } - if ((mcCollision.posZ() < 5) && (mcCollision.posZ() > -5)) { + if ((mcCollision.posZ() < zMax) && (mcCollision.posZ() > -zMax)) { for (auto& particle : particles) { auto p = pdg->GetParticle(particle.pdgCode()); auto charge = 0; @@ -116,7 +117,7 @@ struct EffPtMFT { //In the MFT the measurement of pT is not precise, so we access it by using the particle's pT instead if (collision.has_mcCollision()) { - if ((collision.mcCollision().posZ() < 5) && (collision.mcCollision().posZ() > -5)) { + if ((collision.mcCollision().posZ() < zMax) && (collision.mcCollision().posZ() > -zMax)) { if (!useEvSel || (useEvSel && collision.sel8())) { for (auto& track : tracks) { From 9ac213ee58fe4a1f9daf0f5741b2a3663c8f1660 Mon Sep 17 00:00:00 2001 From: rbailhac Date: Thu, 21 Jul 2022 09:43:19 +0200 Subject: [PATCH 15/31] More cut and signal definition + nb of its clusters for Run 3 (#1027) * Some more cuts, signal definition and number of ITS clusters for skimmed data for Run 3 * Fix --- PWGDQ/Core/CutsLibrary.h | 13 +++++++++++++ PWGDQ/Core/MCSignalLibrary.h | 13 +++++++++++++ PWGDQ/Core/VarManager.h | 2 +- 3 files changed, 27 insertions(+), 1 deletion(-) diff --git a/PWGDQ/Core/CutsLibrary.h b/PWGDQ/Core/CutsLibrary.h index 0628d37104c..27746658441 100644 --- a/PWGDQ/Core/CutsLibrary.h +++ b/PWGDQ/Core/CutsLibrary.h @@ -284,6 +284,13 @@ AnalysisCompositeCut* o2::aod::dqcuts::GetCompositeCut(const char* cutName) return cut; } + if (!nameStr.compare("lmee_TPCTrackRun3_lowPt")) { + cut->AddCut(GetAnalysisCut("lmeeLowBKine")); + cut->AddCut(GetAnalysisCut("TightTPCTrackRun3")); + cut->AddCut(GetAnalysisCut("standardPrimaryTrack")); + return cut; + } + if (!nameStr.compare("lmee_GlobalTrackRun3_TPC_ePID_lowPt")) { cut->AddCut(GetAnalysisCut("lmeeLowBKine")); cut->AddCut(GetAnalysisCut("TightGlobalTrackRun3")); @@ -460,6 +467,12 @@ AnalysisCut* o2::aod::dqcuts::GetAnalysisCut(const char* cutName) return cut; } + if (!nameStr.compare("TightTPCTrackRun3")) { + cut->AddCut(VarManager::kTPCchi2, 0.0, 4.0); + cut->AddCut(VarManager::kTPCnclsCR, 80.0, 161.); + return cut; + } + if (!nameStr.compare("electronStandardQuality")) { cut->AddCut(VarManager::kIsSPDany, 0.5, 1.5); cut->AddCut(VarManager::kIsITSrefit, 0.5, 1.5); diff --git a/PWGDQ/Core/MCSignalLibrary.h b/PWGDQ/Core/MCSignalLibrary.h index 58994d06f2e..eaf21491dfd 100644 --- a/PWGDQ/Core/MCSignalLibrary.h +++ b/PWGDQ/Core/MCSignalLibrary.h @@ -45,6 +45,12 @@ MCSignal* o2::aod::dqmcsignals::GetMCSignal(const char* name) signal = new MCSignal(name, "Primary electrons", {prong}, {-1}); // define the signal using the full constructor return signal; } + if (!nameStr.compare("pionPrimary")) { + MCProng prong(1, {211}, {true}, {false}, {0}, {0}, {false}); // define 1-generation prong using the full constructor + prong.SetSourceBit(0, MCProng::kPhysicalPrimary); // set source to be ALICE primary particles + signal = new MCSignal(name, "Primary electrons", {prong}, {-1}); // define the signal using the full constructor + return signal; + } if (!nameStr.compare("photon")) { MCProng prong(1, {22}, {true}, {false}, {0}, {0}, {false}); // define 1-generation prong using the full constructor signal = new MCSignal(name, "Photon", {prong}, {-1}); // define the signal using the full constructor @@ -357,6 +363,13 @@ MCSignal* o2::aod::dqmcsignals::GetMCSignal(const char* name) signal = new MCSignal(name, "Electrons from open charmed hadron decays from b hadron decays", {prong}, {-1}); return signal; } + if (!nameStr.compare("HFdecayToE")) { + MCProng prong(2, {902, 11}, {true, true}, {false, false}, {0, 0}, {0, 0}, {false, false}); + // prong.SetSourceBit(0, MCProng::kPhysicalPrimary, false); // set source to be ALICE primary particles + prong.SetSignalInTime(true); // set direction to check for daughters (true, in time) or for mothers (false, back in time) + signal = new MCSignal(name, "Open charm and beauty to electrons", {prong}, {-1}); + return signal; + } // if (!nameStr.compare("LFQtoPC")) { // MCProng prong(3, {900, 22, 11}, {true, true, true}, {false, false, false}, {0, 0, 0}, {0, 0, 0}, {false, false, false}); // prong.SetSignalInTime(true); // set direction to check for daughters (true, in time) or for mothers (false, back in time) diff --git a/PWGDQ/Core/VarManager.h b/PWGDQ/Core/VarManager.h index 3b46db921be..ccf75bb8e13 100644 --- a/PWGDQ/Core/VarManager.h +++ b/PWGDQ/Core/VarManager.h @@ -667,7 +667,7 @@ void VarManager::FillTrack(T const& track, float* values) if constexpr ((fillMap & ReducedTrackBarrel) > 0) { if (fgUsedVars[kITSncls]) { values[kITSncls] = 0.0; - for (int i = 0; i < 6; ++i) { + for (int i = 0; i < 7; ++i) { values[kITSncls] += ((track.itsClusterMap() & (1 << i)) ? 1 : 0); } } From 3e7d20d5094b2a6d2da5ad35495fe7ff97047a59 Mon Sep 17 00:00:00 2001 From: Nazar Burmasov Date: Thu, 21 Jul 2022 10:45:35 +0300 Subject: [PATCH 16/31] Developments of data model and tasks for skimming and candidates creation in UD (#1021) * [WIP] UD skimming developments * [WIP] Add UD tables for skimming * [WIP] UD skimming developments: do not dereference table pointers * [WIP] UD skimming developments: rework MC information processing in skimmer, rework dimuon analysis * [WIP] UD skimming developments: clang format * [WIP] UD skimming developments: add skimming of barrel tracks and semiforward candidates * [WIP] UD skimming developments: minor improvements of tables and analysis * [WIP] UD skimming developments: add more code comments * [WIP] UD skimming developments: switch to index columns for candidate IDs and add global BCs to tracks * [WIP] UD skimming developments: rename tables, switch to propagated tracks * [WIP] UD skimming developments: merge DGCandidates with UDTables and adapt DG tasks * [WIP] UD skimming developments: rename skimmer and creator tasks * UD skimming developments: fix typos, clang format * UD skimming developments: fix typos, naming, rework UPC candidate analyzer --- PWGUD/CMakeLists.txt | 1 - PWGUD/Core/DGPIDSelector.cxx | 20 +- PWGUD/Core/DGPIDSelector.h | 13 +- PWGUD/DataModel/DGCandidates.h | 51 --- PWGUD/DataModel/UDTables.h | 250 ++++++++++++ PWGUD/TableProducer/CMakeLists.txt | 10 + PWGUD/TableProducer/DGCandProducer.cxx | 28 +- PWGUD/TableProducer/UPCTrackSkimmer.cxx | 414 ++++++++++++++++++++ PWGUD/TableProducer/UPCandidateProducer.cxx | 200 ++++++++++ PWGUD/Tasks/CMakeLists.txt | 10 + PWGUD/Tasks/DGCandAnalyzer.cxx | 6 +- PWGUD/Tasks/UPCCandidateAnalyzer.cxx | 179 +++++++++ PWGUD/Tasks/UPCTrackSkimmerQA.cxx | 88 +++++ 13 files changed, 1194 insertions(+), 76 deletions(-) delete mode 100644 PWGUD/DataModel/DGCandidates.h create mode 100644 PWGUD/DataModel/UDTables.h create mode 100644 PWGUD/TableProducer/UPCTrackSkimmer.cxx create mode 100644 PWGUD/TableProducer/UPCandidateProducer.cxx create mode 100644 PWGUD/Tasks/UPCCandidateAnalyzer.cxx create mode 100644 PWGUD/Tasks/UPCTrackSkimmerQA.cxx diff --git a/PWGUD/CMakeLists.txt b/PWGUD/CMakeLists.txt index 7ff980baa4f..8a08f451979 100644 --- a/PWGUD/CMakeLists.txt +++ b/PWGUD/CMakeLists.txt @@ -13,4 +13,3 @@ add_subdirectory(Core) # add_subdirectory(DataModel) add_subdirectory(Tasks) add_subdirectory(TableProducer) - diff --git a/PWGUD/Core/DGPIDSelector.cxx b/PWGUD/Core/DGPIDSelector.cxx index 3a753803284..36749c5bab8 100644 --- a/PWGUD/Core/DGPIDSelector.cxx +++ b/PWGUD/Core/DGPIDSelector.cxx @@ -24,7 +24,7 @@ float particleMass(TDatabasePDG* pdg, int pid) }; // ----------------------------------------------------------------------------- -DGParticle::DGParticle(TDatabasePDG* pdg, DGAnaparHolder anaPars, aod::DGTracks const& dgtracks, std::vector comb) +DGParticle::DGParticle(TDatabasePDG* pdg, DGAnaparHolder anaPars, UDTracksFull const& tracks, std::vector comb) { // compute invariant mass TLorentzVector lvtmp; @@ -35,8 +35,8 @@ DGParticle::DGParticle(TDatabasePDG* pdg, DGAnaparHolder anaPars, aod::DGTracks auto cnt = -1; for (auto ind : comb) { cnt++; - auto track = dgtracks.rawIteratorAt(ind); - lvtmp.SetPtEtaPhiM(track.pt(), track.eta(), track.phi(), particleMass(pdg, pidinfo[cnt * 12])); + auto track = tracks.rawIteratorAt(ind); + lvtmp.SetXYZM(track.px(), track.py(), track.pz(), particleMass(pdg, pidinfo[cnt * 12])); mIVM += lvtmp; } @@ -60,7 +60,7 @@ DGPIDSelector::DGPIDSelector() } // ----------------------------------------------------------------------------- -float DGPIDSelector::getTPCnSigma(aod::DGTrack track, int hypo) +float DGPIDSelector::getTPCnSigma(UDTrackFull track, int hypo) { switch (hypo) { case 0: @@ -79,7 +79,7 @@ float DGPIDSelector::getTPCnSigma(aod::DGTrack track, int hypo) } // ----------------------------------------------------------------------------- -bool DGPIDSelector::isGoodTrack(aod::DGTrack track, int cnt) +bool DGPIDSelector::isGoodTrack(UDTrackFull track, int cnt) { // extract PID information auto pidinfo = mAnaPars.TPCnSigmas(); @@ -121,22 +121,22 @@ bool DGPIDSelector::isGoodTrack(aod::DGTrack track, int cnt) } // ----------------------------------------------------------------------------- -int DGPIDSelector::computeIVMs(int nCombine, aod::DGTracks const& dgtracks) +int DGPIDSelector::computeIVMs(int nCombine, UDTracksFull const& tracks) { // reset mIVMs.clear(); // create combinations including permutations - auto combs = combinations(nCombine, dgtracks.size()); + auto combs = combinations(nCombine, tracks.size()); // loop over combinations for (auto comb : combs) { - // is dgtracks compatible with PID requirements? + // is tracks compatible with PID requirements? bool isGoodComb = true; auto cnt = -1; for (auto ind : comb) { cnt++; - if (!isGoodTrack(dgtracks.rawIteratorAt(ind), cnt)) { + if (!isGoodTrack(tracks.rawIteratorAt(ind), cnt)) { isGoodComb = false; break; } @@ -144,7 +144,7 @@ int DGPIDSelector::computeIVMs(int nCombine, aod::DGTracks const& dgtracks) // update list of IVMs if (isGoodComb) { - DGParticle IVM(fPDG, mAnaPars, dgtracks, comb); + DGParticle IVM(fPDG, mAnaPars, tracks, comb); mIVMs.push_back(IVM); } } diff --git a/PWGUD/Core/DGPIDSelector.h b/PWGUD/Core/DGPIDSelector.h index 89ce7d1982f..146ed557847 100644 --- a/PWGUD/Core/DGPIDSelector.h +++ b/PWGUD/Core/DGPIDSelector.h @@ -15,11 +15,14 @@ #include #include "TDatabasePDG.h" #include "TLorentzVector.h" -#include "PWGUD/DataModel/DGCandidates.h" +#include "PWGUD/DataModel/UDTables.h" #include "DGAnaparHolder.h" using namespace o2; +using UDTracksFull = soa::Join; +using UDTrackFull = soa::Join::iterator; + float particleMass(TDatabasePDG* pdg, int pid); // ----------------------------------------------------------------------------- @@ -27,7 +30,7 @@ float particleMass(TDatabasePDG* pdg, int pid); struct DGParticle { public: DGParticle() = default; - DGParticle(TDatabasePDG* pdg, DGAnaparHolder anaPars, aod::DGTracks const& dgtracks, std::vector comb); + DGParticle(TDatabasePDG* pdg, DGAnaparHolder anaPars, UDTracksFull const& tracks, std::vector comb); // getter std::vector trkinds() { return mtrkinds; } @@ -60,9 +63,9 @@ struct DGPIDSelector { // getters std::vector IVMs() { return mIVMs; } - float getTPCnSigma(aod::DGTrack track, int hypo); - bool isGoodTrack(aod::DGTrack track, int cnt); - int computeIVMs(int nCombine, aod::DGTracks const& dgtracks); + float getTPCnSigma(UDTrackFull track, int hypo); + bool isGoodTrack(UDTrackFull track, int cnt); + int computeIVMs(int nCombine, UDTracksFull const& tracks); private: // analysis parameters diff --git a/PWGUD/DataModel/DGCandidates.h b/PWGUD/DataModel/DGCandidates.h deleted file mode 100644 index 9159be6eb62..00000000000 --- a/PWGUD/DataModel/DGCandidates.h +++ /dev/null @@ -1,51 +0,0 @@ -// Copyright 2019-2020 CERN and copyright holders of ALICE O2. -// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. -// All rights not expressly granted are reserved. -// -// This software is distributed under the terms of the GNU General Public -// License v3 (GPL Version 3), copied verbatim in the file "COPYING". -// -// In applying this license CERN does not waive the privileges and immunities -// granted to it by virtue of its status as an Intergovernmental Organization -// or submit itself to any jurisdiction. -/// -/// \brief -/// \author Paul Buehler, paul.buehler@oeaw.ac.at -/// \since 03.06.2022 - -#ifndef O2_ANALYSIS_DGCANDIDATES_H -#define O2_ANALYSIS_DGCANDIDATES_H - -#include "Common/DataModel/PIDResponse.h" - -namespace o2::aod -{ -namespace dgcand -{ -DECLARE_SOA_COLUMN(NetCharge, netCharge, int8_t); //! Sum of track signs -DECLARE_SOA_COLUMN(RgtrwTOF, rgtrwTOF, float); //! Fraction of global tracks with TOF hit - -} // namespace dgcand -DECLARE_SOA_TABLE(DGCandidates, "AOD", "DGCANDIDATES", //! Table with DG candidates - o2::soa::Index<>, bc::RunNumber, timestamp::Timestamp, - collision::PosX, collision::PosY, collision::PosZ, - collision::NumContrib, dgcand::NetCharge, dgcand::RgtrwTOF); -using DGCandidate = DGCandidates::iterator; - -namespace dgtrack -{ -DECLARE_SOA_INDEX_COLUMN(DGCandidate, dgCandidate); //! pointer into table DGCandidates -DECLARE_SOA_COLUMN(Sign, sign, int8_t); //! Charge sign of DG track -} // namespace dgtrack - -DECLARE_SOA_TABLE(DGTracks, "AOD", "DGTRACKS", //! Table with tracks belonging to a DG candidate - o2::soa::Index<>, - dgtrack::DGCandidateId, - track::Pt, track::Eta, track::Phi, dgtrack::Sign, - pidtpc::TPCNSigmaEl, pidtpc::TPCNSigmaMu, pidtpc::TPCNSigmaPi, pidtpc::TPCNSigmaKa, pidtpc::TPCNSigmaPr, - pidtof::TOFNSigmaEl, pidtof::TOFNSigmaMu, pidtof::TOFNSigmaPi, pidtof::TOFNSigmaKa, pidtof::TOFNSigmaPr); -using DGTrack = DGTracks::iterator; - -} // namespace o2::aod - -#endif // O2_ANALYSIS_DGCANDIDATES_H diff --git a/PWGUD/DataModel/UDTables.h b/PWGUD/DataModel/UDTables.h new file mode 100644 index 00000000000..6bb81c4bbc1 --- /dev/null +++ b/PWGUD/DataModel/UDTables.h @@ -0,0 +1,250 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +#ifndef O2PHYSICS_UDTABLES_H +#define O2PHYSICS_UDTABLES_H + +#include "Framework/ASoA.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/DataTypes.h" +#include "MathUtils/Utils.h" +#include "Common/DataModel/PIDResponse.h" +#include + +namespace o2::aod +{ + +namespace udmccollision +{ +DECLARE_SOA_COLUMN(GlobalBC, globalBC, uint64_t); +} // namespace udmccollision + +DECLARE_SOA_TABLE(UDMcCollisions, "AOD", "UDMCCOLLISIONS", + o2::soa::Index<>, + udmccollision::GlobalBC, + mccollision::GeneratorsID, + mccollision::PosX, + mccollision::PosY, + mccollision::PosZ, + mccollision::T, + mccollision::Weight, + mccollision::ImpactParameter); + +using UDMcCollision = UDMcCollisions::iterator; + +namespace udmcparticle +{ +DECLARE_SOA_INDEX_COLUMN(UDMcCollision, udMcCollision); //! +DECLARE_SOA_SELF_ARRAY_INDEX_COLUMN(Mothers, mothers); //! Mother tracks (possible empty) array. Iterate over mcParticle.mothers_as()) +DECLARE_SOA_SELF_SLICE_INDEX_COLUMN(Daughters, daughters); //! Daughter tracks (possibly empty) slice. Check for non-zero with mcParticle.has_daughters(). Iterate over mcParticle.daughters_as()) +DECLARE_SOA_COLUMN(Px, px, float); //! +DECLARE_SOA_COLUMN(Py, py, float); //! +DECLARE_SOA_COLUMN(Pz, pz, float); //! +DECLARE_SOA_COLUMN(E, e, float); //! +} // namespace udmcparticle + +DECLARE_SOA_TABLE_FULL(UDMcParticles, "UDMcParticles", "AOD", "UDMCPARTICLES", //! + o2::soa::Index<>, udmcparticle::UDMcCollisionId, + mcparticle::PdgCode, + mcparticle::StatusCode, + mcparticle::Flags, + udmcparticle::MothersIds, + udmcparticle::DaughtersIdSlice, + mcparticle::Weight, + udmcparticle::Px, + udmcparticle::Py, + udmcparticle::Pz, + udmcparticle::E, + mcparticle::ProducedByGenerator, + mcparticle::FromBackgroundEvent, + mcparticle::GetGenStatusCode, + mcparticle::GetProcess, + mcparticle::IsPhysicalPrimary); + +using UDMcParticle = UDMcParticles::iterator; + +namespace udcollision +{ +// general information +DECLARE_SOA_COLUMN(RunNumber, runNumber, int32_t); //! run number +DECLARE_SOA_COLUMN(GlobalBC, globalBC, uint64_t); //! global BC instead of BC ID since candidate may not have a corresponding record in BCs table +DECLARE_SOA_COLUMN(NetCharge, netCharge, int8_t); //! Sum of track signs +DECLARE_SOA_COLUMN(RgtrwTOF, rgtrwTOF, float); //! Fraction of global tracks with TOF hit +// FT0 information +DECLARE_SOA_COLUMN(TotalFT0AmplitudeA, totalFT0AmplitudeA, float); //! sum of amplitudes on A side of FT0 +DECLARE_SOA_COLUMN(TotalFT0AmplitudeC, totalFT0AmplitudeC, float); //! sum of amplitudes on C side of FT0 +DECLARE_SOA_COLUMN(TimeFT0A, timeFT0A, float); //! FT0A average time +DECLARE_SOA_COLUMN(TimeFT0C, timeFT0C, float); //! FT0C average time +DECLARE_SOA_COLUMN(TriggerMaskFT0, triggerMaskFT0, uint8_t); //! FT0 trigger mask +DECLARE_SOA_DYNAMIC_COLUMN(HasFT0, hasFT0, //! has FT0 signal in the same BC + [](float TimeFT0A, float TimeFT0C) -> bool { return TimeFT0A > -999. && TimeFT0C > -999.; }); +} // namespace udcollision + +DECLARE_SOA_TABLE(UDCollisions, "AOD", "UDCOLLISION", + o2::soa::Index<>, + udcollision::GlobalBC, + udcollision::RunNumber, + collision::PosX, + collision::PosY, + collision::PosZ, + collision::NumContrib, + udcollision::NetCharge, + udcollision::RgtrwTOF, + udcollision::TotalFT0AmplitudeA, + udcollision::TotalFT0AmplitudeC, + udcollision::TimeFT0A, + udcollision::TimeFT0C, + udcollision::TriggerMaskFT0, + udcollision::HasFT0); + +using UDCollision = UDCollisions::iterator; + +namespace udtrack +{ +DECLARE_SOA_INDEX_COLUMN(UDCollision, udCollision); //! +DECLARE_SOA_COLUMN(Px, px, float); //! +DECLARE_SOA_COLUMN(Py, py, float); //! +DECLARE_SOA_COLUMN(Pz, pz, float); //! +DECLARE_SOA_COLUMN(Sign, sign, int); //! +DECLARE_SOA_COLUMN(GlobalBC, globalBC, uint64_t); //! +DECLARE_SOA_COLUMN(TrackTime, trackTime, double); //! +DECLARE_SOA_COLUMN(TrackTimeRes, trackTimeRes, float); //! time resolution +DECLARE_SOA_COLUMN(DetectorMap, detectorMap, uint8_t); //! +DECLARE_SOA_DYNAMIC_COLUMN(Pt, pt, //! + [](float px, float py) -> float { + return std::sqrt(px * px + py * py); + }); +} // namespace udtrack + +// Barrel track kinematics +DECLARE_SOA_TABLE(UDTracks, "AOD", "UDTRACK", + o2::soa::Index<>, + udtrack::Px, + udtrack::Py, + udtrack::Pz, + udtrack::Sign, + udtrack::GlobalBC, + udtrack::TrackTime, + udtrack::TrackTimeRes, + udtrack::Pt); + +DECLARE_SOA_TABLE(UDTracksPID, "AOD", "UDTRACKPID", + pidtpc::TPCNSigmaEl, pidtpc::TPCNSigmaMu, pidtpc::TPCNSigmaPi, pidtpc::TPCNSigmaKa, pidtpc::TPCNSigmaPr, + pidtof::TOFNSigmaEl, pidtof::TOFNSigmaMu, pidtof::TOFNSigmaPi, pidtof::TOFNSigmaKa, pidtof::TOFNSigmaPr); + +DECLARE_SOA_TABLE(UDTrackCollisionIDs, "AOD", "UDTRCOLID", + udtrack::UDCollisionId); + +DECLARE_SOA_TABLE(UDTracksExtra, "AOD", "UDTRACKEXTRA", + track::ITSClusterMap, + track::TPCNClsFindable, + track::TPCNClsFindableMinusFound, + track::TPCNClsFindableMinusCrossedRows, + track::TPCNClsShared, + track::TRDPattern, + track::ITSChi2NCl, + track::TPCChi2NCl, + track::TRDChi2, + track::TOFChi2, + track::TPCSignal, + track::TRDSignal, + track::Length, + track::TOFExpMom, + udtrack::DetectorMap, + track::HasITS, + track::HasTPC, + track::HasTRD, + track::HasTOF, + track::ITSNCls, + track::TPCNClsCrossedRows); + +using UDTrack = UDTracks::iterator; +using UDTrackExtra = UDTracksExtra::iterator; +using UDTrackCollisionID = UDTrackCollisionIDs::iterator; + +namespace udmctracklabel +{ +DECLARE_SOA_INDEX_COLUMN(UDMcParticle, udMcParticle); +DECLARE_SOA_COLUMN(McMask, mcMask, uint16_t); +} // namespace udmctracklabel + +DECLARE_SOA_TABLE(UDMcTrackLabels, "AOD", "UDMCTRACKLABEL", + udmctracklabel::UDMcParticleId, + udmctracklabel::McMask); + +using UDMcTrackLabel = UDMcTrackLabels::iterator; + +// only MCH-MID tracks +namespace udfwdtrack +{ +DECLARE_SOA_INDEX_COLUMN(UDCollision, udCollision); //! +DECLARE_SOA_COLUMN(Px, px, float); //! +DECLARE_SOA_COLUMN(Py, py, float); //! +DECLARE_SOA_COLUMN(Pz, pz, float); //! +DECLARE_SOA_COLUMN(Sign, sign, int); //! +DECLARE_SOA_COLUMN(GlobalBC, globalBC, uint64_t); //! +DECLARE_SOA_COLUMN(TrackTime, trackTime, double); //! +DECLARE_SOA_COLUMN(TrackTimeRes, trackTimeRes, float); //! time resolution + +DECLARE_SOA_DYNAMIC_COLUMN(MIDBoardCh1, midBoardCh1, //! + [](uint32_t midBoards) -> int { return static_cast(midBoards & 0xFF); }); +DECLARE_SOA_DYNAMIC_COLUMN(MIDBoardCh2, midBoardCh2, //! + [](uint32_t midBoards) -> int { return static_cast((midBoards >> 8) & 0xFF); }); +DECLARE_SOA_DYNAMIC_COLUMN(MIDBoardCh3, midBoardCh3, //! + [](uint32_t midBoards) -> int { return static_cast((midBoards >> 16) & 0xFF); }); +DECLARE_SOA_DYNAMIC_COLUMN(MIDBoardCh4, midBoardCh4, //! + [](uint32_t midBoards) -> int { return static_cast((midBoards >> 24) & 0xFF); }); +} // namespace udfwdtrack + +// Muon track kinematics +DECLARE_SOA_TABLE(UDFwdTracks, "AOD", "UDFWDTRACK", + o2::soa::Index<>, + udfwdtrack::Px, + udfwdtrack::Py, + udfwdtrack::Pz, + udfwdtrack::Sign, + udfwdtrack::GlobalBC, + udfwdtrack::TrackTime, + udfwdtrack::TrackTimeRes); + +DECLARE_SOA_TABLE(UDFwdTrackCollisionIDs, "AOD", "UDFWDTRCOLID", + udfwdtrack::UDCollisionId); + +// Muon track quality details +DECLARE_SOA_TABLE(UDFwdTracksExtra, "AOD", "UDFWDTRACKEXTRA", + fwdtrack::NClusters, + fwdtrack::PDca, + fwdtrack::RAtAbsorberEnd, + fwdtrack::Chi2, + fwdtrack::Chi2MatchMCHMID, + fwdtrack::MCHBitMap, + fwdtrack::MIDBitMap, + fwdtrack::MIDBoards); + +using UDFwdTrack = UDFwdTracks::iterator; +using UDFwdTrackExtra = UDFwdTracksExtra::iterator; +using UDFwdTrackCollisionID = UDFwdTrackCollisionIDs::iterator; + +namespace udmcfwdtracklabel +{ +DECLARE_SOA_INDEX_COLUMN(UDMcParticle, udMcParticle); +DECLARE_SOA_COLUMN(McMask, mcMask, uint16_t); +} // namespace udmcfwdtracklabel + +DECLARE_SOA_TABLE(UDMcFwdTrackLabels, "AOD", "UDMCFWDTRLABEL", + udmcfwdtracklabel::UDMcParticleId, + udmcfwdtracklabel::McMask); + +using UDMcFwdTrackLabel = UDMcFwdTrackLabels::iterator; + +} // namespace o2::aod + +#endif // O2PHYSICS_UDTABLES_H diff --git a/PWGUD/TableProducer/CMakeLists.txt b/PWGUD/TableProducer/CMakeLists.txt index 17e349c64d0..bc99f26d977 100644 --- a/PWGUD/TableProducer/CMakeLists.txt +++ b/PWGUD/TableProducer/CMakeLists.txt @@ -13,3 +13,13 @@ o2physics_add_dpl_workflow(dgcand-producer SOURCES DGCandProducer.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::DGCutparHolder COMPONENT_NAME Analysis) + +o2physics_add_dpl_workflow(upctrack-skimmer + SOURCES UPCTrackSkimmer.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore + COMPONENT_NAME Analysis) + +o2physics_add_dpl_workflow(upccand-producer + SOURCES UPCandidateProducer.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore + COMPONENT_NAME Analysis) diff --git a/PWGUD/TableProducer/DGCandProducer.cxx b/PWGUD/TableProducer/DGCandProducer.cxx index 55421b9e056..91ecbbfb2e9 100644 --- a/PWGUD/TableProducer/DGCandProducer.cxx +++ b/PWGUD/TableProducer/DGCandProducer.cxx @@ -53,7 +53,7 @@ #include "EventFiltering/PWGUD/DGHelpers.h" #include "PWGUD/Core/UDHelperFunctions.h" -#include "PWGUD/DataModel/DGCandidates.h" +#include "PWGUD/DataModel/UDTables.h" using namespace o2; using namespace o2::framework; @@ -73,8 +73,19 @@ struct DGCandProducer { diffCuts = (DGCutparHolder)DGCuts; } - Produces outputCollisions; - Produces outputTracks; + Produces outputCollisions; + Produces outputTracks; + Produces outputTracksPID; + Produces outputTrackColIDs; + + // helper struct + struct FT0Info { + float amplitudeA = -1; + float amplitudeC = -1; + float timeA = -999.; + float timeC = -999.; + uint8_t triggerMask = 0; + }; using CCs = soa::Join; using CC = CCs::iterator; @@ -105,18 +116,21 @@ struct DGCandProducer { // save DG candidates if (isDGEvent == 0) { + FT0Info ft0Info; // update DGCandidates tables outputCollisions(bc.runNumber(), bc.timestamp(), collision.posX(), collision.posY(), collision.posZ(), - collision.numContrib(), netCharge(tracks), rPVtrwTOF(tracks, collision.numContrib())); + collision.numContrib(), netCharge(tracks), rPVtrwTOF(tracks, collision.numContrib()), + ft0Info.amplitudeA, ft0Info.amplitudeC, ft0Info.timeA, ft0Info.timeC, ft0Info.triggerMask); // update DGTracks tables for (auto& track : tracks) { if (track.isPVContributor()) { - outputTracks(outputCollisions.lastIndex(), track.pt(), track.eta(), track.phi(), track.sign(), - track.tpcNSigmaEl(), track.tpcNSigmaMu(), track.tpcNSigmaPi(), track.tpcNSigmaKa(), track.tpcNSigmaPr(), - track.tofNSigmaEl(), track.tofNSigmaMu(), track.tofNSigmaPi(), track.tofNSigmaKa(), track.tofNSigmaPr()); + outputTracks(track.px(), track.py(), track.pz(), track.sign(), bc.globalBC(), track.trackTime(), track.trackTimeRes()); + outputTrackColIDs(outputCollisions.lastIndex()); + outputTracksPID(track.tpcNSigmaEl(), track.tpcNSigmaMu(), track.tpcNSigmaPi(), track.tpcNSigmaKa(), track.tpcNSigmaPr(), + track.tofNSigmaEl(), track.tofNSigmaMu(), track.tofNSigmaPi(), track.tofNSigmaKa(), track.tofNSigmaPr()); } } } diff --git a/PWGUD/TableProducer/UPCTrackSkimmer.cxx b/PWGUD/TableProducer/UPCTrackSkimmer.cxx new file mode 100644 index 00000000000..d9093058eff --- /dev/null +++ b/PWGUD/TableProducer/UPCTrackSkimmer.cxx @@ -0,0 +1,414 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +#include "Framework/runDataProcessing.h" +#include "Framework/AnalysisTask.h" +#include "CommonConstants/LHCConstants.h" +#include "Common/DataModel/TrackSelectionTables.h" +#include "PWGUD/DataModel/UDTables.h" + +using namespace o2::framework; +using namespace o2::framework::expressions; + +struct UpcTrackSkimmer { + int32_t fSignalGenID{1}; + bool fDoMC; + + Produces udMCCollisions; + Produces udMCParticles; + + Produces fwdTracks; + Produces fwdTracksExtra; + Produces fwdTrackLabels; + + Produces udTracks; + Produces udTracksExtra; + Produces udTracksPID; + Produces udTrackLabels; + + // cuts for forward tracks + Configurable fUseFwdCuts{"useFwdCuts", 1, "Use cuts for forward tracks"}; + // basic + Configurable fFwdPtLow{"fwdPtLow", 0.5, "Minimal Pt for forward tracks"}; + Configurable fFwdPtHigh{"fwdPtHigh", 4., "Maximal Pt for forward tracks"}; + Configurable fFwdEtaLow{"fwdEtaLow", -4.0, "Maximal Eta for forward tracks"}; + Configurable fFwdEtaHigh{"fwdEtaHigh", -2.5, "Maximal Eta for forward tracks"}; + // quality + Configurable fMuonRAtAbsorberEndLow{"muonRAtAbsorberEndLow", 17.6, "Minimal muon R at absorber end"}; + Configurable fMuonRAtAbsorberEndHigh{"muonRAtAbsorberEndHigh", 89.5, "Maximal muon R at absorber end"}; + Configurable fMuonPDcaHighFirst{"fMuonPDcaHighFirst", 594.0, "Primary PDCA cut: Maximal value for R < 26.5"}; + Configurable fMuonPDcaHighSecond{"fMuonPDcaHighSecond", 324.0, "Additional PDCA cut: Maximal value for R >= 26.5"}; + Configurable fFwdChi2Low{"fwdChi2Low", 0.0, "Minimal Chi2 for forward tracks"}; + Configurable fFwdChi2High{"fwdChi2High", 10000.0, "Maximal Chi2 for forward tracks"}; + + // cuts for central-barrel tracks + Configurable fUseBarCuts{"useBarCuts", 1, "Use cuts for barrel tracks"}; + // basic + Configurable fBarPtLow{"barPtLow", 0., "Minimal Pt for barrel tracks"}; + Configurable fBarPtHigh{"barPtHigh", 1000., "Maximal Pt for barrel tracks"}; + Configurable fBarEtaLow{"barEtaLow", -0.9, "Maximal Eta for barrel tracks"}; + Configurable fBarEtaHigh{"barEtaHigh", 0.9, "Maximal Eta for barrel tracks"}; + // quality: ITS + Configurable fITSNClusLow{"ITSNClusLow", 4, "Minimal number of ITS clusters"}; + Configurable fITSNClusHigh{"ITSNClusHigh", 9, "Maximal number of ITS clusters"}; + Configurable fITSChi2Low{"ITSChi2Low", 0., "Minimal Chi2 in ITS per cluster"}; + Configurable fITSChi2High{"ITSChi2High", 5., "Maximal Chi2 in ITS per cluster"}; + // quality: TPC + Configurable fTPCNClusCRLow{"TPCNClusCRLow", 70, "Minimal number of TPC clusters (crossed rows)"}; + Configurable fTPCNClusCRHigh{"TPCNClusCRHigh", 161, "Maximal number of TPC clusters (crossed rows)"}; + Configurable fTPCChi2Low{"TPCChi2Low", 0., "Minimal Chi2 in TPC per cluster"}; + Configurable fTPCChi2High{"TPCChi2High", 4., "Maximal Chi2 in TPC per cluster"}; + // quality: DCA + Configurable fCheckMaxDcaXY{"checkMaxDCACut", 1, "Apply cut on maximal DCA_xy"}; + Configurable fDcaZLow{"dcaZLow", -3., "Minimal DCA_z for barrel tracks"}; + Configurable fDcaZHigh{"dcaZHigh", 3., "Maximal DCA_z for barrel tracks"}; + + template + bool applyFwdCuts(TFwdTrack const& track) + { + // using any cuts at all? + if (!fUseFwdCuts) { + return true; + } + // check Pt cuts + float pt = track.pt(); + bool checkPt = pt > fFwdPtLow && pt < fFwdPtHigh; + if (!checkPt) { + return false; + } + // check pseudorapidity cuts + float eta = track.eta(); + bool checkEta = eta > fFwdEtaLow && eta < fFwdEtaHigh; + if (!checkEta) { + return false; + } + // check muon R + float r = track.rAtAbsorberEnd(); + bool checkR = r > fMuonRAtAbsorberEndLow && r < fMuonRAtAbsorberEndHigh; + if (!checkR) { + return false; + } + // check pDCA + float pDCA = track.pDca(); + bool checkPDCA = r < 26.5 ? pDCA < fMuonPDcaHighFirst : pDCA < fMuonPDcaHighSecond; + if (!checkPDCA) { + return false; + } + // check Chi2 + float chi2 = track.chi2(); + bool checkChi2 = chi2 > fFwdChi2Low && chi2 < fFwdChi2High; + if (!checkChi2) { + return false; + } + return true; + } + + template + bool applyBarCuts(TBarTrack const& track) + { + // using any cuts at all? + if (!fUseBarCuts) { + return true; + } + // check Pt cuts + float pt = track.pt(); + bool checkPt = pt > fBarPtLow && pt < fBarPtHigh; + if (!checkPt) { + return false; + } + // check pseudorapidity cuts + float eta = track.eta(); + bool checkEta = eta > fBarEtaLow && eta < fBarEtaHigh; + if (!checkEta) { + return false; + } + // check ITS cuts + bool checkITSNClus = track.itsNCls() >= static_cast(fITSNClusLow) && track.itsNCls() <= static_cast(fITSNClusHigh); + if (!checkITSNClus) { + return false; + } + bool checkChi2ITS = track.itsChi2NCl() > fITSChi2Low && track.itsChi2NCl() < fITSChi2High; + if (!checkChi2ITS) { + return false; + } + // check TPC cuts + int checkTPCNClus = track.tpcNClsCrossedRows() > static_cast(fTPCNClusCRLow) && track.tpcNClsCrossedRows() < static_cast(fTPCNClusCRHigh); + if (!checkTPCNClus) { + return false; + } + bool checkChi2TPC = track.tpcChi2NCl() > fTPCChi2Low && track.tpcChi2NCl() < fTPCChi2High; + if (!checkChi2TPC) { + return false; + } + // check DCA + if (fCheckMaxDcaXY) { + float dca = track.dcaXY(); + float maxDCA = 0.0105f + 0.0350f / pow(pt, 1.1f); + if (dca < maxDCA) { + return false; + } + } + bool checkDCAZ = track.dcaZ() > fDcaZLow && track.dcaZ() < fDcaZHigh; + if (!checkDCAZ) { + return false; + } + return true; + } + + template + void skimMCInfo(TMcCollisions const& mcCollisions, + TMcParticles const& mcParticles, + TBCs const& bcs, + std::map& newPartIDs) + { + std::vector newEventIDs(mcCollisions.size(), -1); + + int32_t newPartID = 0; + int32_t newEventID = 0; + int32_t nMCParticles = mcParticles.size(); + // loop over MC particles to select only the ones from signal events + // and calculate new MC table IDs + for (int32_t mcPartID = 0; mcPartID < nMCParticles; mcPartID++) { + const auto& mcPart = mcParticles.iteratorAt(mcPartID); + int32_t mcEventID = mcPart.mcCollisionId(); + const auto& mcEvent = mcCollisions.iteratorAt(mcEventID); + bool isSignal = mcEvent.generatorsID() == fSignalGenID; + if (!isSignal || !mcPart.producedByGenerator()) { + continue; + } + newPartIDs[mcPartID] = newPartID; + newPartID++; + if (newEventIDs[mcEventID] == -1) { + newEventIDs[mcEventID] = newEventID; + newEventID++; + } + } + + // storing MC particles + for (const auto& item : newPartIDs) { + int32_t mcPartID = item.first; + const auto& mcPart = mcParticles.iteratorAt(mcPartID); + int32_t mcEventID = mcPart.mcCollisionId(); + int32_t newEventID = newEventIDs[mcEventID]; + // collecting new mother IDs + const auto& motherIDs = mcPart.mothersIds(); + std::vector newMotherIDs; + newMotherIDs.reserve(motherIDs.size()); + for (auto motherID : motherIDs) { + if (motherID >= nMCParticles) { + continue; + } + auto it = newPartIDs.find(motherID); + if (it != newPartIDs.end()) { + newMotherIDs.push_back(it->second); + } + } + // collecting new daughter IDs + const auto& daughterIDs = mcPart.daughtersIds(); + int32_t newDaughterIDs[2] = {-1, -1}; + if (daughterIDs.size() > 0) { + int32_t firstDaughter = daughterIDs.front(); + int32_t lastDaughter = daughterIDs.back(); + if (firstDaughter >= nMCParticles || lastDaughter >= nMCParticles) { + continue; + } + auto itFirst = newPartIDs.find(firstDaughter); + auto itLast = newPartIDs.find(lastDaughter); + if (itFirst != newPartIDs.end() && itLast != newPartIDs.end()) { + newDaughterIDs[0] = newPartIDs.at(daughterIDs.front()); + newDaughterIDs[1] = newPartIDs.at(daughterIDs.back()); + } + } + udMCParticles(newEventID, mcPart.pdgCode(), mcPart.statusCode(), mcPart.flags(), newMotherIDs, newDaughterIDs, + mcPart.weight(), mcPart.px(), mcPart.py(), mcPart.pz(), mcPart.e()); + } + + // storing MC events + for (int32_t i = 0; i < mcCollisions.size(); i++) { + if (newEventIDs[i] == -1) { + continue; + } + const auto& mcEvent = mcCollisions.iteratorAt(i); + udMCCollisions(mcEvent.bc().globalBC(), mcEvent.generatorsID(), mcEvent.posX(), mcEvent.posY(), mcEvent.posZ(), + mcEvent.t(), mcEvent.weight(), mcEvent.impactParameter()); + } + + newEventIDs.clear(); + } + + template + void skimFwdTracks(TFwdTracks const& tracks, + TAmbFwdTracks const& ambTracks, + TBCs const& bcs, + TMcFwdTrackLabels* mcTrackLabels, + std::map const& newPartIDs) + { + for (const auto& ambTr : ambTracks) { + auto trId = ambTr.fwdtrackId(); + const auto& tr = tracks.iteratorAt(trId); + // filter only interesting type of tracks if needed + if constexpr (TTrackType != -1) { + auto trType = tr.trackType(); + if (trType != TTrackType) { + continue; + } + } + // skip if doesn't pass cuts + if (!applyFwdCuts(tr)) { + continue; + } + const auto& bcSlice = ambTr.bc(); + auto first = bcSlice.begin(); + uint64_t firstBC = first.globalBC(); + double realTime = firstBC * o2::constants::lhc::LHCBunchSpacingNS + (double)tr.trackTime(); // "real" = relative to start of TF + uint64_t bc = realTime > 0. ? std::round(realTime / o2::constants::lhc::LHCBunchSpacingNS) : 0; + double trTime = bc * o2::constants::lhc::LHCBunchSpacingNS - realTime; + fwdTracks(tr.px(), tr.py(), tr.pz(), tr.sign(), bc, trTime, tr.trackTimeRes()); + fwdTracksExtra(tr.nClusters(), tr.pDca(), tr.rAtAbsorberEnd(), tr.chi2(), tr.chi2MatchMCHMID(), + tr.mchBitMap(), tr.midBitMap(), tr.midBoards()); + // fill MC labels and masks if needed + if (fDoMC) { + const auto& label = mcTrackLabels->iteratorAt(trId); + uint16_t mcMask = label.mcMask(); + auto it = newPartIDs.find(label.mcParticleId()); + // signal tracks should always have an MC particle + // background tracks have label == -1 + int32_t newPartID = it != newPartIDs.end() ? it->second : -1; + fwdTrackLabels(newPartID, mcMask); + } + } + } + + template + void skimBarTracks(TBarTracks const& tracks, + TAmbBarTracks const& ambTracks, + TBCs const& bcs, + TMcBarTrackLabels* mcTrackLabels, + std::map const& newPartIDs) + { + for (const auto& ambTr : ambTracks) { + auto trId = ambTr.trackId(); + const auto& tr = tracks.iteratorAt(trId); + // using only tracks with TOF match + // todo: make this selection optional? + if (!tr.hasTOF()) { + continue; + } + // skip if doesn't pass cuts + if (!applyBarCuts(tr)) { + continue; + } + const auto& bcSlice = ambTr.bc(); + auto first = bcSlice.begin(); + uint64_t firstBC = first.globalBC(); + double realTime = firstBC * o2::constants::lhc::LHCBunchSpacingNS + (double)tr.trackTime(); // "real" = relative to start of TF + uint64_t bc = realTime > 0. ? std::round(realTime / o2::constants::lhc::LHCBunchSpacingNS) : 0; + double trTime = bc * o2::constants::lhc::LHCBunchSpacingNS - realTime; + udTracks(tr.px(), tr.py(), tr.pz(), tr.sign(), bc, trTime, tr.trackTimeRes()); + udTracksExtra(tr.itsClusterMap(), tr.tpcNClsFindable(), tr.tpcNClsFindableMinusFound(), tr.tpcNClsFindableMinusCrossedRows(), + tr.tpcNClsShared(), tr.trdPattern(), tr.itsChi2NCl(), tr.tpcChi2NCl(), tr.trdChi2(), tr.tofChi2(), + tr.tpcSignal(), tr.trdSignal(), tr.length(), tr.tofExpMom(), tr.detectorMap()); + udTracksPID(tr.tpcNSigmaEl(), tr.tpcNSigmaMu(), tr.tpcNSigmaPi(), tr.tpcNSigmaKa(), tr.tpcNSigmaPr(), + tr.tofNSigmaEl(), tr.tofNSigmaMu(), tr.tofNSigmaPi(), tr.tofNSigmaKa(), tr.tofNSigmaPr()); + // fill MC labels and masks if needed + if (fDoMC) { + const auto& label = mcTrackLabels->iteratorAt(trId); + uint16_t mcMask = label.mcMask(); + int32_t mcPartID = label.mcParticleId(); + auto it = newPartIDs.find(mcPartID); + // signal tracks should always have an MC particle + // background tracks have label == -1 + int32_t newPartID = it != newPartIDs.end() ? it->second : -1; + udTrackLabels(newPartID, mcMask); + } + } + } + + using BarrelTracks = o2::soa::Join; + + // process only MCH-MID tracks with MC information + void processFwdMC(o2::soa::Join const& tracks, + o2::aod::AmbiguousFwdTracks const& ambTracks, + o2::aod::McFwdTrackLabels const& mcFwdTrackLabels, + o2::aod::McCollisions const& mcCollisions, + o2::aod::McParticles const& mcParticles, + o2::aod::BCs const& bcs) + { + fDoMC = true; + using namespace o2::aod::fwdtrack; + const int32_t trType = ForwardTrackTypeEnum::MuonStandaloneTrack; + std::map newPartIDs; + skimMCInfo(mcCollisions, mcParticles, bcs, newPartIDs); + skimFwdTracks(tracks, ambTracks, bcs, &mcFwdTrackLabels, newPartIDs); + newPartIDs.clear(); + } + + // process only MCH-MID tracks without MC information + void processFwd(o2::soa::Join const& tracks, + o2::aod::AmbiguousFwdTracks const& ambTracks, + o2::aod::BCs const& bcs) + { + fDoMC = false; + using namespace o2::aod::fwdtrack; + const int32_t trType = ForwardTrackTypeEnum::MuonStandaloneTrack; + std::map dummyMap; + skimFwdTracks(tracks, ambTracks, bcs, (o2::aod::McFwdTrackLabels*)nullptr, dummyMap); + } + + // process both barrel and muon tracks with MC information + void processAllMC(o2::soa::Join const& fwdTracks, + o2::aod::McFwdTrackLabels const& mcFwdTrackLabels, + o2::aod::AmbiguousFwdTracks const& ambFwdTracks, + BarrelTracks const& barTracks, + o2::aod::McTrackLabels const& mcBarTrackLabels, + o2::aod::AmbiguousTracks const& ambBarTracks, + o2::aod::McCollisions const& mcCollisions, + o2::aod::McParticles const& mcParticles, + o2::aod::BCs const& bcs) + { + fDoMC = true; + using namespace o2::aod::fwdtrack; + const int32_t trType = ForwardTrackTypeEnum::MuonStandaloneTrack; + std::map newPartIDs; + skimMCInfo(mcCollisions, mcParticles, bcs, newPartIDs); + skimFwdTracks(fwdTracks, ambFwdTracks, bcs, &mcFwdTrackLabels, newPartIDs); + skimBarTracks(barTracks, ambBarTracks, bcs, &mcBarTrackLabels, newPartIDs); + newPartIDs.clear(); + } + + // process both barrel and muon tracks without MC information + void processAll(o2::soa::Join const& fwdTracks, + o2::aod::AmbiguousFwdTracks const& ambFwdTracks, + BarrelTracks const& barTracks, + o2::aod::AmbiguousTracks const& ambBarTracks, + o2::aod::BCs const& bcs) + { + fDoMC = true; + using namespace o2::aod::fwdtrack; + const int32_t trType = ForwardTrackTypeEnum::MuonStandaloneTrack; + std::map dummyMap; + skimFwdTracks(fwdTracks, ambFwdTracks, bcs, (o2::aod::McFwdTrackLabels*)nullptr, dummyMap); + skimBarTracks(barTracks, ambBarTracks, bcs, (o2::aod::McTrackLabels*)nullptr, dummyMap); + } + + PROCESS_SWITCH(UpcTrackSkimmer, processFwdMC, "Produce only muon tracks with MC information", false); + PROCESS_SWITCH(UpcTrackSkimmer, processFwd, "Produce only muon tracks", false); + PROCESS_SWITCH(UpcTrackSkimmer, processAllMC, "Produce barrel and muon tracks with MC information", false); + PROCESS_SWITCH(UpcTrackSkimmer, processAll, "Produce barrel and muon tracks", false); +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{ + o2::framework::adaptAnalysisTask(cfgc)}; +} \ No newline at end of file diff --git a/PWGUD/TableProducer/UPCandidateProducer.cxx b/PWGUD/TableProducer/UPCandidateProducer.cxx new file mode 100644 index 00000000000..bdb2642063d --- /dev/null +++ b/PWGUD/TableProducer/UPCandidateProducer.cxx @@ -0,0 +1,200 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +#include "Framework/runDataProcessing.h" +#include "Framework/AnalysisTask.h" +#include "Framework/AnalysisDataModel.h" +#include "PWGUD/DataModel/UDTables.h" + +using namespace o2::framework; +using namespace o2::framework::expressions; + +struct UpcCandProducer { + Produces eventCandidates; + Produces barrelCandIds; + Produces muonCandIds; + + bool fDoSemiFwd{false}; + + Configurable fNFwdProngs{"nFwdProngs", 2, "Matched forward tracks per candidate"}; + Configurable fNBarProngs{"nBarProngs", 0, "Matched barrel tracks per candidate"}; + + // helper struct + struct FT0Info { + float amplitudeA = -1; + float amplitudeC = -1; + float timeA = -999.; + float timeC = -999.; + uint8_t triggerMask = 0; + }; + + template + void createCandidates(TFwdTracks* fwdTracks, + TBarTracks* barTracks, + TBCs const& bcs, + TFT0s const& ft0s) + { + // map track IDs to the respective event candidate IDs + std::vector barTrackCandIds; + std::vector fwdTrackCandIds; + + std::map BCsWithFT0; + // collect BCs with FT0 signals + for (const auto& ft0 : ft0s) { + uint64_t bc = ft0.bc().globalBC(); + BCsWithFT0[bc] = ft0.globalIndex(); + } + + // pairs of global BCs and vectors of matched track IDs: + // global BC <-> + std::map, std::vector>> bcsMatchedFwdTrIds; + + // forward matching + if (fwdTracks != nullptr) { + fwdTrackCandIds.resize(fwdTracks->size(), -1); + for (const auto& fwdTr : *fwdTracks) { + uint64_t bc = fwdTr.globalBC(); + // search for BC: + // if found -> store track ID to vector of matched tracks + // else make a new vector of matched tracks and store track ID + auto it = bcsMatchedFwdTrIds.find(bc); + if (it != bcsMatchedFwdTrIds.end()) { + it->second.first.emplace_back(fwdTr.globalIndex()); + } else { + bcsMatchedFwdTrIds[bc] = std::make_pair(std::vector(1, fwdTr.globalIndex()), std::vector()); + } + } + } + + // central barrel tracks + if (barTracks != nullptr) { + barTrackCandIds.resize(barTracks->size(), -1); + for (const auto& barTr : *barTracks) { + uint64_t bc = barTr.globalBC(); + // search for BC: + // if found -> store track ID to vector of matched tracks + // else make a new vector of matched tracks and store track ID + auto it = bcsMatchedFwdTrIds.find(bc); + if (it != bcsMatchedFwdTrIds.end()) { + it->second.second.emplace_back(barTr.globalIndex()); + } else if (!fDoSemiFwd) { // tag central-barrel tracks to forward tracks in semiforward case + bcsMatchedFwdTrIds[bc] = std::make_pair(std::vector(), std::vector(1, barTr.globalIndex())); + } + } + } + + // todo: calculate position of UD collision? + float dummyX = 0.; + float dummyY = 0.; + float dummyZ = 0.; + + // storing n-prong matches + int32_t candID = 0; + for (const auto& item : bcsMatchedFwdTrIds) { + uint64_t bc = item.first; + const std::vector& fwdTrackIDs = item.second.first; + const std::vector& barTrackIDs = item.second.second; + int32_t nFwdTracks = fwdTrackIDs.size(); + int32_t nBarTracks = barTrackIDs.size(); + // skip candidate if it does not pass `number of tracks` requirement + if (!(nFwdTracks == fNFwdProngs && nBarTracks == fNBarProngs)) { + continue; + } + int8_t netCharge = 0; + uint16_t numContrib = nFwdTracks + nBarTracks; + float RgtrwTOF = 0.; + for (auto id : fwdTrackIDs) { + fwdTrackCandIds[id] = candID; + const auto& tr = fwdTracks->iteratorAt(id); + netCharge += tr.sign(); + } + for (auto id : barTrackIDs) { + barTrackCandIds[id] = candID; + const auto& tr = barTracks->iteratorAt(id); + netCharge += tr.sign(); + if (tr.hasTOF()) { + RgtrwTOF++; + } + } + RgtrwTOF /= nBarTracks; + // fetching FT0 information + // if there is no FT0 signal, dummy info will be used + FT0Info ft0Info; + auto ft0Iter = BCsWithFT0.find(bc); + if (ft0Iter != BCsWithFT0.end()) { + const auto& ft0 = ft0s.iteratorAt(ft0Iter->second); + const auto& ampsA = ft0.amplitudeA(); + const auto& ampsC = ft0.amplitudeC(); + ft0Info.amplitudeA = 0.; + for (auto amp : ampsA) { + ft0Info.amplitudeA += amp; + } + ft0Info.amplitudeC = 0.; + for (auto amp : ampsC) { + ft0Info.amplitudeC += amp; + } + ft0Info.timeA = ft0.timeA(); + ft0Info.timeC = ft0.timeC(); + ft0Info.triggerMask = ft0.triggerMask(); + } + int32_t runNumber = bcs.iteratorAt(0).runNumber(); + eventCandidates(bc, runNumber, dummyX, dummyY, dummyZ, numContrib, netCharge, RgtrwTOF, + ft0Info.amplitudeA, ft0Info.amplitudeC, ft0Info.timeA, ft0Info.timeC, ft0Info.triggerMask); + candID++; + } + bcsMatchedFwdTrIds.clear(); + BCsWithFT0.clear(); + + if (fwdTracks != nullptr) { + for (const auto& fwdTr : *fwdTracks) { + muonCandIds(fwdTrackCandIds[fwdTr.globalIndex()]); + } + } + + fwdTrackCandIds.clear(); + + if (barTracks != nullptr) { + for (const auto& barTr : *barTracks) { + barrelCandIds(barTrackCandIds[barTr.globalIndex()]); + } + } + + barTrackCandIds.clear(); + } + + // create candidates for forward region + void processFwd(o2::aod::UDFwdTracks const& muonTracks, + o2::aod::BCs const& bcs, + o2::aod::FT0s const& ft0s) + { + createCandidates(&muonTracks, (o2::soa::Join*)nullptr, bcs, ft0s); + } + + // create candidates for semiforward region + void processSemiFwd(o2::aod::UDFwdTracks const& muonTracks, + o2::soa::Join const& barTracks, + o2::aod::BCs const& bcs, + o2::aod::FT0s const& ft0s) + { + fDoSemiFwd = true; + createCandidates(&muonTracks, &barTracks, bcs, ft0s); + } + + PROCESS_SWITCH(UpcCandProducer, processFwd, "Produce candidates for forward rapidities", false); + PROCESS_SWITCH(UpcCandProducer, processSemiFwd, "Produce candidates in semiforward region", false); +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{ + adaptAnalysisTask(cfgc)}; +} diff --git a/PWGUD/Tasks/CMakeLists.txt b/PWGUD/Tasks/CMakeLists.txt index 28fb9cd06d1..c0a9b1fef7c 100644 --- a/PWGUD/Tasks/CMakeLists.txt +++ b/PWGUD/Tasks/CMakeLists.txt @@ -38,3 +38,13 @@ o2physics_add_dpl_workflow(dgcand-analyzer SOURCES DGCandAnalyzer.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::DGCutparHolder O2Physics::DGPIDSelector COMPONENT_NAME Analysis) + +o2physics_add_dpl_workflow(upccand-analyzer + SOURCES UPCCandidateAnalyzer.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2::DetectorsBase + COMPONENT_NAME Analysis) + +o2physics_add_dpl_workflow(upc-track-skimmer-qa + SOURCES UPCTrackSkimmerQA.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2::DetectorsBase + COMPONENT_NAME Analysis) diff --git a/PWGUD/Tasks/DGCandAnalyzer.cxx b/PWGUD/Tasks/DGCandAnalyzer.cxx index 0c2c9f037f8..34a5f35ec0f 100644 --- a/PWGUD/Tasks/DGCandAnalyzer.cxx +++ b/PWGUD/Tasks/DGCandAnalyzer.cxx @@ -38,7 +38,7 @@ #include "Common/DataModel/PIDResponse.h" #include "EventFiltering/PWGUD/DGCutparHolder.h" -#include "PWGUD/DataModel/DGCandidates.h" +#include "PWGUD/DataModel/UDTables.h" #include "PWGUD/Core/DGPIDSelector.h" using namespace o2; @@ -72,7 +72,9 @@ struct DGCandAnalyzer { pidsel.init(anaPars); } - void process(aod::DGCandidate const& dgcand, aod::DGTracks const& dgtracks) + using UDTracksFull = soa::Join; + + void process(aod::UDCollision const& dgcand, UDTracksFull const& dgtracks) { // skip events with too few/many tracks diff --git a/PWGUD/Tasks/UPCCandidateAnalyzer.cxx b/PWGUD/Tasks/UPCCandidateAnalyzer.cxx new file mode 100644 index 00000000000..b497b4279ca --- /dev/null +++ b/PWGUD/Tasks/UPCCandidateAnalyzer.cxx @@ -0,0 +1,179 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +#include "Framework/runDataProcessing.h" +#include "Framework/AnalysisTask.h" +#include "Framework/AnalysisDataModel.h" +#include "PWGUD/DataModel/UDTables.h" + +#include +#include "TLorentzVector.h" + +using namespace o2; +using namespace o2::framework; +using namespace o2::framework::expressions; + +struct UpcCandAnalyzer { + Preslice perMcCollision = o2::aod::udmcparticle::udMcCollisionId; + + float ft0DummyTime = 32.767f; + float mmuon = 0.1056583745; + float muonPDG = 13; + + HistogramRegistry registry{ + "registry", + {{"TracksWithFT0/Eta", ";#eta;", {HistType::kTH1D, {{80, -4., 4.}}}}, + {"TracksWithFT0/TimeFT0A", ";time A, ns;", {HistType::kTH1D, {{1000, -50., 50.}}}}, + {"TracksWithFT0/TimeFT0C", ";time C, ns;", {HistType::kTH1D, {{1000, -50., 50.}}}}, + // + {"PairsMC/Mass", ";#it{m}_{#mu#mu}, GeV;", {HistType::kTH1D, {{100, 0., 10.}}}}, + {"PairsMC/EtaMu", ";#eta_{#mu};", {HistType::kTH1D, {{100, -6., 6.}}}}, + // + {"PairSelection/MassRaw", ";#it{m}_{#mu#mu}, GeV;", {HistType::kTH1D, {{100, 0., 10.}}}}, + {"PairSelection/PtRaw", ";#it{p}_{T}^{#mu#mu}, GeV;", {HistType::kTH1D, {{100, 0., 10.}}}}, + // + {"PairSelection/Mass", ";#it{m}_{#mu#mu}, GeV;", {HistType::kTH1D, {{100, 0., 10.}}}}, + {"PairSelection/MassMC", ";#it{m}_{#mu#mu}, GeV;", {HistType::kTH1D, {{100, 0., 10.}}}}, + {"PairSelection/Pt", ";#it{p}_{T}^{#mu#mu}, GeV;", {HistType::kTH1D, {{100, 0., 10.}}}}, + {"PairSelection/EtaMu", ";#eta_{#mu};", {HistType::kTH1D, {{100, -6., 6.}}}}, + // + {"PairSelection/MassNoFT0", ";#it{m}_{#mu#mu}, GeV;", {HistType::kTH1D, {{100, 0., 10.}}}}, + {"PairSelection/MassNoFT0Contam", ";#it{m}_{#mu#mu}, GeV;", {HistType::kTH1D, {{100, 0., 10.}}}}, + {"PairSelection/MassNoFT0MC", ";#it{m}_{#mu#mu}, GeV;", {HistType::kTH1D, {{100, 0., 10.}}}}, + {"PairSelection/PtNoFT0", ";#it{p}_{T}^{#mu#mu}, GeV;", {HistType::kTH1D, {{100, 0., 10.}}}}}}; + + void collectMC(o2::aod::UDMcCollisions const& mcCollisions, o2::aod::UDMcParticles const& mcParticles) + { + int32_t nMCEvents = mcCollisions.size(); + // collect MC distributions + for (int32_t i = 0; i < nMCEvents; i++) { + auto mcPartsGroup = mcParticles.sliceBy(perMcCollision, i); + std::vector mcPartsFiltered; + for (const auto& mcPart : mcPartsGroup) { + if (!mcPart.isPhysicalPrimary() || std::abs(mcPart.pdgCode()) != muonPDG) { + continue; + } + mcPartsFiltered.emplace_back(mcPart); + } + // sanity check + if (mcPartsFiltered.size() != 2) { + continue; + } + const auto& part1 = mcPartsFiltered[0]; + const auto& part2 = mcPartsFiltered[1]; + TLorentzVector p1, p2, p; + p1.SetXYZM(part1.px(), part1.py(), part1.pz(), mmuon); + p2.SetXYZM(part2.px(), part2.py(), part2.pz(), mmuon); + p = p1 + p2; + registry.fill(HIST("PairsMC/Mass"), p.M()); + registry.fill(HIST("PairsMC/EtaMu"), p1.Eta()); + registry.fill(HIST("PairsMC/EtaMu"), p2.Eta()); + mcPartsFiltered.clear(); + } + } + + template + void processCandidate(o2::aod::UDCollision const& cand, o2::aod::UDMcParticles const& mcParticles, TTrack1& tr1, TTrack2& tr2) + { + TLorentzVector p1, p2, pPair; + p1.SetXYZM(tr1.px(), tr1.py(), tr1.pz(), mmuon); + p2.SetXYZM(tr2.px(), tr2.py(), tr2.pz(), mmuon); + pPair = p1 + p2; + // distributions without selection + registry.fill(HIST("PairSelection/MassRaw"), pPair.M()); + registry.fill(HIST("PairSelection/PtRaw"), pPair.Pt()); + // unlike-charged tracks requirement + if (tr1.sign() * tr2.sign() >= 0) { + return; + } + int mcPartId1 = tr1.udMcParticleId(); + int mcPartId2 = tr2.udMcParticleId(); + const auto& mcPart1 = mcParticles.iteratorAt(mcPartId1); + const auto& mcPart2 = mcParticles.iteratorAt(mcPartId2); + TLorentzVector mcP1, mcP2, pPairMC; + mcP1.SetXYZM(mcPart1.px(), mcPart1.py(), mcPart1.pz(), mmuon); + mcP2.SetXYZM(mcPart2.px(), mcPart2.py(), mcPart2.pz(), mmuon); + pPairMC = mcP1 + mcP2; + // reconstructed distributions and "MC" distributions for reconstructed tracks + registry.fill(HIST("PairSelection/Mass"), pPair.M()); + registry.fill(HIST("PairSelection/Pt"), pPair.Pt()); + registry.fill(HIST("PairSelection/EtaMu"), p1.Eta()); + registry.fill(HIST("PairSelection/EtaMu"), p2.Eta()); + registry.fill(HIST("PairSelection/MassMC"), pPairMC.M()); + // check FT0 signal + if (cand.hasFT0()) { + registry.fill(HIST("TracksWithFT0/Eta"), p1.Eta()); + registry.fill(HIST("TracksWithFT0/Eta"), p2.Eta()); + registry.fill(HIST("TracksWithFT0/TimeFT0A"), cand.timeFT0A()); + registry.fill(HIST("TracksWithFT0/TimeFT0C"), cand.timeFT0C()); + // if there is a signal, candidate passes if timeA is dummy + // and timeC is between +/- 1 ns + bool checkA = std::abs(cand.timeFT0A() - ft0DummyTime) < 1e-3; + bool checkC = cand.timeFT0C() > -1. && cand.timeFT0C() < 1.; + if (!(checkA && checkC)) { + return; + } + } + registry.fill(HIST("PairSelection/MassNoFT0"), pPair.M()); + registry.fill(HIST("PairSelection/MassNoFT0MC"), pPairMC.M()); + registry.fill(HIST("PairSelection/PtNoFT0"), pPair.Pt()); + if (mcPartId1 == -1 || mcPartId2 == -1) { + registry.fill(HIST("PairSelection/MassNoFT0Contam"), pPair.M()); + } + } + + // process candidates with 2 muon tracks + void processFwdMC(o2::aod::UDCollisions const& eventCandidates, + soa::Join const& muonTracks, + o2::aod::UDMcCollisions const& mcCollisions, + o2::aod::UDMcParticles const& mcParticles) + { + collectMC(mcCollisions, mcParticles); + + // assuming that candidates have exatly 2 muon tracks and 0 barrel tracks + for (const auto& cand : eventCandidates) { + auto candID = cand.globalIndex(); + auto muonTracksPerCand = muonTracks.select(o2::aod::udfwdtrack::udCollisionId == candID); + const auto& tr1 = muonTracksPerCand.iteratorAt(0); + const auto& tr2 = muonTracksPerCand.iteratorAt(1); + processCandidate(cand, mcParticles, tr1, tr2); + } + } + + // process candidates with 1 muon and 1 barrel tracks + void processSemiFwdMC(o2::aod::UDCollisions const& eventCandidates, + soa::Join const& muonTracks, + soa::Join const& barTracks, + o2::aod::UDMcCollisions const& mcCollisions, + o2::aod::UDMcParticles const& mcParticles) + { + collectMC(mcCollisions, mcParticles); + + // assuming that candidates have exatly 1 muon track and 1 barrel track + for (const auto& cand : eventCandidates) { + auto candID = cand.globalIndex(); + auto muonTracksPerCand = muonTracks.select(o2::aod::udfwdtrack::udCollisionId == candID); + auto barTracksPerCand = barTracks.select(o2::aod::udtrack::udCollisionId == candID); + const auto& tr1 = muonTracksPerCand.iteratorAt(0); + const auto& tr2 = barTracksPerCand.iteratorAt(0); + processCandidate(cand, mcParticles, tr1, tr2); + } + } + + // todo: add processes without MC information + PROCESS_SWITCH(UpcCandAnalyzer, processFwdMC, "Analyse forward candidates", false); + PROCESS_SWITCH(UpcCandAnalyzer, processSemiFwdMC, "Analyse semiforward candidates", false); +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{adaptAnalysisTask(cfgc)}; +} diff --git a/PWGUD/Tasks/UPCTrackSkimmerQA.cxx b/PWGUD/Tasks/UPCTrackSkimmerQA.cxx new file mode 100644 index 00000000000..18992211d01 --- /dev/null +++ b/PWGUD/Tasks/UPCTrackSkimmerQA.cxx @@ -0,0 +1,88 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +#include "Framework/runDataProcessing.h" +#include "Framework/AnalysisTask.h" +#include "Framework/AnalysisDataModel.h" +#include "PWGUD/DataModel/UDTables.h" + +#include "TLorentzVector.h" + +using namespace o2; +using namespace o2::framework; +using namespace o2::framework::expressions; + +#define mmuon 0.1056583745 + +struct UpcTrackSkimmerQa { + HistogramRegistry registry{ + "registry", + { + {"Muons/Timings/TrackTimeRes", ";Track time resolution, ns;", {HistType::kTH1D, {{100, 0., 10.}}}}, + {"Muons/Kine/Pt", ";#it{p}_{T}, GeV;", {HistType::kTH1D, {{100, 0., 10.}}}}, + {"Muons/Kine/Eta", ";#eta;", {HistType::kTH1D, {{100, -4., 4.}}}}, + // + {"Barrels/Timings/TrackTimeRes", ";Track time resolution, ns;", {HistType::kTH1D, {{100, 0., 10.}}}}, + {"Barrels/Kine/Pt", ";#it{p}_{T}, GeV;", {HistType::kTH1D, {{100, 0., 10.}}}}, + {"Barrels/Kine/Eta", ";#eta;", {HistType::kTH1D, {{100, -4., 4.}}}}, + {"Barrels/ITS/chi2", ";chi2;", {HistType::kTH1D, {{1100, -100., 1000.}}}}, + {"Barrels/ITS/nClusters", ";n clusters;", {HistType::kTH1I, {{10, 0, 10}}}}, + {"Barrels/TPC/chi2", ";chi2;", {HistType::kTH1D, {{110, -10., 100.}}}}, + {"Barrels/TPC/nClusters", ";n clusters;", {HistType::kTH1I, {{200, 0, 200}}}}, + }}; + + void process(soa::Join const& muonTracks, + soa::Join const& barTracks, + o2::aod::UDMcParticles const& mcParticles) + { + for (const auto& track : muonTracks) { + int32_t mcPartId = track.udMcParticleId(); + if (mcPartId < 0) { + continue; + } + const auto& mcPart = mcParticles.iteratorAt(mcPartId); + if (!(mcPart.isPhysicalPrimary() && std::abs(mcPart.pdgCode()) == 13)) { + continue; + } + TLorentzVector p; + p.SetXYZM(track.px(), track.py(), track.pz(), mmuon); + registry.fill(HIST("Muons/Timings/TrackTimeRes"), track.trackTimeRes()); + registry.fill(HIST("Muons/Kine/Pt"), p.Pt()); + registry.fill(HIST("Muons/Kine/Eta"), p.Eta()); + } + + for (const auto& track : barTracks) { + int32_t mcPartId = track.udMcParticleId(); + if (mcPartId < 0) { + continue; + } + const auto& mcPart = mcParticles.iteratorAt(mcPartId); + if (!(mcPart.isPhysicalPrimary() && std::abs(mcPart.pdgCode()) == 13)) { + continue; + } + TLorentzVector p; + p.SetXYZM(track.px(), track.py(), track.pz(), mmuon); + registry.fill(HIST("Barrels/Timings/TrackTimeRes"), track.trackTimeRes()); + registry.fill(HIST("Barrels/Kine/Pt"), p.Pt()); + registry.fill(HIST("Barrels/Kine/Eta"), p.Eta()); + registry.fill(HIST("Barrels/ITS/chi2"), track.itsChi2NCl()); + registry.fill(HIST("Barrels/ITS/nClusters"), track.itsNCls()); + registry.fill(HIST("Barrels/TPC/chi2"), track.tpcChi2NCl()); + registry.fill(HIST("Barrels/TPC/nClusters"), track.tpcNClsCrossedRows()); + } + } +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{ + adaptAnalysisTask(cfgc)}; +} From 2179cd0a8e632e0347cc7c81a95816406f731e54 Mon Sep 17 00:00:00 2001 From: Fabrizio Date: Thu, 21 Jul 2022 09:56:45 +0200 Subject: [PATCH 17/31] PWGHF: Add more checks on collision association probability (#1032) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * PWGHF: Add more checks on collision association probability Co-authored-by: Vít Kučera --- PWGHF/Tasks/HFMCValidation.cxx | 51 +++++++++++++++++++++++++++++++--- 1 file changed, 47 insertions(+), 4 deletions(-) diff --git a/PWGHF/Tasks/HFMCValidation.cxx b/PWGHF/Tasks/HFMCValidation.cxx index 2bbc105a45d..c78f8846172 100644 --- a/PWGHF/Tasks/HFMCValidation.cxx +++ b/PWGHF/Tasks/HFMCValidation.cxx @@ -52,6 +52,14 @@ static const std::array originNames = {"Prompt", "NonPrompt"}; /// - Momentum Conservation for these particles struct ValidationGenLevel { + + Configurable xVertexMin{"xVertexMin", -100., "min. x of generated primary vertex [cm]"}; + Configurable xVertexMax{"xVertexMax", 100., "max. x of generated primary vertex [cm]"}; + Configurable yVertexMin{"yVertexMin", -100., "min. y of generated primary vertex [cm]"}; + Configurable yVertexMax{"yVertexMax", 100., "max. y of generated primary vertex [cm]"}; + Configurable zVertexMin{"zVertexMin", -10., "min. z of generated primary vertex [cm]"}; + Configurable zVertexMax{"zVertexMax", 10., "max. z of generated primary vertex [cm]"}; + std::shared_ptr hPromptCharmHadronsPtDistr, hPromptCharmHadronsYDistr, hNonPromptCharmHadronsPtDistr, hNonPromptCharmHadronsYDistr, hPromptCharmHadronsDecLenDistr, hNonPromptCharmHadronsDecLenDistr, hQuarkPerEvent; HistogramRegistry registry{ @@ -101,6 +109,26 @@ struct ValidationGenLevel { } } + /// Primary-vertex selection + /// \param collision mccollision table row + template + bool selectVertex(const Col& collision) + { + // x position + if (collision.posX() < xVertexMin || collision.posX() > xVertexMax) { + return false; + } + // y position + if (collision.posY() < yVertexMin || collision.posY() > yVertexMax) { + return false; + } + // z position + if (collision.posZ() < zVertexMin || collision.posZ() > zVertexMax) { + return false; + } + return true; + } + void process(aod::McCollision const& mccollision, aod::McParticles const& particlesMC) { int cPerCollision = 0; @@ -115,6 +143,9 @@ struct ValidationGenLevel { std::vector listDaughters{}; for (auto& particle : particlesMC) { + if (!selectVertex(mccollision)) + continue; + int particlePdgCode = particle.pdgCode(); if (!particle.has_mothers()) { continue; @@ -242,13 +273,15 @@ struct ValidationRecLevel { std::array, nCharmHadrons> histDeltaPt, histDeltaPx, histDeltaPy, histDeltaPz, histDeltaSecondaryVertexX, histDeltaSecondaryVertexY, histDeltaSecondaryVertexZ, histDeltaDecayLength; std::array, 3>, 2>, nCharmHadrons> histPtDau, histEtaDau, histImpactParameterDau; std::array, 2>, nCharmHadrons> histPtReco; - std::array, 2> histOriginTracks; + std::array, 4> histOriginTracks; HistogramRegistry registry{"registry", {}}; void init(o2::framework::InitContext&) { - histOriginTracks[0] = registry.add("histOriginNonAssociatedTracks", ";origin;#it{p}_{T}^{reco} (GeV/#it{c})", HistType::kTH2F, {{4, -1.5, 2.5}, {50, 0., 10.}}); - histOriginTracks[1] = registry.add("histOriginAssociatedTracks", ";origin;#it{p}_{T}^{reco} (GeV/#it{c})", HistType::kTH2F, {{4, -1.5, 2.5}, {50, 0., 10.}}); + histOriginTracks[0] = registry.add("histOriginNonAssociatedTracks", ";origin;#it{p}_{T}^{reco} (GeV/#it{c})", HistType::kTH2F, {{4, -1.5, 2.5}, {50, 0., 10.}}); // tracks not associated to any collision + histOriginTracks[1] = registry.add("histOriginAssociatedTracks", ";origin;#it{p}_{T}^{reco} (GeV/#it{c})", HistType::kTH2F, {{4, -1.5, 2.5}, {50, 0., 10.}}); // tracks associasted to a collision + histOriginTracks[2] = registry.add("histOriginGoodAssociatedTracks", ";origin;#it{p}_{T}^{reco} (GeV/#it{c})", HistType::kTH2F, {{4, -1.5, 2.5}, {50, 0., 10.}}); // tracks associated to the correct collision (considering the MC collision index) + histOriginTracks[3] = registry.add("histOriginWrongAssociatedTracks", ";origin;#it{p}_{T}^{reco} (GeV/#it{c})", HistType::kTH2F, {{4, -1.5, 2.5}, {50, 0., 10.}}); // tracks associated to the wrong collision (considering the MC collision index) for (std::size_t iHist{0}; iHist < histOriginTracks.size(); ++iHist) { histOriginTracks[iHist]->GetXaxis()->SetBinLabel(1, "no MC particle"); histOriginTracks[iHist]->GetXaxis()->SetBinLabel(2, "no quark"); @@ -277,8 +310,9 @@ struct ValidationRecLevel { using HfCandProng2WithMCRec = soa::Join; using HfCandProng3WithMCRec = soa::Join; + using CollisionsWithMCLabels = soa::Join; - void process(HfCandProng2WithMCRec const& cand2Prongs, HfCandProng3WithMCRec const& cand3Prongs, aod::BigTracksMC const& tracks, aod::McParticles const& particlesMC) + void process(HfCandProng2WithMCRec const& cand2Prongs, HfCandProng3WithMCRec const& cand3Prongs, aod::BigTracksMC const& tracks, aod::McParticles const& particlesMC, aod::McCollisions const& mcCollisions, CollisionsWithMCLabels const& collisions) { // loop over tracks for (auto& track : tracks) { @@ -287,6 +321,15 @@ struct ValidationRecLevel { auto particle = track.mcParticle(); // get corresponding MC particle to check origin auto origin = RecoDecay::getCharmHadronOrigin(particlesMC, particle, true); histOriginTracks[index]->Fill(origin, track.pt()); + if (index) { + auto collision = collisions.rawIteratorAt(track.collisionId()); + auto mcCollision = particle.mcCollision(); + uint index2 = 2; + if (collision.mcCollisionId() - particle.mcCollisionId() == 0 && std::abs(collision.posZ() - mcCollision.posZ()) < 0.02) { // 200 microns compatibility of Z vertex position also required + index2 = 1; + } + histOriginTracks[index + index2]->Fill(origin, track.pt()); + } } else { histOriginTracks[index]->Fill(-1., track.pt()); } From 78a1657be548955dddcc7c8f492ed678f0a60830 Mon Sep 17 00:00:00 2001 From: Giovanni Malfattore <89481844+giovannimalfattore@users.noreply.github.com> Date: Thu, 21 Jul 2022 14:37:22 +0200 Subject: [PATCH 18/31] Fix building issues with NucleiTask (#1034) * Fix y cut. Add antiproton histograms. --- PWGLF/Tasks/LFNucleiBATask.cxx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/PWGLF/Tasks/LFNucleiBATask.cxx b/PWGLF/Tasks/LFNucleiBATask.cxx index bccec3ec7d9..1acb0c92527 100644 --- a/PWGLF/Tasks/LFNucleiBATask.cxx +++ b/PWGLF/Tasks/LFNucleiBATask.cxx @@ -74,8 +74,8 @@ struct LFNucleiBATask { // trackQA histos.add("tracks/h1Eta", "pseudoRapidity; #eta; counts", HistType::kTH1F, {{200, -1.0, 1.0}}); - histos.add("tracks/h1VarPhi", "#phi; #phi; counts", HistType::kTH1F, {{80, -0.5, 7.5}}); - histos.add("tracks/h2EtaVsPhi", "#eta (TOF) vs #phi; #eta; #phi", HistType::kTH2F, {{200, -1.0, 1.0}, {80, -0.5, 7.5}}); + histos.add("tracks/h1VarPhi", "#phi; #phi; counts", HistType::kTH1F, {{63, 0.0, 6.3}}); + histos.add("tracks/h2EtaVsPhi", "#eta vs #phi; #eta; #phi", HistType::kTH2F, {{200, -1.0, 1.0}, {63, 0.0, 6.3}}); histos.add("tracks/h1pT", "Track #it{p}_{T}; #it{p}_{T} (GeV/#it{c}); counts", HistType::kTH1F, {{1000, 0., 10}}); histos.add("tracks/h1p", "Track momentum; p (GeV/#it{c}); counts", HistType::kTH1F, {{1000, 0., 10.}}); From 4ade33b3c2037825c1ba95ba948b389b8adb7bec Mon Sep 17 00:00:00 2001 From: Rosario Turrisi Date: Thu, 21 Jul 2022 16:15:52 +0200 Subject: [PATCH 19/31] Eta histos wider limits (now -2,2) (#1037) * Eta histos wider limits (now -2,2) * Eta histos wider limits (now -2,2) and smaller pt bins up to 0.5 Gev/c * Got read of unused configurables --- DPG/Tasks/qaMatchEff.cxx | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/DPG/Tasks/qaMatchEff.cxx b/DPG/Tasks/qaMatchEff.cxx index 7f929a55340..66ec62defe3 100644 --- a/DPG/Tasks/qaMatchEff.cxx +++ b/DPG/Tasks/qaMatchEff.cxx @@ -40,20 +40,17 @@ struct qaMatchEff { // Histogram configuration // // histo x axes limits - Configurable etaMin{"eta-min", -0.8f, "Lower limit in eta"}; - Configurable etaMax{"eta-max", 0.8f, "Upper limit in eta"}; + Configurable etaMin{"eta-min", -2.0f, "Lower limit in eta"}; + Configurable etaMax{"eta-max", 2.0f, "Upper limit in eta"}; Configurable phiMin{"phi-min", 0.0f, "Lower limit in phi"}; Configurable phiMax{"phi-max", 1.0f * TwoPI, "Upper limit in phi"}; - Configurable ptMin{"pt-min", 0.0f, "Lower limit in pT"}; - Configurable ptMax{"pt-max", 15.f, "Upper limit in pT"}; // histos bins - Configurable ptBins{"pt-bins", 16, "Number of pT bins"}; - Configurable etaBins{"eta-bins", 16, "Number of eta bins"}; + Configurable etaBins{"eta-bins", 40, "Number of eta bins"}; Configurable phiBins{"phi-bins", 18, "Number of phi bins"}; // histo axes // // non uniform pt binning - std::vector ptBinning = {0.0, 0.5, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15.0}; + std::vector ptBinning = {0.0, 0.05, 0.1, 0.15, 0.2, 0.25, 0.3, 0.35, 0.4, 0.45, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15.0}; AxisSpec axisPt{ptBinning, "#it{p}_{T} (GeV/#it{c})"}; // const AxisSpec axisPt{ptBins, ptMin, ptMax, "#it{p}_{T} (GeV/#it{c})"}; // From 4047552184a67dd9b5a017e4b82bae27fe8a3e30 Mon Sep 17 00:00:00 2001 From: Timo Wilken Date: Thu, 21 Jul 2022 16:25:33 +0200 Subject: [PATCH 20/31] Fix MegaLinter workflow location Sold to "Ox Security", so repo ownership has changed. --- .github/workflows/mega-linter.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/mega-linter.yml b/.github/workflows/mega-linter.yml index 1d2e063926c..bf43e0644b5 100644 --- a/.github/workflows/mega-linter.yml +++ b/.github/workflows/mega-linter.yml @@ -33,7 +33,7 @@ jobs: id: ml # You can override MegaLinter flavor used to have faster performances # More info at https://megalinter.github.io/flavors/ - uses: megalinter/megalinter@v5 + uses: oxsecurity/megalinter@v5 env: # All available variables are described in documentation # https://megalinter.github.io/configuration/ From d1f54f1c891cc36e7ca672eb26777569054bef48 Mon Sep 17 00:00:00 2001 From: Fabrizio Date: Thu, 21 Jul 2022 16:55:41 +0200 Subject: [PATCH 21/31] PWGHF: Minor modifications (#1035) --- PWGHF/Tasks/HFMCValidation.cxx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/PWGHF/Tasks/HFMCValidation.cxx b/PWGHF/Tasks/HFMCValidation.cxx index c78f8846172..4faaa9c13b2 100644 --- a/PWGHF/Tasks/HFMCValidation.cxx +++ b/PWGHF/Tasks/HFMCValidation.cxx @@ -322,10 +322,10 @@ struct ValidationRecLevel { auto origin = RecoDecay::getCharmHadronOrigin(particlesMC, particle, true); histOriginTracks[index]->Fill(origin, track.pt()); if (index) { - auto collision = collisions.rawIteratorAt(track.collisionId()); + auto collision = track.collision_as(); auto mcCollision = particle.mcCollision(); uint index2 = 2; - if (collision.mcCollisionId() - particle.mcCollisionId() == 0 && std::abs(collision.posZ() - mcCollision.posZ()) < 0.02) { // 200 microns compatibility of Z vertex position also required + if ((collision.mcCollisionId() == particle.mcCollisionId()) && std::abs(collision.posZ() - mcCollision.posZ()) < 0.02) { // 200 microns compatibility of Z vertex position also required index2 = 1; } histOriginTracks[index + index2]->Fill(origin, track.pt()); From 768cbcff4ac49ca97dd0a10a27118c4e48e6e43a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mario=20Kr=C3=BCger?= Date: Thu, 21 Jul 2022 17:30:19 +0200 Subject: [PATCH 22/31] PWGLF: move free-floating Preslice<> into task (#1040) --- PWGLF/Tasks/spectraCharged.cxx | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/PWGLF/Tasks/spectraCharged.cxx b/PWGLF/Tasks/spectraCharged.cxx index 16c460ade4e..14b68b4eb84 100644 --- a/PWGLF/Tasks/spectraCharged.cxx +++ b/PWGLF/Tasks/spectraCharged.cxx @@ -12,9 +12,6 @@ // task for charged particle pt spectra vs multiplicity analysis with 2d unfolding for run3+ // mimics https://github.com/alisw/AliPhysics/blob/master/PWGLF/SPECTRA/ChargedHadrons/MultDepSpec/AliMultDepSpecAnalysisTask.cxx -// run for data as: o2-analysis-timestamp | o2-analysis-event-selection | o2-analysis-trackextension | o2-analysis-trackselection | o2-analysis-lf-spectra-charged --aod-file AO2D_data.root -// run for mc as: o2-analysis-timestamp --isRun2MC | o2-analysis-event-selection --isMC | o2-analysis-trackextension | o2-analysis-trackselection | o2-analysis-lf-spectra-charged --aod-file AO2D_mc.root --isMC - #include "Framework/HistogramRegistry.h" #include "ReconstructionDataFormats/Track.h" #include "Framework/runDataProcessing.h" @@ -38,7 +35,7 @@ struct chargedSpectra { Service pdg; // task settings that can be steered via hyperloop - Configurable isRun3{"isRun3", true, "is Run3 dataset"}; // TODO: derive this from metadata once possible to get rid of the flag + Configurable isRun3{"isRun3", true, "is Run3 dataset"}; Configurable maxMultMeas{"maxMultMeas", 100, "max measured multiplicity"}; Configurable maxMultTrue{"maxMultTrue", 100, "max true multiplicity"}; Configurable etaCut{"etaCut", 0.8f, "eta cut"}; @@ -84,6 +81,7 @@ struct chargedSpectra { using CollisionTableMC = soa::SmallGroups>; using TrackTableMC = soa::Join; using ParticleTableMC = aod::McParticles; + Preslice perCollision = aod::track::collisionId; void processMC(CollisionTableMCTrue::iterator const& mcCollision, CollisionTableMC const& collisions, TrackTableMC const& tracks, ParticleTableMC const& particles); PROCESS_SWITCH(chargedSpectra, processMC, "process mc", true); @@ -178,8 +176,6 @@ void chargedSpectra::processData(CollisionTableData::iterator const& collision, * Entrypoint to processes mc. */ //************************************************************************************************** -Preslice perCollision = aod::track::collisionId; - void chargedSpectra::processMC(CollisionTableMCTrue::iterator const& mcCollision, CollisionTableMC const& collisions, TrackTableMC const& tracks, ParticleTableMC const& particles) { histos.fill(HIST("collision_ambiguity"), collisions.size()); From 0e288dd2bee1d3114ddb36d12a339608eb176a16 Mon Sep 17 00:00:00 2001 From: Giovanni Malfattore <89481844+giovannimalfattore@users.noreply.github.com> Date: Fri, 22 Jul 2022 09:21:14 +0200 Subject: [PATCH 23/31] Add antiparticle histograms in light antinuclei analysis (#1043) * Add antiparticle histograms in nuclei analysis --- PWGLF/Tasks/LFNucleiBATask.cxx | 117 +++++++++++++++++++++++++-------- 1 file changed, 90 insertions(+), 27 deletions(-) diff --git a/PWGLF/Tasks/LFNucleiBATask.cxx b/PWGLF/Tasks/LFNucleiBATask.cxx index 1acb0c92527..38c0ed780e1 100644 --- a/PWGLF/Tasks/LFNucleiBATask.cxx +++ b/PWGLF/Tasks/LFNucleiBATask.cxx @@ -88,6 +88,10 @@ struct LFNucleiBATask { histos.add("tracks/deuteron/h1DeuteronSpectra", "#it{p}_{T} (d)", HistType::kTH1F, {ptAxis}); histos.add("tracks/helium/h1HeliumSpectra", "#it{p}_{T} (He)", HistType::kTH1F, {ptAxis}); + histos.add("tracks/proton/h1antiProtonSpectra", "#it{p}_{T} (#bar{p})", HistType::kTH1F, {ptAxis}); + histos.add("tracks/deuteron/h1antiDeuteronSpectra", "#it{p}_{T} (#bar{d})", HistType::kTH1F, {ptAxis}); + histos.add("tracks/helium/h1antiHeliumSpectra", "#it{p}_{T} (#bar{He})", HistType::kTH1F, {ptAxis}); + if (doprocessMCReco) { histos.add("tracks/proton/h1ProtonSpectraTrue", "#it{p}_{T} (p)", HistType::kTH1F, {ptAxis}); histos.add("tracks/proton/h1ProtonSpectraTruePrim", "#it{p}_{T} (p)", HistType::kTH1F, {ptAxis}); @@ -115,21 +119,31 @@ struct LFNucleiBATask { histos.add("tracks/helium/h1HeliumSpectraTrueTransport", "#it{p}_{T} (He)", HistType::kTH1F, {ptAxis}); histos.add("tracks/helium/h1antiHeliumSpectraTrue", "#it{p}_{T} (He)", HistType::kTH1F, {ptAxis}); + histos.add("tracks/helium/h1antiHeliumSpectraTruePrim", "#it{p}_{T} (He)", HistType::kTH1F, {ptAxis}); + histos.add("tracks/helium/h1antiHeliumSpectraTrueSec", "#it{p}_{T} (He)", HistType::kTH1F, {ptAxis}); + histos.add("tracks/helium/h1antiHeliumSpectraTrueTransport", "#it{p}_{T} (He)", HistType::kTH1F, {ptAxis}); } - histos.add("tracks/h2TPCsignVsTPCmomentum", "-dE/dX vs p; p (GeV/c); -dE/dx (a.u.)", HistType::kTH2F, {{500, 0.0, 5.0}, {81000, 0.0, 1E3}}); - histos.add("tracks/h2TOFbetaVsP", "#beta (TOF) vs p; p (GeV/c); #beta", HistType::kTH2F, {{500, 0.0, 5.0}, {1200, 0.0, 1.2}}); + histos.add("tracks/h2TPCsignVsTPCmomentum", "-dE/dX vs p/Z; p/Z (GeV/c); -dE/dx (a.u.)", HistType::kTH2F, {{1000, -5.f, 5.f}, {81000, 0.0, 1E3}}); + histos.add("tracks/h2TOFbetaVsP", "#beta (TOF) vs p/Z; p/Z (GeV/c); #beta", HistType::kTH2F, {{1000, -5.f, 5.f}, {1200, 0.0, 1.2}}); histos.add("tracks/pion/h2PionVspTNSigmaTPC", "NSigmaTPC(pi) vs pT; #it{p}_{T} (GeV/#it{c}); NSigmaTPC", HistType::kTH2F, {{ptAxis}, {200, -10, 10.}}); histos.add("tracks/kaon/h2KaonVspTNSigmaTPC", "NSigmaTPC(Ka) vs pT; #it{p}_{T} (GeV/#it{c}); NSigmaTPC", HistType::kTH2F, {{ptAxis}, {200, -10, 10.}}); - histos.add("tracks/proton/h2ProtonVspTNSigmaTPC", "NSigmaTPC(proton) vs pT; #it{p}_{T} (GeV/#it{c}); NSigmaTPC", HistType::kTH2F, {{ptAxis}, {200, -10, 10.}}); - histos.add("tracks/deuteron/h2DeuteronVspTNSigmaTPC", "NSigmaTPC(D) vs pT; #it{p}_{T} (GeV/#it{c}); NSigmaTPC", HistType::kTH2F, {{ptAxis}, {200, -10, 10.}}); + histos.add("tracks/proton/h2ProtonVspTNSigmaTPC", "NSigmaTPC(p) vs pT; #it{p}_{T} (GeV/#it{c}); NSigmaTPC", HistType::kTH2F, {{ptAxis}, {200, -10, 10.}}); + histos.add("tracks/deuteron/h2DeuteronVspTNSigmaTPC", "NSigmaTPC(d) vs pT; #it{p}_{T} (GeV/#it{c}); NSigmaTPC", HistType::kTH2F, {{ptAxis}, {200, -10, 10.}}); histos.add("tracks/helium/h2HeliumVspTNSigmaTPC", "NSigmaTPC(He) vs pT; #it{p}_{T} (GeV/#it{c}); NSigmaTPC", HistType::kTH2F, {{ptAxis}, {200, -10, 10.}}); + histos.add("tracks/proton/h2antiProtonVspTNSigmaTPC", "NSigmaTPC(#bar{p}) vs pT; #it{p}_{T} (GeV/#it{c}); NSigmaTPC", HistType::kTH2F, {{ptAxis}, {200, -10, 10.}}); + histos.add("tracks/deuteron/h2antiDeuteronVspTNSigmaTPC", "NSigmaTPC(#bar{d}) vs pT; #it{p}_{T} (GeV/#it{c}); NSigmaTPC", HistType::kTH2F, {{ptAxis}, {200, -10, 10.}}); + histos.add("tracks/helium/h2antiHeliumVspTNSigmaTPC", "NSigmaTPC(#bar{He}) vs pT; #it{p}_{T} (GeV/#it{c}); NSigmaTPC", HistType::kTH2F, {{ptAxis}, {200, -10, 10.}}); + histos.add("tracks/pion/h2PionVspTNSigmaTOF", "NSigmaTOF(pi) vs pT; #it{p}_{T} (GeV/#it{c}); NSigmaTOF", HistType::kTH2F, {{ptAxis}, {200, -10, 10.}}); histos.add("tracks/kaon/h2KaonVspTNSigmaTOF", "NSigmaTOF(Ka) vs pT; #it{p}_{T} (GeV/#it{c}); NSigmaTOF", HistType::kTH2F, {{ptAxis}, {200, -10, 10.}}); - histos.add("tracks/proton/h2ProtonVspTNSigmaTOF", "NSigmaTOF(proton) vs pT; #it{p}_{T} (GeV/#it{c}); NSigmaTOF", HistType::kTH2F, {{ptAxis}, {200, -10, 10.}}); - histos.add("tracks/deuteron/h2DeuteronVspTNSigmaTOF", "NSigmaTOF(D) vs pT; #it{p}_{T} (GeV/#it{c}); NSigmaTOF", HistType::kTH2F, {{ptAxis}, {200, -10, 10.}}); + histos.add("tracks/proton/h2ProtonVspTNSigmaTOF", "NSigmaTOF(p) vs pT; #it{p}_{T} (GeV/#it{c}); NSigmaTOF", HistType::kTH2F, {{ptAxis}, {200, -10, 10.}}); + histos.add("tracks/deuteron/h2DeuteronVspTNSigmaTOF", "NSigmaTOF(d) vs pT; #it{p}_{T} (GeV/#it{c}); NSigmaTOF", HistType::kTH2F, {{ptAxis}, {200, -10, 10.}}); histos.add("tracks/helium/h2HeliumVspTNSigmaTOF", "NSigmaTOF(He) vs pT; #it{p}_{T} (GeV/#it{c}); NSigmaTOF", HistType::kTH2F, {{ptAxis}, {200, -10, 10.}}); + histos.add("tracks/proton/h2antiProtonVspTNSigmaTOF", "NSigmaTOF(#bar{p}) vs pT; #it{p}_{T} (GeV/#it{c}); NSigmaTOF", HistType::kTH2F, {{ptAxis}, {200, -10, 10.}}); + histos.add("tracks/deuteron/h2antiDeuteronVspTNSigmaTOF", "NSigmaTOF(#bar{d}) vs pT; #it{p}_{T} (GeV/#it{c}); NSigmaTOF", HistType::kTH2F, {{ptAxis}, {200, -10, 10.}}); + histos.add("tracks/helium/h2antiHeliumVspTNSigmaTOF", "NSigmaTOF(#bar{He}) vs pT; #it{p}_{T} (GeV/#it{c}); NSigmaTOF", HistType::kTH2F, {{ptAxis}, {200, -10, 10.}}); // TOF mass histograms histos.add("tracks/h2TOFmassVsPt", "h2TOFmassVsPt; TOFmass; #it{p}_{T} (GeV)", HistType::kTH2F, {{600, 0., 3.}, {500, 0., 5.}}); @@ -139,6 +153,10 @@ struct LFNucleiBATask { histos.add("tracks/deuteron/h2TOFmass2DeuteronVsPt", "#Delta M^{2} (d) vs #it{p}_{T}; #Delta M^{2} (d); #it{p}_{T} (GeV/#it{c})", HistType::kTH2F, {{1000, -5., 5.}, {800, 0., 8.}}); histos.add("tracks/helium/h2TOFmass2HeliumVsPt", "#Delta M^{2} (He) vs #it{p}_{T}; #Delta M^{2} (He); #it{p}_{T} (GeV/#it{c})", HistType::kTH2F, {{1800, -9., 9.}, {800, 0., 8.}}); + histos.add("tracks/proton/h2TOFmass2antiProtonVsPt", "#Delta M^{2} (#bar{p}) vs #it{p}_{T}; #Delta M^{2} (#bar{p}); #it{p}_{T} (GeV/#it{c})", HistType::kTH2F, {{600, -3., 3.}, {800, 0., 8.}}); + histos.add("tracks/deuteron/h2TOFmass2antiDeuteronVsPt", "#Delta M^{2} (#bar{d}) vs #it{p}_{T}; #Delta M^{2} (#bar{d}); #it{p}_{T} (GeV/#it{c})", HistType::kTH2F, {{1000, -5., 5.}, {800, 0., 8.}}); + histos.add("tracks/helium/h2TOFmass2antiHeliumVsPt", "#Delta M^{2} (#bar{He}) vs #it{p}_{T}; #Delta M^{2} (#bar{He}); #it{p}_{T} (GeV/#it{c})", HistType::kTH2F, {{1800, -9., 9.}, {800, 0., 8.}}); + // MC histograms // AxisSpec ptAxis = {2000, 0.f, 20.f, "#it{p}_{T} (GeV/#it{c})"}; histos.add("spectraGen/histGenVetxZ", "PosZ generated events", HistType::kTH1F, {{2000, -20.f, 20.f, "Vertex Z (cm)"}}); @@ -216,33 +234,57 @@ struct LFNucleiBATask { // TPC // if(std::abs(track.nsigTPCD()) < 5. && std::abs(track.nsigTOFD()) < 3.) - histos.fill(HIST("tracks/h2TPCsignVsTPCmomentum"), track.tpcInnerParam(), track.tpcSignal()); + histos.fill(HIST("tracks/h2TPCsignVsTPCmomentum"), track.tpcInnerParam() / (1.f * track.sign()), track.tpcSignal()); histos.fill(HIST("tracks/pion/h2PionVspTNSigmaTPC"), track.pt(), track.nsigTPCPi()); histos.fill(HIST("tracks/kaon/h2KaonVspTNSigmaTPC"), track.pt(), track.nsigTPCKa()); - histos.fill(HIST("tracks/proton/h2ProtonVspTNSigmaTPC"), track.pt(), track.nsigTPCPr()); - histos.fill(HIST("tracks/deuteron/h2DeuteronVspTNSigmaTPC"), track.pt(), track.nsigTPCD()); - histos.fill(HIST("tracks/helium/h2HeliumVspTNSigmaTPC"), track.pt(), track.nsigTPC3He()); + if (track.sign() > 0) { + histos.fill(HIST("tracks/proton/h2ProtonVspTNSigmaTPC"), track.pt(), track.nsigTPCPr()); + histos.fill(HIST("tracks/deuteron/h2DeuteronVspTNSigmaTPC"), track.pt(), track.nsigTPCD()); + histos.fill(HIST("tracks/helium/h2HeliumVspTNSigmaTPC"), track.pt(), track.nsigTPC3He()); + } else { + histos.fill(HIST("tracks/proton/h2antiProtonVspTNSigmaTPC"), track.pt(), track.nsigTPCPr()); + histos.fill(HIST("tracks/deuteron/h2antiDeuteronVspTNSigmaTPC"), track.pt(), track.nsigTPCD()); + histos.fill(HIST("tracks/helium/h2antiHeliumVspTNSigmaTPC"), track.pt(), track.nsigTPC3He()); + } // TOF histos.fill(HIST("tracks/pion/h2PionVspTNSigmaTOF"), track.pt(), track.nsigTOFPi()); histos.fill(HIST("tracks/kaon/h2KaonVspTNSigmaTOF"), track.pt(), track.nsigTOFKa()); - histos.fill(HIST("tracks/proton/h2ProtonVspTNSigmaTOF"), track.pt(), track.nsigTOFPr()); - histos.fill(HIST("tracks/deuteron/h2DeuteronVspTNSigmaTOF"), track.pt(), track.nsigTOFD()); - histos.fill(HIST("tracks/helium/h2HeliumVspTNSigmaTOF"), track.pt(), track.nsigTOF3He()); + if (track.sign() > 0) { + histos.fill(HIST("tracks/proton/h2ProtonVspTNSigmaTOF"), track.pt(), track.nsigTOFPr()); + histos.fill(HIST("tracks/deuteron/h2DeuteronVspTNSigmaTOF"), track.pt(), track.nsigTOFD()); + histos.fill(HIST("tracks/helium/h2HeliumVspTNSigmaTOF"), track.pt(), track.nsigTOF3He()); + } else { + histos.fill(HIST("tracks/proton/h2antiProtonVspTNSigmaTOF"), track.pt(), track.nsigTOFPr()); + histos.fill(HIST("tracks/deuteron/h2antiDeuteronVspTNSigmaTOF"), track.pt(), track.nsigTOFD()); + histos.fill(HIST("tracks/helium/h2antiHeliumVspTNSigmaTOF"), track.pt(), track.nsigTOF3He()); + } // PID - if (std::abs(track.nsigTPCPr()) < nsigmaTPCcut) - histos.fill(HIST("tracks/proton/h1ProtonSpectra"), track.pt()); + if (std::abs(track.nsigTPCPr()) < nsigmaTPCcut) { + if (track.sign() > 0) + histos.fill(HIST("tracks/proton/h1ProtonSpectra"), track.pt()); + else + histos.fill(HIST("tracks/proton/h1antiProtonSpectra"), track.pt()); + } - if (std::abs(track.nsigTPCD()) < nsigmaTPCcut) - histos.fill(HIST("tracks/deuteron/h1DeuteronSpectra"), track.pt()); + if (std::abs(track.nsigTPCD()) < nsigmaTPCcut) { + if (track.sign() > 0) + histos.fill(HIST("tracks/deuteron/h1DeuteronSpectra"), track.pt()); + else + histos.fill(HIST("tracks/deuteron/h1antiDeuteronSpectra"), track.pt()); + } - if (std::abs(track.nsigTPC3He()) < nsigmaTPCcut) - histos.fill(HIST("tracks/helium/h1HeliumSpectra"), track.pt()); + if (std::abs(track.nsigTPC3He()) < nsigmaTPCcut) { + if (track.sign() > 0) + histos.fill(HIST("tracks/helium/h1HeliumSpectra"), track.pt()); + else + histos.fill(HIST("tracks/helium/h1antiHeliumSpectra"), track.pt()); + } if (track.hasTOF()) { - histos.fill(HIST("tracks/h2TOFbetaVsP"), track.p(), track.beta()); + histos.fill(HIST("tracks/h2TOFbetaVsP"), track.p() / (1.f * track.sign()), track.beta()); if ((track.beta() * track.beta()) < 1.) { gamma = 1.f / TMath::Sqrt(1.f - (track.beta() * track.beta())); massTOF = track.p() / TMath::Sqrt(gamma * gamma - 1.f); @@ -251,14 +293,25 @@ struct LFNucleiBATask { } histos.fill(HIST("tracks/h2TOFmassVsPt"), massTOF, track.pt()); - if (std::abs(track.nsigTPCPr()) < nsigmaTPCcut) - histos.fill(HIST("tracks/proton/h2TOFmass2ProtonVsPt"), massTOF * massTOF - fMassProton * fMassProton, track.pt()); - - if (std::abs(track.nsigTPCD()) < nsigmaTPCcut) - histos.fill(HIST("tracks/deuteron/h2TOFmass2DeuteronVsPt"), massTOF * massTOF - fMassDeuteron * fMassDeuteron, track.pt()); + if (std::abs(track.nsigTPCPr()) < nsigmaTPCcut) { + if (track.sign() > 0) + histos.fill(HIST("tracks/proton/h2TOFmass2ProtonVsPt"), massTOF * massTOF - fMassProton * fMassProton, track.pt()); + else + histos.fill(HIST("tracks/proton/h2TOFmass2antiProtonVsPt"), massTOF * massTOF - fMassProton * fMassProton, track.pt()); + } - if (std::abs(track.nsigTPC3He()) < nsigmaTPCcut) - histos.fill(HIST("tracks/helium/h2TOFmass2HeliumVsPt"), massTOF * massTOF - fMassHelium * fMassHelium, track.pt()); + if (std::abs(track.nsigTPCD()) < nsigmaTPCcut) { + if (track.sign() > 0) + histos.fill(HIST("tracks/deuteron/h2TOFmass2DeuteronVsPt"), massTOF * massTOF - fMassDeuteron * fMassDeuteron, track.pt()); + else + histos.fill(HIST("tracks/deuteron/h2TOFmass2antiDeuteronVsPt"), massTOF * massTOF - fMassDeuteron * fMassDeuteron, track.pt()); + } + if (std::abs(track.nsigTPC3He()) < nsigmaTPCcut) { + if (track.sign() > 0) + histos.fill(HIST("tracks/helium/h2TOFmass2HeliumVsPt"), massTOF * massTOF - fMassHelium * fMassHelium, track.pt()); + else + histos.fill(HIST("tracks/helium/h2TOFmass2antiHeliumVsPt"), massTOF * massTOF - fMassHelium * fMassHelium, track.pt()); + } } if constexpr (IsMC) { bool isPhysPrim = track.isPhysicalPrimary(); @@ -313,6 +366,16 @@ struct LFNucleiBATask { if (!isPhysPrim && !isProdByGen) histos.fill(HIST("tracks/helium/h1HeliumSpectraTrueTransport"), track.pt()); } + + if (track.pdgCode() == -PDGHelium) { + histos.fill(HIST("tracks/helium/h1antiHeliumSpectraTrue"), track.pt()); + if (isPhysPrim) + histos.fill(HIST("tracks/helium/h1antiHeliumSpectraTruePrim"), track.pt()); + if (!isPhysPrim && isProdByGen) + histos.fill(HIST("tracks/helium/h1antiHeliumSpectraTrueSec"), track.pt()); + if (!isPhysPrim && !isProdByGen) + histos.fill(HIST("tracks/helium/h1antiHeliumSpectraTrueTransport"), track.pt()); + } } } } From 4ac46a444416efd0253be54f4d2cfdeeec6f063b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=B2=20Jacazio?= Date: Fri, 22 Jul 2022 13:00:07 +0200 Subject: [PATCH 24/31] Extend DPG tools (#1044) - more plots with different ev. time for TOF - Fixes in hist naming in qaEfficiency - extend qaPIDPTC - improve PDG selection in qa lite - Add pdg selection configurable for multiple particles --- DPG/Tasks/qaEfficiency.cxx | 28 +++++++------- DPG/Tasks/qaEventTrackLite.cxx | 40 +++++++++++++++----- DPG/Tasks/qaPIDTOF.h | 67 +++++++++++++++++++++++++++++++--- DPG/Tasks/qaPIDTPC.h | 57 +++++++++++++++++++++++++---- 4 files changed, 156 insertions(+), 36 deletions(-) diff --git a/DPG/Tasks/qaEfficiency.cxx b/DPG/Tasks/qaEfficiency.cxx index bfcd7c0a895..9937b326b85 100644 --- a/DPG/Tasks/qaEfficiency.cxx +++ b/DPG/Tasks/qaEfficiency.cxx @@ -142,10 +142,10 @@ struct QaEfficiency { "MC/ka/pos/prm/pt/num", "MC/pr/pos/prm/pt/num", "MC/de/pos/prm/pt/num", "MC/tr/pos/prm/pt/num", "MC/he/pos/prm/pt/num", "MC/al/pos/prm/pt/num", "MC/all/pos/prm/pt/num", - "MC/el/den/prm/pt/num", "MC/mu/den/prm/pt/num", "MC/pi/den/prm/pt/num", - "MC/ka/den/prm/pt/num", "MC/pr/den/prm/pt/num", "MC/de/den/prm/pt/num", - "MC/tr/den/prm/pt/num", "MC/he/den/prm/pt/num", "MC/al/den/prm/pt/num", - "MC/all/den/prm/pt/num"}; + "MC/el/neg/prm/pt/num", "MC/mu/neg/prm/pt/num", "MC/pi/neg/prm/pt/num", + "MC/ka/neg/prm/pt/num", "MC/pr/neg/prm/pt/num", "MC/de/neg/prm/pt/num", + "MC/tr/neg/prm/pt/num", "MC/he/neg/prm/pt/num", "MC/al/neg/prm/pt/num", + "MC/all/neg/prm/pt/num"}; static constexpr std::string_view hPtPrmNumTrk[nHistograms] = {"MC/el/sum/prm/pt/numtrk", "MC/mu/sum/prm/pt/numtrk", "MC/pi/sum/prm/pt/numtrk", "MC/ka/sum/prm/pt/numtrk", "MC/pr/sum/prm/pt/numtrk", "MC/de/sum/prm/pt/numtrk", "MC/tr/sum/prm/pt/numtrk", "MC/he/sum/prm/pt/numtrk", "MC/al/sum/prm/pt/numtrk", @@ -191,10 +191,10 @@ struct QaEfficiency { "MC/ka/pos/dec/pt/num", "MC/pr/pos/dec/pt/num", "MC/de/pos/dec/pt/num", "MC/tr/pos/dec/pt/num", "MC/he/pos/dec/pt/num", "MC/al/pos/dec/pt/num", "MC/all/pos/dec/pt/num", - "MC/el/den/dec/pt/num", "MC/mu/den/dec/pt/num", "MC/pi/den/dec/pt/num", - "MC/ka/den/dec/pt/num", "MC/pr/den/dec/pt/num", "MC/de/den/dec/pt/num", - "MC/tr/den/dec/pt/num", "MC/he/den/dec/pt/num", "MC/al/den/dec/pt/num", - "MC/all/den/dec/pt/num"}; + "MC/el/neg/dec/pt/num", "MC/mu/neg/dec/pt/num", "MC/pi/neg/dec/pt/num", + "MC/ka/neg/dec/pt/num", "MC/pr/neg/dec/pt/num", "MC/de/neg/dec/pt/num", + "MC/tr/neg/dec/pt/num", "MC/he/neg/dec/pt/num", "MC/al/neg/dec/pt/num", + "MC/all/neg/dec/pt/num"}; static constexpr std::string_view hPtDecNumTrk[nHistograms] = {"MC/el/sum/dec/pt/numtrk", "MC/mu/sum/dec/pt/numtrk", "MC/pi/sum/dec/pt/numtrk", "MC/ka/sum/dec/pt/numtrk", "MC/pr/sum/dec/pt/numtrk", "MC/de/sum/dec/pt/numtrk", "MC/tr/sum/dec/pt/numtrk", "MC/he/sum/dec/pt/numtrk", "MC/al/sum/dec/pt/numtrk", @@ -240,10 +240,10 @@ struct QaEfficiency { "MC/ka/pos/mat/pt/num", "MC/pr/pos/mat/pt/num", "MC/de/pos/mat/pt/num", "MC/tr/pos/mat/pt/num", "MC/he/pos/mat/pt/num", "MC/al/pos/mat/pt/num", "MC/all/pos/mat/pt/num", - "MC/el/den/mat/pt/num", "MC/mu/den/mat/pt/num", "MC/pi/den/mat/pt/num", - "MC/ka/den/mat/pt/num", "MC/pr/den/mat/pt/num", "MC/de/den/mat/pt/num", - "MC/tr/den/mat/pt/num", "MC/he/den/mat/pt/num", "MC/al/den/mat/pt/num", - "MC/all/den/mat/pt/num"}; + "MC/el/neg/mat/pt/num", "MC/mu/neg/mat/pt/num", "MC/pi/neg/mat/pt/num", + "MC/ka/neg/mat/pt/num", "MC/pr/neg/mat/pt/num", "MC/de/neg/mat/pt/num", + "MC/tr/neg/mat/pt/num", "MC/he/neg/mat/pt/num", "MC/al/neg/mat/pt/num", + "MC/all/neg/mat/pt/num"}; static constexpr std::string_view hPtMatNumTrk[nHistograms] = {"MC/el/sum/mat/pt/numtrk", "MC/mu/sum/mat/pt/numtrk", "MC/pi/sum/mat/pt/numtrk", "MC/ka/sum/mat/pt/numtrk", "MC/pr/sum/mat/pt/numtrk", "MC/de/sum/mat/pt/numtrk", "MC/tr/sum/mat/pt/numtrk", "MC/he/sum/mat/pt/numtrk", "MC/al/sum/mat/pt/numtrk", @@ -1189,11 +1189,11 @@ struct QaEfficiency { if (!isTrackSelected(track)) { // Check general cuts continue; } - histos.fill(HIST("MC/trackSelection"), 11); + histos.fill(HIST("MC/trackSelection"), 9); if (!track.has_collision()) { continue; } - histos.fill(HIST("MC/trackSelection"), 12); + histos.fill(HIST("MC/trackSelection"), 10); // Filling variable histograms histos.fill(HIST("MC/trackLength"), track.length()); if (doEl) { diff --git a/DPG/Tasks/qaEventTrackLite.cxx b/DPG/Tasks/qaEventTrackLite.cxx index 48423742a8f..b08edf431c4 100644 --- a/DPG/Tasks/qaEventTrackLite.cxx +++ b/DPG/Tasks/qaEventTrackLite.cxx @@ -114,7 +114,9 @@ struct qaEventTrackLite { Configurable dcaXYmaxSel3{"dcaXYMaxSel3", 999., "Max dca XY sel3"}; // MC selections - Configurable pdgCodeSel{"pdgCodeSel", 2, "pdgCode based particle selection, 1 defines pi,K,p,mu,e, 2 all final-state charged particles including light (hyper)nuclei"}; + Configurable pdgCodeSel{"pdgCodeSel", 0, "pdgCode based particle selection. Provide a PDG code required for particles to have. To be used in combo with pdgCodeSelMode"}; + Configurable pdgCodeSelMode{"pdgCodeSelMode", 2, "multiple pdgCode based particle selection. `1` accepts pi,K,p,mu,e, `2` accepts all final-state charged particles including light (hyper)nuclei"}; + Configurable checkPdgAtReco{"checkPdgAtReco", false, "check pdg code also at reco levo for data-like reference"}; // TPC dEdx splines @@ -578,18 +580,38 @@ struct qaEventTrackLite { return true; } - bool isPdgSelected(const Int_t pdgcode) + bool isPdgSelected(const int pdgcode) { // mimics selection of charged particles or id particles - Int_t abspdgcode = TMath::Abs(pdgcode); - if (abspdgcode == pdgCodeSel) + + if (pdgcode == pdgCodeSel) { // Check that the pdg code is exactly what was asked return true; - if (pdgCodeSel == 1 || pdgCodeSel == 2) { - if (abspdgcode == 211 || abspdgcode == 321 || abspdgcode == 2212 || abspdgcode == 11 || abspdgcode == 13) - return true; - if (pdgCodeSel == 2) { - if (abspdgcode == 3222 || abspdgcode == 3112 || abspdgcode == 3312 || abspdgcode == 3334 || abspdgcode == 1000010020 || abspdgcode == 1000010030 || abspdgcode == 1000020030 || abspdgcode == 1000020040 || abspdgcode == 1010010030 || abspdgcode == 1010020040) + } + const int abspdgcode = abs(pdgcode); + if (pdgCodeSelMode == 1 || pdgCodeSelMode == 2) { + switch (abspdgcode) { + case 11: // electron + case 13: // muon + case 211: // pion + case 321: // kaon + case 2212: // proton return true; } + + if (pdgCodeSelMode == 2) { + switch (abspdgcode) { + case 3222: // Σ+ + case 3112: // Σ− + case 3312: // Ξ− + case 3334: // Ω− + case 1000010020: // deuteron + case 1000010030: // triton + case 1000020030: // helium3 + case 1000020040: // helium4 + case 1010010030: // hyper triton + case 1010020040: // hyper helium4 + return true; + } + } } return false; } diff --git a/DPG/Tasks/qaPIDTOF.h b/DPG/Tasks/qaPIDTOF.h index 30518f9ce18..341e3b830eb 100644 --- a/DPG/Tasks/qaPIDTOF.h +++ b/DPG/Tasks/qaPIDTOF.h @@ -67,7 +67,7 @@ struct tofPidQa { Configurable nBinsNSigma{"nBinsNSigma", 200, "Number of bins for the NSigma"}; Configurable minNSigma{"minNSigma", -10.f, "Minimum NSigma in range"}; Configurable maxNSigma{"maxNSigma", 10.f, "Maximum NSigma in range"}; - Configurable applyEvSel{"applyEvSel", 2, "Flag to apply rapidity cut: 0 -> no event selection, 1 -> Run 2 event selection, 2 -> Run 3 event selection"}; + Configurable applyEvSel{"applyEvSel", 2, "Flag to apply event selection cut: 0 -> no event selection, 1 -> Run 2 event selection, 2 -> Run 3 event selection"}; Configurable applyTrackCut{"applyTrackCut", false, "Flag to apply standard track cuts"}; Configurable applyRapidityCut{"applyRapidityCut", false, "Flag to apply rapidity cut"}; Configurable enableEvTimeSplitting{"enableEvTimeSplitting", false, "Flag to enable histograms splitting depending on the Event Time used"}; @@ -482,6 +482,8 @@ struct tofPidBetaQa { Configurable nBinsBeta{"nBinsBeta", 4000, "Number of bins for the beta"}; Configurable minBeta{"minBeta", 0, "Minimum beta in range"}; Configurable maxBeta{"maxBeta", 2.f, "Maximum beta in range"}; + Configurable applyEvSel{"applyEvSel", 2, "Flag to apply event selection cut: 0 -> no event selection, 1 -> Run 2 event selection, 2 -> Run 3 event selection"}; + Configurable applyTrackCut{"applyTrackCut", false, "Flag to apply standard track cuts"}; void init(o2::framework::InitContext&) { @@ -502,11 +504,24 @@ struct tofPidBetaQa { // Event properties histos.add("event/tofsignal", "", HistType::kTH2F, {pAxis, tofAxis}); histos.add("event/tofbeta", "", HistType::kTH2F, {pAxis, betaAxis}); - histos.add("event/tofbetaEvTimeTOF", "", HistType::kTH2F, {pAxis, betaAxis}); + histos.add("event/tofbetaEvTimeTOF", "Ev. Time TOF", HistType::kTH2F, {pAxis, betaAxis}); + histos.add("event/tofbetaEvTimeTOFOnly", "Ev. Time TOF Only", HistType::kTH2F, {pAxis, betaAxis}); + histos.add("event/tofbetaEvTimeT0AC", "Ev. Time T0AC", HistType::kTH2F, {pAxis, betaAxis}); + histos.add("event/tofbetaEvTimeT0ACOnly", "Ev. Time T0AC Only", HistType::kTH2F, {pAxis, betaAxis}); histos.add("event/eta", "", HistType::kTH1F, {etaAxis}); histos.add("event/length", "", HistType::kTH1F, {lAxis}); histos.add("event/pt", "", HistType::kTH1F, {ptAxis}); histos.add("event/p", "", HistType::kTH1F, {pAxis}); + auto h = histos.add("event/evsel", "", kTH1F, {{10, 0.5, 10.5, "Ev. Sel."}}); + h->GetXaxis()->SetBinLabel(1, "Events read"); + h->GetXaxis()->SetBinLabel(2, "Passed ev. sel."); + h->GetXaxis()->SetBinLabel(3, "Passed mult."); + h->GetXaxis()->SetBinLabel(4, "Passed vtx Z"); + + h = histos.add("event/trackselection", "", kTH1F, {{10, 0.5, 10.5, "Selection passed"}}); + h->GetXaxis()->SetBinLabel(1, "Tracks read"); + h->GetXaxis()->SetBinLabel(2, "hasTOF"); + h->GetXaxis()->SetBinLabel(3, "isGlobalTrack"); } template @@ -516,20 +531,62 @@ struct tofPidBetaQa { histos.fill(HIST(hexpected_diff[i]), t.p(), exp_diff); histos.fill(HIST(hnsigma[i]), t.p(), nsigma); } - void process(soa::Join const& tracks, - aod::Collisions const&) + + using CollisionCandidate = soa::Join::iterator; + void process(CollisionCandidate const& collision, + soa::Join const& tracks) { - for (auto const& track : tracks) { + histos.fill(HIST("event/evsel"), 1); + if (applyEvSel == 1) { + if (!collision.sel7()) { + return; + } + } else if (applyEvSel == 2) { + if (!collision.sel8()) { + return; + } + } + + histos.fill(HIST("event/evsel"), 2); + + // Computing Multiplicity first + float ntracks = 0; + for (auto t : tracks) { + if (applyTrackCut && !t.isGlobalTrack()) { + continue; + } + ntracks += 1; + } + histos.fill(HIST("event/evsel"), 3); + if (abs(collision.posZ()) > 10.f) { + return; + } + + histos.fill(HIST("event/evsel"), 4); + + for (auto const& track : tracks) { + histos.fill(HIST("event/trackselection"), 1.f); if (!track.hasTOF()) { // Skipping tracks without TOF continue; } + histos.fill(HIST("event/trackselection"), 2.f); if (!track.isGlobalTrack()) { continue; } + histos.fill(HIST("event/trackselection"), 3.f); if (track.isEvTimeTOF()) { histos.fill(HIST("event/tofbetaEvTimeTOF"), track.p(), track.beta()); } + if (track.isEvTimeTOF() && !track.isEvTimeT0AC()) { + histos.fill(HIST("event/tofbetaEvTimeTOFOnly"), track.p(), track.beta()); + } + if (track.isEvTimeT0AC()) { + histos.fill(HIST("event/tofbetaEvTimeT0AC"), track.p(), track.beta()); + } + if (track.isEvTimeT0AC() && !track.isEvTimeTOF()) { + histos.fill(HIST("event/tofbetaEvTimeT0ACOnly"), track.p(), track.beta()); + } histos.fill(HIST("event/tofbeta"), track.p(), track.beta()); histos.fill(HIST("event/length"), track.length()); histos.fill(HIST("event/eta"), track.eta()); diff --git a/DPG/Tasks/qaPIDTPC.h b/DPG/Tasks/qaPIDTPC.h index ee6b7ef0dc9..05205bd9992 100644 --- a/DPG/Tasks/qaPIDTPC.h +++ b/DPG/Tasks/qaPIDTPC.h @@ -36,6 +36,20 @@ struct tpcPidQa { static constexpr std::string_view hexpected_diff[Np] = {"expected_diff/El", "expected_diff/Mu", "expected_diff/Pi", "expected_diff/Ka", "expected_diff/Pr", "expected_diff/De", "expected_diff/Tr", "expected_diff/He", "expected_diff/Al"}; + static constexpr std::string_view hexpected_diffptpos[Np] = {"expected_diffptpos/El", "expected_diffptpos/Mu", "expected_diffptpos/Pi", + "expected_diffptpos/Ka", "expected_diffptpos/Pr", "expected_diffptpos/De", + "expected_diffptpos/Tr", "expected_diffptpos/He", "expected_diffptpos/Al"}; + static constexpr std::string_view hexpected_diffptneg[Np] = {"expected_diffptneg/El", "expected_diffptneg/Mu", "expected_diffptneg/Pi", + "expected_diffptneg/Ka", "expected_diffptneg/Pr", "expected_diffptneg/De", + "expected_diffptneg/Tr", "expected_diffptneg/He", "expected_diffptneg/Al"}; + // With TOF + static constexpr std::string_view hexpectedwtof[Np] = {"expectedwtof/El", "expectedwtof/Mu", "expectedwtof/Pi", + "expectedwtof/Ka", "expectedwtof/Pr", "expectedwtof/De", + "expectedwtof/Tr", "expectedwtof/He", "expectedwtof/Al"}; + static constexpr std::string_view hexpected_diffwtof[Np] = {"expected_diffwtof/El", "expected_diffwtof/Mu", "expected_diffwtof/Pi", + "expected_diffwtof/Ka", "expected_diffwtof/Pr", "expected_diffwtof/De", + "expected_diffwtof/Tr", "expected_diffwtof/He", "expected_diffwtof/Al"}; + static constexpr std::string_view hexpsigma[Np] = {"expsigma/El", "expsigma/Mu", "expsigma/Pi", "expsigma/Ka", "expsigma/Pr", "expsigma/De", "expsigma/Tr", "expsigma/He", "expsigma/Al"}; @@ -51,9 +65,24 @@ struct tpcPidQa { static constexpr std::string_view hnsigmanegpt[Np] = {"nsigmanegpt/El", "nsigmanegpt/Mu", "nsigmanegpt/Pi", "nsigmanegpt/Ka", "nsigmanegpt/Pr", "nsigmanegpt/De", "nsigmanegpt/Tr", "nsigmanegpt/He", "nsigmanegpt/Al"}; + // With TOF + static constexpr std::string_view hexpsigmawtof[Np] = {"expsigmawtof/El", "expsigmawtof/Mu", "expsigmawtof/Pi", + "expsigmawtof/Ka", "expsigmawtof/Pr", "expsigmawtof/De", + "expsigmawtof/Tr", "expsigmawtof/He", "expsigmawtof/Al"}; + static constexpr std::string_view hnsigmawtof[Np] = {"nsigmawtof/El", "nsigmawtof/Mu", "nsigmawtof/Pi", + "nsigmawtof/Ka", "nsigmawtof/Pr", "nsigmawtof/De", + "nsigmawtof/Tr", "nsigmawtof/He", "nsigmawtof/Al"}; + static constexpr std::string_view hnsigmaptwtof[Np] = {"nsigmaptwtof/El", "nsigmaptwtof/Mu", "nsigmaptwtof/Pi", + "nsigmaptwtof/Ka", "nsigmaptwtof/Pr", "nsigmaptwtof/De", + "nsigmaptwtof/Tr", "nsigmaptwtof/He", "nsigmaptwtof/Al"}; + static constexpr std::string_view hsignal[Np] = {"signal/El", "signal/Mu", "signal/Pi", "signal/Ka", "signal/Pr", "signal/De", "signal/Tr", "signal/He", "signal/Al"}; + // With TOF + static constexpr std::string_view hsignalwtof[Np] = {"signalwtof/El", "signalwtof/Mu", "signalwtof/Pi", + "signalwtof/Ka", "signalwtof/Pr", "signalwtof/De", + "signalwtof/Tr", "signalwtof/He", "signalwtof/Al"}; HistogramRegistry histos{"Histos", {}, OutputObjHandlingPolicy::AnalysisObject}; @@ -70,7 +99,7 @@ struct tpcPidQa { Configurable nBinsNSigma{"nBinsNSigma", 200, "Number of bins for the NSigma"}; Configurable minNSigma{"minNSigma", -10.f, "Minimum NSigma in range"}; Configurable maxNSigma{"maxNSigma", 10.f, "Maximum NSigma in range"}; - Configurable applyEvSel{"applyEvSel", 2, "Flag to apply rapidity cut: 0 -> no event selection, 1 -> Run 2 event selection, 2 -> Run 3 event selection"}; + Configurable applyEvSel{"applyEvSel", 2, "Flag to apply event selection cut: 0 -> no event selection, 1 -> Run 2 event selection, 2 -> Run 3 event selection"}; Configurable applyTrackCut{"applyTrackCut", false, "Flag to apply standard track cuts"}; Configurable applyRapidityCut{"applyRapidityCut", false, "Flag to apply rapidity cut"}; @@ -105,6 +134,8 @@ struct tpcPidQa { // Signal - Expected signal const AxisSpec deltaAxis{nBinsDelta, minDelta, maxDelta, Form("d#it{E}/d#it{x} - d#it{E}/d#it{x}(%s)", pT[id])}; histos.add(hexpected_diff[id].data(), "", kTH2F, {pAxis, deltaAxis}); + histos.add(hexpected_diffptpos[id].data(), "Positive", kTH2F, {pAxis, deltaAxis}); + histos.add(hexpected_diffptneg[id].data(), "Negative", kTH2F, {pAxis, deltaAxis}); // Exp Sigma const AxisSpec expSigmaAxis{nBinsExpSigma, minExpSigma, maxExpSigma, Form("Exp_{#sigma}^{TPC}(%s)", pT[id])}; @@ -132,13 +163,14 @@ struct tpcPidQa { const AxisSpec phiAxis{100, 0, TMath::TwoPi(), "#it{#phi}"}; const AxisSpec lAxis{100, 0, 500, "Track length (cm)"}; const AxisSpec pAxisPosNeg{nBinsP, -maxP, maxP, "Signed #it{p} (GeV/#it{c})"}; + const AxisSpec ptAxisPosNeg{nBinsP, -maxP, maxP, "Signed #it{p}_{T} (GeV/#it{c})"}; AxisSpec ptAxis{nBinsP, minP, maxP, "#it{p}_{T} (GeV/#it{c})"}; AxisSpec pAxis{nBinsP, minP, maxP, "#it{p} (GeV/#it{c})"}; if (logAxis) { ptAxis.makeLogaritmic(); pAxis.makeLogaritmic(); } - const AxisSpec dedxAxis{1000, 0, 1000, "d#it{E}/d#it{x} A.U."}; + const AxisSpec dedxAxis{5000, 0, 5000, "d#it{E}/d#it{x} A.U."}; // Event properties auto h = histos.add("event/evsel", "", kTH1F, {{10, 0.5, 10.5, "Ev. Sel."}}); @@ -161,6 +193,8 @@ struct tpcPidQa { histos.add("event/trackmultiplicity", "", kTH1F, {multAxis}); histos.add("event/tpcsignal", "", kTH2F, {pAxis, dedxAxis}); histos.add("event/signedtpcsignal", "", kTH2F, {pAxisPosNeg, dedxAxis}); + histos.add("event/tpcsignalvspt", "", kTH2F, {ptAxis, dedxAxis}); + histos.add("event/signedtpcsignalvspt", "", kTH2F, {ptAxisPosNeg, dedxAxis}); histos.add("event/eta", "", kTH1F, {etaAxis}); histos.add("event/phi", "", kTH1F, {phiAxis}); histos.add("event/etaphi", "", kTH2F, {etaAxis, phiAxis}); @@ -237,6 +271,8 @@ struct tpcPidQa { histos.fill(HIST("event/particlehypo"), track.pidForTracking()); histos.fill(HIST("event/tpcsignal"), track.tpcInnerParam(), track.tpcSignal()); histos.fill(HIST("event/signedtpcsignal"), track.tpcInnerParam() * track.sign(), track.tpcSignal()); + histos.fill(HIST("event/tpcsignalvspt"), track.pt(), track.tpcSignal()); + histos.fill(HIST("event/signedtpcsignalvspt"), track.pt() * track.sign(), track.tpcSignal()); histos.fill(HIST("event/eta"), track.eta()); histos.fill(HIST("event/phi"), track.phi()); histos.fill(HIST("event/etaphi"), track.eta(), track.phi()); @@ -291,21 +327,26 @@ struct tpcPidQa { // Fill histograms histos.fill(HIST(hexpected[id]), t.tpcInnerParam(), t.tpcSignal() - diff); histos.fill(HIST(hexpected_diff[id]), t.tpcInnerParam(), diff); + if (t.sign() > 0) { + histos.fill(HIST(hexpected_diffptpos[id]), t.pt(), diff); + } else { + histos.fill(HIST(hexpected_diffptneg[id]), t.pt(), diff); + } histos.fill(HIST(hexpsigma[id]), t.tpcInnerParam(), o2::aod::pidutils::tpcExpSigma(t)); if constexpr (fillWithTOFHistograms) { if (std::abs(o2::aod::pidutils::tofNSigma(t)) < 3.f) { - histos.fill(HIST(hexpected[id]), t.tpcInnerParam(), t.tpcSignal() - diff); - histos.fill(HIST(hexpected_diff[id]), t.tpcInnerParam(), diff); - histos.fill(HIST(hexpsigma[id]), t.p(), o2::aod::pidutils::tpcExpSigma(t)); + histos.fill(HIST(hexpectedwtof[id]), t.tpcInnerParam(), t.tpcSignal() - diff); + histos.fill(HIST(hexpected_diffwtof[id]), t.tpcInnerParam(), diff); + histos.fill(HIST(hexpsigmawtof[id]), t.p(), o2::aod::pidutils::tpcExpSigma(t)); } } } if constexpr (fillWithTOFHistograms) { const auto& nsigmatof = o2::aod::pidutils::tofNSigma(t); if (std::abs(nsigmatof) < 3.f) { - histos.fill(HIST(hnsigma[id]), t.p(), nsigma); - histos.fill(HIST(hnsigmapt[id]), t.pt(), nsigma); - histos.fill(HIST(hsignal[id]), t.tpcInnerParam(), t.tpcSignal()); + histos.fill(HIST(hnsigmawtof[id]), t.p(), nsigma); + histos.fill(HIST(hnsigmaptwtof[id]), t.pt(), nsigma); + histos.fill(HIST(hsignalwtof[id]), t.tpcInnerParam(), t.tpcSignal()); // histos.fill(HIST("event/signedtpcsignal"), t.tpcInnerParam() * t.sign(), t.tpcSignal()); } } From c75ea5d9c1657aa185c3cd2f95648fe2470d0d10 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=B2=20Jacazio?= Date: Fri, 22 Jul 2022 16:20:57 +0200 Subject: [PATCH 25/31] Add vs Zvtx histograms (#1045) --- DPG/Tasks/qaEventTrack.h | 20 +++++++++++-- DPG/Tasks/qaEventTrackLite.cxx | 52 +++++++++++++++++++++++----------- 2 files changed, 53 insertions(+), 19 deletions(-) diff --git a/DPG/Tasks/qaEventTrack.h b/DPG/Tasks/qaEventTrack.h index 19956866797..b34b7d40c3b 100644 --- a/DPG/Tasks/qaEventTrack.h +++ b/DPG/Tasks/qaEventTrack.h @@ -79,16 +79,32 @@ DECLARE_SOA_COLUMN(PtMC, ptMC, float); //! Pt MC DECLARE_SOA_COLUMN(EtaMC, etaMC, float); //! Eta MC DECLARE_SOA_COLUMN(PhiMC, phiMC, float); //! Phi MC DECLARE_SOA_COLUMN(ProductionMode, productionMode, int); //! ProductionMode i.e. non matched (-1), physical primary (0), weak decay product (1) or material (2) +DECLARE_SOA_DYNAMIC_COLUMN(IsNonMatched, isNonMatched, //! True if particle is considered a non matched particle + [](int mode) -> bool { return mode == -1; }); +DECLARE_SOA_DYNAMIC_COLUMN(IsPhysicalPrimary, isPhysicalPrimary, //! True if particle is considered a physical primary according to the ALICE definition + [](int mode) -> bool { return mode == 0; }); +DECLARE_SOA_DYNAMIC_COLUMN(IsFromWeakDecay, isFromWeakDecay, //! True if particle is considered from a weak decay + [](int mode) -> bool { return mode == 1; }); +DECLARE_SOA_DYNAMIC_COLUMN(IsFromMaterial, isFromMaterial, //! True if particle is considered from a weak decay + [](int mode) -> bool { return mode == 2; }); } // namespace dpgparticles DECLARE_SOA_TABLE(DPGRecoParticles, "AOD", "DPGRecoPart", //! Table of the DPG reconstructed particles dpgparticles::PtMC, dpgparticles::EtaMC, dpgparticles::PhiMC, - mcparticle::PdgCode, dpgparticles::ProductionMode); + mcparticle::PdgCode, dpgparticles::ProductionMode, + dpgparticles::IsNonMatched, + dpgparticles::IsPhysicalPrimary, + dpgparticles::IsFromWeakDecay, + dpgparticles::IsFromMaterial); -DECLARE_SOA_TABLE(DPGNonRecoParticles, "AOD", "DPGNonRecoPart", //! Table of the DPG particles +DECLARE_SOA_TABLE(DPGNonRecoParticles, "AOD", "DPGNonRecoPart", //! Table of the DPG non reconstructed particles dpgtrack::DPGCollisionId, dpgparticles::PtMC, dpgparticles::EtaMC, dpgparticles::PhiMC, mcparticle::PdgCode, dpgparticles::ProductionMode, + dpgparticles::IsNonMatched, + dpgparticles::IsPhysicalPrimary, + dpgparticles::IsFromWeakDecay, + dpgparticles::IsFromMaterial, mcparticle::Vx, mcparticle::Vy, mcparticle::Vz); } // namespace o2::aod diff --git a/DPG/Tasks/qaEventTrackLite.cxx b/DPG/Tasks/qaEventTrackLite.cxx index b08edf431c4..d9446ca5fab 100644 --- a/DPG/Tasks/qaEventTrackLite.cxx +++ b/DPG/Tasks/qaEventTrackLite.cxx @@ -48,6 +48,7 @@ struct qaEventTrackLite { ConfigurableAxis binsImpPar{"binsImpPar", {200, -0.15, 0.15}, "Impact parameter binning (cm)"}; ConfigurableAxis binsEta{"binsEta", {200, -2., 2.}, "Eta binning"}; ConfigurableAxis binsPhi{"binsPhi", {180, 0., 2 * M_PI}, "Phi binning"}; + ConfigurableAxis binsVtxZ{"binsVtxZ", {100, -20., 20.}, "Vtx Z binning"}; HistogramRegistry histos; @@ -189,14 +190,15 @@ struct qaEventTrackLite { const AxisSpec axis1overPt{bins1overPt, "1/#it{p}_{T} (GeV/c)^{-1}"}; const AxisSpec axisEta{binsEta, "#it{#eta}"}; const AxisSpec axisPhi{binsPhi, "#it{#phi} (rad)"}; + const AxisSpec axisVtxZ{binsVtxZ, "Vertex Z (cm)"}; // TPC dEdx splines betheBlock.setUpBetheBlockAleph(tpcSplinesPeriod); // kine histograms - histos.add("Tracks/VertexPositionZ", "", kTH1D, {{100, -20.f, 20.f, "Vertex Z (cm)"}}); - histos.add("Tracks/VertexPositionZvsEta", "", kTH2D, {axisEta, {100, -20.f, 20.f, "Vertex Z (cm)"}}); - histos.add("Tracks/VertexPositionZvsEtaHasITS", "", kTH2D, {axisEta, {100, -20.f, 20.f, "Vertex Z (cm)"}}); + histos.add("Tracks/VertexPositionZ", "", kTH1D, {axisVtxZ}); + histos.add("Tracks/VertexPositionZvsEta", "", kTH2D, {axisEta, axisVtxZ}); + histos.add("Tracks/VertexPositionZvsEtaHasITS", "", kTH2D, {axisEta, axisVtxZ}); histos.add("Tracks/Kine/pt", "#it{p}_{T}", kTH1D, {axisPt}); histos.add("Tracks/Kine/eta", "#eta", kTH1D, {axisEta}); histos.add("Tracks/Kine/phi", "#phi", kTH1D, {axisPhi}); @@ -283,11 +285,17 @@ struct qaEventTrackLite { histos.add("Particles/Kine/pt", "Particle #it{p}_{T}", kTH1D, {axisPt}); histos.add("Particles/Kine/eta", "Particle #eta", kTH1D, {axisEta}); histos.add("Particles/Kine/phi", "Particle #phi", kTH1D, {axisPhi}); - histos.add("Particle/selPtEtaPhiMCGenPrimary", "pt eta phi map MC gen Primary; pt,eta,phi", kTH3D, {axisPt, {50, -1.2, 1.2, "#eta"}, {30, 0., 2 * M_PI, "#varphi"}}); - histos.add("Particle/selPtEtaPhiMCRecoNoSelPrimary", "pt eta phi map MC gen Primary sel0; pt,eta,phi", kTH3D, {axisPt, {50, -1.2, 1.2, "#eta"}, {30, 0., 2 * M_PI, "#varphi"}}); - histos.add("Particle/selPtEtaPhiMCRecoSel1Primary", "pt eta phi map MC gen Primary sel1; pt,eta,phi", kTH3D, {axisPt, {50, -1.2, 1.2, "#eta"}, {30, 0., 2 * M_PI, "#varphi"}}); - histos.add("Particle/selPtEtaPhiMCRecoSel2Primary", "pt eta phi map MC gen Primary sel2; pt,eta,phi", kTH3D, {axisPt, {50, -1.2, 1.2, "#eta"}, {30, 0., 2 * M_PI, "#varphi"}}); - histos.add("Particle/selPtEtaPhiMCRecoSel3Primary", "pt eta phi map MC gen Primary sel3; pt,eta,phi", kTH3D, {axisPt, {50, -1.2, 1.2, "#eta"}, {30, 0., 2 * M_PI, "#varphi"}}); + histos.add("Particle/selPtEtaPhiMCGenPrimary", "pt eta phi map MC gen Primary", kTH3D, {axisPt, {50, -1.2, 1.2, "#eta"}, {30, 0., 2 * M_PI, "#varphi"}}); + histos.add("Particle/selPtEtaPhiMCRecoNoSelPrimary", "pt eta phi map MC reco Primary sel0", kTH3D, {axisPt, {50, -1.2, 1.2, "#eta"}, {30, 0., 2 * M_PI, "#varphi"}}); + histos.add("Particle/selPtEtaPhiMCRecoSel1Primary", "pt eta phi map MC reco Primary sel1", kTH3D, {axisPt, {50, -1.2, 1.2, "#eta"}, {30, 0., 2 * M_PI, "#varphi"}}); + histos.add("Particle/selPtEtaPhiMCRecoSel2Primary", "pt eta phi map MC reco Primary sel2", kTH3D, {axisPt, {50, -1.2, 1.2, "#eta"}, {30, 0., 2 * M_PI, "#varphi"}}); + histos.add("Particle/selPtEtaPhiMCRecoSel3Primary", "pt eta phi map MC reco Primary sel3", kTH3D, {axisPt, {50, -1.2, 1.2, "#eta"}, {30, 0., 2 * M_PI, "#varphi"}}); + + histos.add("Particle/selPtEtaVtxzMCGenPrimary", "pt eta VtxZ map MC gen Primary", kTH3F, {axisPt, axisEta, axisVtxZ}); + histos.add("Particle/selPtEtaVtxzMCRecoNoSelPrimary", "pt eta VtxZ map MC reco Primary sel0", kTH3F, {axisPt, axisEta, axisVtxZ}); + histos.add("Particle/selPtEtaVtxzMCRecoSel1Primary", "pt eta VtxZ map MC reco Primary sel1", kTH3F, {axisPt, axisEta, axisVtxZ}); + histos.add("Particle/selPtEtaVtxzMCRecoSel2Primary", "pt eta VtxZ map MC reco Primary sel2", kTH3F, {axisPt, axisEta, axisVtxZ}); + histos.add("Particle/selPtEtaVtxzMCRecoSel3Primary", "pt eta VtxZ map MC reco Primary sel3", kTH3F, {axisPt, axisEta, axisVtxZ}); histos.add("Tracks/resoPhivsPtvsEta", "#varphi(reco)-#varphi(gen);", kTH3D, {axisPt, axisEta, {180, -M_PI, M_PI, "#varphi(reco)-#varphi(gen)"}}); histos.add("Tracks/phiRecovsphiGen", "#varphi(reco) vs. #varphi(gen);", kTH2D, {axisPhi, axisPhi}); histos.get(HIST("Tracks/phiRecovsphiGen"))->GetXaxis()->SetTitle("#varphi(reco)"); @@ -316,16 +324,17 @@ struct qaEventTrackLite { // TOF Filter tofChi = o2::aod::track::tofChi2 > chi2TofMin; Filter length = o2::aod::track::length > lengthMin; - template void fillHistograms(trackType const& track) { - - if (TMath::Abs(track.dpgCollision().posZ()) > vtxZMax) + const float vtxZ = track.dpgCollision().posZ(); + if (TMath::Abs(vtxZ) > vtxZMax) { return; + } if constexpr (isMC) { - if (track.productionMode() == 0 && isPdgSelected(track.pdgCode())) { + if (track.isPhysicalPrimary() && isPdgSelected(track.pdgCode())) { histos.fill(HIST("Particle/selPtEtaPhiMCGenPrimary"), track.ptMC(), track.etaMC(), track.phiMC()); + histos.fill(HIST("Particle/selPtEtaVtxzMCGenPrimary"), track.ptMC(), track.etaMC(), vtxZ); } } // temporary additional selections @@ -338,18 +347,22 @@ struct qaEventTrackLite { Bool_t isPdgOk = true; if constexpr (isMC) { isPdgOk = isPdgSelected(track.pdgCode()); - if (track.productionMode() == 0 && isPdgOk) { + if (track.isPhysicalPrimary() && isPdgOk) { histos.get(HIST("Particles/PDGs"))->Fill(Form("%i", track.pdgCode()), 1); histos.fill(HIST("Particle/selPtEtaPhiMCRecoNoSelPrimary"), track.ptMC(), track.etaMC(), track.phiMC()); + histos.fill(HIST("Particle/selPtEtaVtxzMCRecoNoSelPrimary"), track.ptMC(), track.etaMC(), vtxZ); if (sel1) { histos.fill(HIST("Particle/selPtEtaPhiMCRecoSel1Primary"), track.ptMC(), track.etaMC(), track.phiMC()); + histos.fill(HIST("Particle/selPtEtaVtxzMCRecoSel1Primary"), track.ptMC(), track.etaMC(), vtxZ); } if (sel2) { histos.fill(HIST("Particle/selPtEtaPhiMCRecoSel2Primary"), track.ptMC(), track.etaMC(), track.phiMC()); + histos.fill(HIST("Particle/selPtEtaVtxzMCRecoSel2Primary"), track.ptMC(), track.etaMC(), vtxZ); } if (sel3) { histos.fill(HIST("Particle/selPtEtaPhiMCRecoSel3Primary"), track.ptMC(), track.etaMC(), track.phiMC()); + histos.fill(HIST("Particle/selPtEtaVtxzMCRecoSel3Primary"), track.ptMC(), track.etaMC(), vtxZ); } } @@ -473,22 +486,27 @@ struct qaEventTrackLite { PROCESS_SWITCH(qaEventTrackLite, processDataLite, "process data lite", true); // Process MC - void processMCLite(o2::soa::Filtered> const& tracks, aod::DPGCollisions const&, aod::DPGNonRecoParticles const& particles) + void processMCLite(o2::soa::Filtered> const& tracks, aod::DPGCollisions const&, + aod::DPGNonRecoParticles const& nonRecoParticles) { for (const auto& track : tracks) { fillHistograms(track); } - for (const auto& particle : particles) { - if (TMath::Abs(particle.dpgCollision().posZ()) > vtxZMax) + for (const auto& particle : nonRecoParticles) { + const float vtxZ = particle.dpgCollision().posZ(); + if (TMath::Abs(vtxZ) > vtxZMax) { continue; + } histos.fill(HIST("Particles/Kine/pt"), particle.ptMC()); histos.fill(HIST("Particles/Kine/eta"), particle.etaMC()); histos.fill(HIST("Particles/Kine/phi"), particle.phiMC()); - if (particle.productionMode() == 0 && isPdgSelected(particle.pdgCode())) + if (particle.isPhysicalPrimary() && isPdgSelected(particle.pdgCode())) { histos.fill(HIST("Particle/selPtEtaPhiMCGenPrimary"), particle.ptMC(), particle.etaMC(), particle.phiMC()); + histos.fill(HIST("Particle/selPtEtaVtxzMCGenPrimary"), particle.ptMC(), particle.etaMC(), vtxZ); + } } } PROCESS_SWITCH(qaEventTrackLite, processMCLite, "process MC lite", false); From 1405e1967ee4da007a20a8c1ca74efa51ebfaecc Mon Sep 17 00:00:00 2001 From: Mattia Faggin Date: Fri, 22 Jul 2022 18:34:57 +0200 Subject: [PATCH 26/31] DPG: test correct track-to-collision matching with MC info. (#1047) Co-authored-by: Mattia Faggin --- DPG/Tasks/qaEventTrack.cxx | 73 +++++++++++++++++++++++++++++++++++++- 1 file changed, 72 insertions(+), 1 deletion(-) diff --git a/DPG/Tasks/qaEventTrack.cxx b/DPG/Tasks/qaEventTrack.cxx index 1948ed55d38..0aac0158e18 100644 --- a/DPG/Tasks/qaEventTrack.cxx +++ b/DPG/Tasks/qaEventTrack.cxx @@ -267,6 +267,61 @@ struct qaEventTrack { const auto& tracksUnfilteredColl = tracksUnfiltered.sliceBy(perRecoCollision, collision.globalIndex()); fillRecoHistogramsGroupedTracks(collision, tracksColl, tracksUnfilteredColl); } + + /// check correct track-to-vertex matching exploiting MC info + for (auto& track : tracks) { + histos.fill(HIST("Tracks/TestMCtrackToVtxMatch/ptAllTracks"), track.pt()); + bool has_MCparticle = track.has_mcParticle(); + if (track.collisionId() >= 0) { + /// track associated to a reconstructed collision + histos.fill(HIST("Tracks/TestMCtrackToVtxMatch/ptAllTracksInColl"), track.pt()); + if (has_MCparticle) { + /// the track is not fake + auto particle = track.mcParticle(); + auto collReco = track.collision_as(); + auto collMC = particle.mcCollision(); + auto mcCollID_recoColl = collReco.mcCollisionId(); + auto mcCollID_particle = particle.mcCollisionId(); + bool indexMatchOK = (mcCollID_recoColl == mcCollID_particle); + double pvZdiff = collReco.posZ() - collMC.posZ(); + if (indexMatchOK) { + /// mc collision indices from the two sides match + if (particle.isPhysicalPrimary()) { + histos.fill(HIST("Tracks/TestMCtrackToVtxMatch/ptVsDpvZgoodMatchPhysPrim"), pvZdiff, track.pt()); + } else if (particle.getProcess() == 4) { + histos.fill(HIST("Tracks/TestMCtrackToVtxMatch/ptVsDpvZgoodMatchSecondary"), pvZdiff, track.pt()); + } else { + histos.fill(HIST("Tracks/TestMCtrackToVtxMatch/ptVsDpvZgoodMatchMaterial"), pvZdiff, track.pt()); + } + } else { + /// mc collision indices from the two sides do not match + if (particle.isPhysicalPrimary()) { + histos.fill(HIST("Tracks/TestMCtrackToVtxMatch/ptVsDpvZbadMatchPhysPrim"), pvZdiff, track.pt()); + } else if (particle.getProcess() == 4) { + histos.fill(HIST("Tracks/TestMCtrackToVtxMatch/ptVsDpvZbadMatchSecondary"), pvZdiff, track.pt()); + } else { + histos.fill(HIST("Tracks/TestMCtrackToVtxMatch/ptVsDpvZbadMatchMaterial"), pvZdiff, track.pt()); + } + } + } + + } else { + /// track not associated to any reconstructed collision + histos.fill(HIST("Tracks/TestMCtrackToVtxMatch/ptAllTracksWoColl"), track.pt()); + if (track.has_mcParticle()) { + auto particle = track.mcParticle(); + int prodProcess = -1; + if (particle.isPhysicalPrimary()) { + prodProcess = 0; + } else if (particle.getProcess() == 4) { + prodProcess = 1; + } else { + prodProcess = 2; + } + histos.fill(HIST("Tracks/TestMCtrackToVtxMatch/ptVsOriginUnmatchedwithMCpart"), prodProcess, track.pt()); + } + } + } } PROCESS_SWITCH(qaEventTrack, processMC, "process mc", true); // FIXME: would like to disable this by default and swich on via --processMC but currently this crashes -> ask experts @@ -501,6 +556,22 @@ void qaEventTrack::init(InitContext const&) histos.add("Tracks/KineUnmatchTracks/eta", "#eta", kTH1D, {axisEta}); histos.add("Tracks/KineUnmatchTracks/phi", "#varphi", kTH1D, {axisPhi}); + /// check correct track-to-vertex matching + histos.add("Tracks/TestMCtrackToVtxMatch/ptAllTracks", "all tracks (MC)", kTH1D, {axisPt}); + histos.add("Tracks/TestMCtrackToVtxMatch/ptAllTracksInColl", "all tracks in collision (MC)", kTH1D, {axisPt}); + histos.add("Tracks/TestMCtrackToVtxMatch/ptAllTracksWoColl", "all tracks w/o collision (MC)", kTH1D, {axisPt}); + auto hUnmatched = histos.add("Tracks/TestMCtrackToVtxMatch/ptVsOriginUnmatchedwithMCpart", "tracks with part. not matched to reco. coll. (MC)", kTH2D, {{4, -1.5, 2.5}, axisPt}); + hUnmatched->GetXaxis()->SetBinLabel(hUnmatched->GetXaxis()->FindBin(-1.), "not found"); + hUnmatched->GetXaxis()->SetBinLabel(hUnmatched->GetXaxis()->FindBin(0.), "Phys. prim."); + hUnmatched->GetXaxis()->SetBinLabel(hUnmatched->GetXaxis()->FindBin(1.), "Secondary"); + hUnmatched->GetXaxis()->SetBinLabel(hUnmatched->GetXaxis()->FindBin(2.), "Material"); + histos.add("Tracks/TestMCtrackToVtxMatch/ptVsDpvZgoodMatchPhysPrim", "good track-to-vtx matching phys. prim. (MC)", kTH2D, {{100, -0.1, 0.1, "pvZ(reco coll.) - pvZ(MC coll.)"}, axisPt}); + histos.add("Tracks/TestMCtrackToVtxMatch/ptVsDpvZbadMatchPhysPrim", "bad track-to-vtx matching phys. prim. (MC)", kTH2D, {{100, -0.1, 0.1, "pvZ(reco coll.) - pvZ(MC coll.)"}, axisPt}); + histos.add("Tracks/TestMCtrackToVtxMatch/ptVsDpvZgoodMatchSecondary", "good track-to-vtx matching secondary (MC)", kTH2D, {{100, -0.1, 0.1, "pvZ(reco coll.) - pvZ(MC coll.)"}, axisPt}); + histos.add("Tracks/TestMCtrackToVtxMatch/ptVsDpvZbadMatchSecondary", "bad track-to-vtx matching secondary (MC)", kTH2D, {{100, -0.1, 0.1, "pvZ(reco coll.) - pvZ(MC coll.)"}, axisPt}); + histos.add("Tracks/TestMCtrackToVtxMatch/ptVsDpvZgoodMatchMaterial", "good track-to-vtx matching material (MC)", kTH2D, {{100, -0.1, 0.1, "pvZ(reco coll.) - pvZ(MC coll.)"}, axisPt}); + histos.add("Tracks/TestMCtrackToVtxMatch/ptVsDpvZbadMatchMaterial", "bad track-to-vtx matching material (MC)", kTH2D, {{100, -0.1, 0.1, "pvZ(reco coll.) - pvZ(MC coll.)"}, axisPt}); + // track histograms auto hselAxis = histos.add("Tracks/selection", "trackSelection", kTH1F, {{40, 0.5, 40.5}})->GetXaxis(); hselAxis->SetBinLabel(1, "Tracks read"); @@ -958,4 +1029,4 @@ void qaEventTrack::fillRecoHistogramsGroupedTracks(const C& collision, const T& histos.fill(HIST("Tracks/ITS/hasITSANDhasTPC"), track.pt()); } } -} +} \ No newline at end of file From f378ef9275ad0a8b42e1e831ac5e11c2b725600c Mon Sep 17 00:00:00 2001 From: Jseo <47848181+JinjooSeo@users.noreply.github.com> Date: Sat, 23 Jul 2022 00:15:40 +0200 Subject: [PATCH 27/31] PWGHF: Update Xic task (#1012) --- PWGHF/Tasks/taskXic.cxx | 111 ++++++++++++++++------------------------ 1 file changed, 45 insertions(+), 66 deletions(-) diff --git a/PWGHF/Tasks/taskXic.cxx b/PWGHF/Tasks/taskXic.cxx index c530ea010c2..2695e5cf2a4 100644 --- a/PWGHF/Tasks/taskXic.cxx +++ b/PWGHF/Tasks/taskXic.cxx @@ -15,6 +15,7 @@ /// /// \author Mattia Faggin , University and INFN PADOVA /// \author Anton Alkin , CERN +/// \author Jinjoo Seo , Inha University #include "Framework/AnalysisTask.h" #include "Framework/HistogramRegistry.h" @@ -25,12 +26,7 @@ using namespace o2; using namespace o2::framework; using namespace o2::framework::expressions; using namespace o2::aod::hf_cand_prong3; - -void customize(std::vector& workflowOptions) -{ - ConfigParamSpec optionDoMC{"doMC", VariantType::Bool, true, {"Fill MC histograms."}}; - workflowOptions.push_back(optionDoMC); -} +using namespace o2::analysis::hf_cuts_xic_topkpi; #include "Framework/runDataProcessing.h" @@ -39,7 +35,11 @@ struct HfTaskXic { HistogramRegistry registry{ "registry", { - {"hPtCand", "3-prong candidates;candidate #it{p}_{T} (GeV/#it{c});entries", {HistType::kTH1F, {{100, 0., 10.}}}} /// + {"hPtCand", "3-prong candidates;candidate #it{p}_{T} (GeV/#it{c});entries", {HistType::kTH1F, {{100, 0., 10.}}}}, + {"hPtRecSig", "3-prong candidates (matched);#it{p}_{T}^{rec.} (GeV/#it{c});entries", {HistType::kTH1F, {{100, 0., 10.}}}}, + {"hPtRecBg", "3-prong candidates (unmatched);#it{p}_{T}^{rec.} (GeV/#it{c});entries", {HistType::kTH1F, {{100, 0., 10.}}}}, + {"hPtGen", "MC particles (matched);#it{p}_{T}^{gen.} (GeV/#it{c});entries", {HistType::kTH1F, {{100, 0., 10.}}}}, + {"hPtGenSig", "3-prong candidates (matched);#it{p}_{T}^{gen.} (GeV/#it{c});entries", {HistType::kTH1F, {{100, 0., 10.}}}} /// }}; Configurable d_selectionFlagXic{"d_selectionFlagXic", 1, "Selection Flag for Xic"}; @@ -63,25 +63,53 @@ struct HfTaskXic { registry.add("hPtProng0", "3-prong candidates;prong 0 #it{p}_{T} (GeV/#it{c});;entries", {HistType::kTH2F, {{100, 0., 10.}, {vbins, "#it{p}_{T} (GeV/#it{c})"}}}); registry.add("hPtProng1", "3-prong candidates;prong 1 #it{p}_{T} (GeV/#it{c});;entries", {HistType::kTH2F, {{100, 0., 10.}, {vbins, "#it{p}_{T} (GeV/#it{c})"}}}); registry.add("hPtProng2", "3-prong candidates;prong 2 #it{p}_{T} (GeV/#it{c});;entries", {HistType::kTH2F, {{100, 0., 10.}, {vbins, "#it{p}_{T} (GeV/#it{c})"}}}); + + registry.add("hMassSig", "Invariant mass (matched);m (p K #pi) (GeV/#it{c}^{2});;entries", {HistType::kTH2F, {{500, 1.6, 3.1}, {vbins, "#it{p}_{T} (GeV/#it{c})"}}}); + registry.add("hMassBg", "Invariant mass (unmatched);m (p K #pi) (GeV/#it{c}^{2});;entries", {HistType::kTH2F, {{500, 1.6, 3.1}, {vbins, "#it{p}_{T} (GeV/#it{c})"}}}); + registry.add("hEtaGen", "3-prong candidates;candidate #it{#eta};;entries", {HistType::kTH2F, {{100, -2., 2.}, {vbins, "#it{p}_{T} (GeV/#it{c})"}}}); + + registry.add("hDecLengthRecSig", "3-prong candidates;decay length (cm);;entries", {HistType::kTH2F, {{200, 0., 2.}, {vbins, "#it{p}_{T} (GeV/#it{c})"}}}); + registry.add("hd0Prong0RecSig", "3-prong candidates;prong 0 DCAxy to prim. vertex (cm);;entries", {HistType::kTH2F, {{100, -1., 1.}, {vbins, "#it{p}_{T} (GeV/#it{c})"}}}); + registry.add("hd0Prong1RecSig", "3-prong candidates;prong 1 DCAxy to prim. vertex (cm);;entries", {HistType::kTH2F, {{100, -1., 1.}, {vbins, "#it{p}_{T} (GeV/#it{c})"}}}); + registry.add("hd0Prong2RecSig", "3-prong candidates;prong 1 DCAxy to prim. vertex (cm);;entries", {HistType::kTH2F, {{100, -1., 1.}, {vbins, "#it{p}_{T} (GeV/#it{c})"}}}); + registry.add("hCtRecSig", "3-prong candidates;proper lifetime (#Xi_{c}) * #it{c} (cm);;entries", {HistType::kTH2F, {{120, -20., 100.}, {vbins, "#it{p}_{T} (GeV/#it{c})"}}}); + registry.add("hCPARecSig", "3-prong candidates;cosine of pointing angle;;entries", {HistType::kTH2F, {{110, -1.1, 1.1}, {vbins, "#it{p}_{T} (GeV/#it{c})"}}}); + registry.add("hEtaRecSig", "3-prong candidates;candidate #it{#eta};;entries", {HistType::kTH2F, {{100, -2., 2.}, {vbins, "#it{p}_{T} (GeV/#it{c})"}}}); + registry.add("hPtProng0RecSig", "3-prong candidates;prong 0 #it{p}_{T} (GeV/#it{c});;entries", {HistType::kTH2F, {{100, 0., 10.}, {vbins, "#it{p}_{T} (GeV/#it{c})"}}}); + registry.add("hPtProng1RecSig", "3-prong candidates;prong 1 #it{p}_{T} (GeV/#it{c});;entries", {HistType::kTH2F, {{100, 0., 10.}, {vbins, "#it{p}_{T} (GeV/#it{c})"}}}); + registry.add("hPtProng2RecSig", "3-prong candidates;prong 2 #it{p}_{T} (GeV/#it{c});;entries", {HistType::kTH2F, {{100, 0., 10.}, {vbins, "#it{p}_{T} (GeV/#it{c})"}}}); + + registry.add("hDecLengthRecBg", "3-prong candidates;decay length (cm);;entries", {HistType::kTH2F, {{200, 0., 2.}, {vbins, "#it{p}_{T} (GeV/#it{c})"}}}); + registry.add("hd0Prong0RecBg", "3-prong candidates;prong 0 DCAxy to prim. vertex (cm);;entries", {HistType::kTH2F, {{100, -1., 1.}, {vbins, "#it{p}_{T} (GeV/#it{c})"}}}); + registry.add("hd0Prong1RecBg", "3-prong candidates;prong 1 DCAxy to prim. vertex (cm);;entries", {HistType::kTH2F, {{100, -1., 1.}, {vbins, "#it{p}_{T} (GeV/#it{c})"}}}); + registry.add("hd0Prong2RecBg", "3-prong candidates;prong 1 DCAxy to prim. vertex (cm);;entries", {HistType::kTH2F, {{100, -1., 1.}, {vbins, "#it{p}_{T} (GeV/#it{c})"}}}); + registry.add("hCtRecBg", "3-prong candidates;proper lifetime (#Xi_{c}) * #it{c} (cm);;entries", {HistType::kTH2F, {{120, -20., 100.}, {vbins, "#it{p}_{T} (GeV/#it{c})"}}}); + registry.add("hCPARecBg", "3-prong candidates;cosine of pointing angle;;entries", {HistType::kTH2F, {{110, -1.1, 1.1}, {vbins, "#it{p}_{T} (GeV/#it{c})"}}}); + registry.add("hEtaRecBg", "3-prong candidates;candidate #it{#eta};;entries", {HistType::kTH2F, {{100, -2., 2.}, {vbins, "#it{p}_{T} (GeV/#it{c})"}}}); + registry.add("hPtProng0RecBg", "3-prong candidates;prong 0 #it{p}_{T} (GeV/#it{c});;entries", {HistType::kTH2F, {{100, 0., 10.}, {vbins, "#it{p}_{T} (GeV/#it{c})"}}}); + registry.add("hPtProng1RecBg", "3-prong candidates;prong 1 #it{p}_{T} (GeV/#it{c});;entries", {HistType::kTH2F, {{100, 0., 10.}, {vbins, "#it{p}_{T} (GeV/#it{c})"}}}); + registry.add("hPtProng2RecBg", "3-prong candidates;prong 2 #it{p}_{T} (GeV/#it{c});;entries", {HistType::kTH2F, {{100, 0., 10.}, {vbins, "#it{p}_{T} (GeV/#it{c})"}}}); } - Filter filterSelectCandidates = (aod::hf_selcandidate_xic::isSelXicToPKPi >= d_selectionFlagXic || aod::hf_selcandidate_xic::isSelXicToPiKP >= d_selectionFlagXic); + Partition> selectedXicCandidates = aod::hf_selcandidate_xic::isSelXicToPKPi >= d_selectionFlagXic || aod::hf_selcandidate_xic::isSelXicToPiKP >= d_selectionFlagXic; - void process(soa::Filtered> const& candidates) + void process(soa::Join const& candidates) { - for (auto& candidate : candidates) { + for (auto& candidate : selectedXicCandidates) { if (!(candidate.hfflag() & 1 << DecayType::XicToPKPi)) { continue; } if (cutYCandMax >= 0. && std::abs(YXic(candidate)) > cutYCandMax) { continue; } + if (candidate.isSelXicToPKPi() >= d_selectionFlagXic) { registry.fill(HIST("hMass"), InvMassXicToPKPi(candidate), candidate.pt()); } if (candidate.isSelXicToPiKP() >= d_selectionFlagXic) { registry.fill(HIST("hMass"), InvMassXicToPiKP(candidate), candidate.pt()); } + registry.fill(HIST("hPtCand"), candidate.pt()); registry.fill(HIST("hPtProng0"), candidate.ptProng0(), candidate.pt()); registry.fill(HIST("hPtProng1"), candidate.ptProng1(), candidate.pt()); @@ -102,60 +130,14 @@ struct HfTaskXic { registry.fill(HIST("hDecLenErr"), candidate.chi2PCA(), candidate.pt()); } } -}; -/// Fills MC histograms. -struct HfTaskXicMc { - HistogramRegistry registry{ - "registry", - { - {"hPtRecSig", "3-prong candidates (matched);#it{p}_{T}^{rec.} (GeV/#it{c});entries", {HistType::kTH1F, {{100, 0., 10.}}}}, - {"hPtRecBg", "3-prong candidates (unmatched);#it{p}_{T}^{rec.} (GeV/#it{c});entries", {HistType::kTH1F, {{100, 0., 10.}}}}, - {"hPtGen", "MC particles (matched);#it{p}_{T}^{gen.} (GeV/#it{c});entries", {HistType::kTH1F, {{100, 0., 10.}}}}, - {"hPtGenSig", "3-prong candidates (matched);#it{p}_{T}^{gen.} (GeV/#it{c});entries", {HistType::kTH1F, {{100, 0., 10.}}}} /// - }}; - - Configurable d_selectionFlagXic{"d_selectionFlagXic", 1, "Selection Flag for Xic"}; - Configurable cutYCandMax{"cutYCandMax", -1., "max. cand. rapidity"}; - Configurable> bins{"pTBins", std::vector{hf_cuts_xic_topkpi::pTBins_v}, "pT bin limits"}; - - void init(o2::framework::InitContext&) - { - auto vbins = (std::vector)bins; - registry.add("hMassSig", "Invariant mass (matched);m (p K #pi) (GeV/#it{c}^{2});;entries", {HistType::kTH2F, {{500, 1.6, 3.1}, {vbins, "#it{p}_{T} (GeV/#it{c})"}}}); - registry.add("hMassBg", "Invariant mass (unmatched);m (p K #pi) (GeV/#it{c}^{2});;entries", {HistType::kTH2F, {{500, 1.6, 3.1}, {vbins, "#it{p}_{T} (GeV/#it{c})"}}}); - registry.add("hEtaGen", "3-prong candidates;candidate #it{#eta};;entries", {HistType::kTH2F, {{100, -2., 2.}, {vbins, "#it{p}_{T} (GeV/#it{c})"}}}); - - registry.add("hDecLengthRecSig", "3-prong candidates;decay length (cm);;entries", {HistType::kTH2F, {{200, 0., 2.}, {vbins, "#it{p}_{T} (GeV/#it{c})"}}}); - registry.add("hd0Prong0RecSig", "3-prong candidates;prong 0 DCAxy to prim. vertex (cm);;entries", {HistType::kTH2F, {{100, -1., 1.}, {vbins, "#it{p}_{T} (GeV/#it{c})"}}}); - registry.add("hd0Prong1RecSig", "3-prong candidates;prong 1 DCAxy to prim. vertex (cm);;entries", {HistType::kTH2F, {{100, -1., 1.}, {vbins, "#it{p}_{T} (GeV/#it{c})"}}}); - registry.add("hd0Prong2RecSig", "3-prong candidates;prong 1 DCAxy to prim. vertex (cm);;entries", {HistType::kTH2F, {{100, -1., 1.}, {vbins, "#it{p}_{T} (GeV/#it{c})"}}}); - registry.add("hCtRecSig", "3-prong candidates;proper lifetime (#Xi_{c}) * #it{c} (cm);;entries", {HistType::kTH2F, {{120, -20., 100.}, {vbins, "#it{p}_{T} (GeV/#it{c})"}}}); - registry.add("hCPARecSig", "3-prong candidates;cosine of pointing angle;;entries", {HistType::kTH2F, {{110, -1.1, 1.1}, {vbins, "#it{p}_{T} (GeV/#it{c})"}}}); - registry.add("hEtaRecSig", "3-prong candidates;candidate #it{#eta};;entries", {HistType::kTH2F, {{100, -2., 2.}, {vbins, "#it{p}_{T} (GeV/#it{c})"}}}); - registry.add("hPtProng0RecSig", "3-prong candidates;prong 0 #it{p}_{T} (GeV/#it{c});;entries", {HistType::kTH2F, {{100, 0., 10.}, {vbins, "#it{p}_{T} (GeV/#it{c})"}}}); - registry.add("hPtProng1RecSig", "3-prong candidates;prong 1 #it{p}_{T} (GeV/#it{c});;entries", {HistType::kTH2F, {{100, 0., 10.}, {vbins, "#it{p}_{T} (GeV/#it{c})"}}}); - registry.add("hPtProng2RecSig", "3-prong candidates;prong 2 #it{p}_{T} (GeV/#it{c});;entries", {HistType::kTH2F, {{100, 0., 10.}, {vbins, "#it{p}_{T} (GeV/#it{c})"}}}); - - registry.add("hDecLengthRecBg", "3-prong candidates;decay length (cm);;entries", {HistType::kTH2F, {{200, 0., 2.}, {vbins, "#it{p}_{T} (GeV/#it{c})"}}}); - registry.add("hd0Prong0RecBg", "3-prong candidates;prong 0 DCAxy to prim. vertex (cm);;entries", {HistType::kTH2F, {{100, -1., 1.}, {vbins, "#it{p}_{T} (GeV/#it{c})"}}}); - registry.add("hd0Prong1RecBg", "3-prong candidates;prong 1 DCAxy to prim. vertex (cm);;entries", {HistType::kTH2F, {{100, -1., 1.}, {vbins, "#it{p}_{T} (GeV/#it{c})"}}}); - registry.add("hd0Prong2RecBg", "3-prong candidates;prong 1 DCAxy to prim. vertex (cm);;entries", {HistType::kTH2F, {{100, -1., 1.}, {vbins, "#it{p}_{T} (GeV/#it{c})"}}}); - registry.add("hCtRecBg", "3-prong candidates;proper lifetime (#Xi_{c}) * #it{c} (cm);;entries", {HistType::kTH2F, {{120, -20., 100.}, {vbins, "#it{p}_{T} (GeV/#it{c})"}}}); - registry.add("hCPARecBg", "3-prong candidates;cosine of pointing angle;;entries", {HistType::kTH2F, {{110, -1.1, 1.1}, {vbins, "#it{p}_{T} (GeV/#it{c})"}}}); - registry.add("hEtaRecBg", "3-prong candidates;candidate #it{#eta};;entries", {HistType::kTH2F, {{100, -2., 2.}, {vbins, "#it{p}_{T} (GeV/#it{c})"}}}); - registry.add("hPtProng0RecBg", "3-prong candidates;prong 0 #it{p}_{T} (GeV/#it{c});;entries", {HistType::kTH2F, {{100, 0., 10.}, {vbins, "#it{p}_{T} (GeV/#it{c})"}}}); - registry.add("hPtProng1RecBg", "3-prong candidates;prong 1 #it{p}_{T} (GeV/#it{c});;entries", {HistType::kTH2F, {{100, 0., 10.}, {vbins, "#it{p}_{T} (GeV/#it{c})"}}}); - registry.add("hPtProng2RecBg", "3-prong candidates;prong 2 #it{p}_{T} (GeV/#it{c});;entries", {HistType::kTH2F, {{100, 0., 10.}, {vbins, "#it{p}_{T} (GeV/#it{c})"}}}); - } - - Filter filterSelectCandidates = (aod::hf_selcandidate_xic::isSelXicToPKPi >= d_selectionFlagXic || aod::hf_selcandidate_xic::isSelXicToPiKP >= d_selectionFlagXic); + Partition> selectedMCXicCandidates = (aod::hf_selcandidate_xic::isSelXicToPKPi >= d_selectionFlagXic || aod::hf_selcandidate_xic::isSelXicToPiKP >= d_selectionFlagXic); - void process(soa::Filtered> const& candidates, - soa::Join const& particlesMC, aod::BigTracksMC const&) + void processMC(soa::Join const& candidates, + soa::Join const& particlesMC, aod::BigTracksMC const&) { // MC rec. - for (auto& candidate : candidates) { + for (auto& candidate : selectedMCXicCandidates) { if (!(candidate.hfflag() & 1 << DecayType::XicToPKPi)) { continue; } @@ -232,14 +214,11 @@ struct HfTaskXicMc { } } } + + PROCESS_SWITCH(HfTaskXic, processMC, "Process MC", false); }; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) { - WorkflowSpec workflow{adaptAnalysisTask(cfgc)}; - const bool doMC = cfgc.options().get("doMC"); - if (doMC) { - workflow.push_back(adaptAnalysisTask(cfgc)); - } - return workflow; + return WorkflowSpec{adaptAnalysisTask(cfgc)}; } From 84a6d4d0ecfac1a885f7b4e0c07e87fa0069e265 Mon Sep 17 00:00:00 2001 From: Fabrizio Date: Sat, 23 Jul 2022 00:29:00 +0200 Subject: [PATCH 28/31] PWGHF: add information about Zvtx residual in histos for collision association probability (#1046) --- PWGHF/Tasks/HFMCValidation.cxx | 42 +++++++++++++++++++--------------- 1 file changed, 24 insertions(+), 18 deletions(-) diff --git a/PWGHF/Tasks/HFMCValidation.cxx b/PWGHF/Tasks/HFMCValidation.cxx index 4faaa9c13b2..59fa5e755e5 100644 --- a/PWGHF/Tasks/HFMCValidation.cxx +++ b/PWGHF/Tasks/HFMCValidation.cxx @@ -273,20 +273,20 @@ struct ValidationRecLevel { std::array, nCharmHadrons> histDeltaPt, histDeltaPx, histDeltaPy, histDeltaPz, histDeltaSecondaryVertexX, histDeltaSecondaryVertexY, histDeltaSecondaryVertexZ, histDeltaDecayLength; std::array, 3>, 2>, nCharmHadrons> histPtDau, histEtaDau, histImpactParameterDau; std::array, 2>, nCharmHadrons> histPtReco; - std::array, 4> histOriginTracks; + std::array, 4> histOriginTracks; HistogramRegistry registry{"registry", {}}; void init(o2::framework::InitContext&) { - histOriginTracks[0] = registry.add("histOriginNonAssociatedTracks", ";origin;#it{p}_{T}^{reco} (GeV/#it{c})", HistType::kTH2F, {{4, -1.5, 2.5}, {50, 0., 10.}}); // tracks not associated to any collision - histOriginTracks[1] = registry.add("histOriginAssociatedTracks", ";origin;#it{p}_{T}^{reco} (GeV/#it{c})", HistType::kTH2F, {{4, -1.5, 2.5}, {50, 0., 10.}}); // tracks associasted to a collision - histOriginTracks[2] = registry.add("histOriginGoodAssociatedTracks", ";origin;#it{p}_{T}^{reco} (GeV/#it{c})", HistType::kTH2F, {{4, -1.5, 2.5}, {50, 0., 10.}}); // tracks associated to the correct collision (considering the MC collision index) - histOriginTracks[3] = registry.add("histOriginWrongAssociatedTracks", ";origin;#it{p}_{T}^{reco} (GeV/#it{c})", HistType::kTH2F, {{4, -1.5, 2.5}, {50, 0., 10.}}); // tracks associated to the wrong collision (considering the MC collision index) + histOriginTracks[0] = registry.add("histOriginNonAssociatedTracks", ";origin;#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};#it{Z}_{vtx}^{reco}#minus#it{Z}_{vtx}^{gen} (cm)", HistType::kTHnSparseF, {{4, -1.5, 2.5}, {50, 0., 10.}, {40, -1., 1.}, {200, -1., 1.}}); // tracks not associated to any collision + histOriginTracks[1] = registry.add("histOriginAssociatedTracks", ";origin;#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};#it{Z}_{vtx}^{reco}#minus#it{Z}_{vtx}^{gen} (cm)", HistType::kTHnSparseF, {{4, -1.5, 2.5}, {50, 0., 10.}, {40, -1., 1.}, {200, -1., 1.}}); // tracks associasted to a collision + histOriginTracks[2] = registry.add("histOriginGoodAssociatedTracks", ";origin;#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};#it{Z}_{vtx}^{reco}#minus#it{Z}_{vtx}^{gen} (cm)", HistType::kTHnSparseF, {{4, -1.5, 2.5}, {50, 0., 10.}, {40, -1., 1.}, {200, -1., 1.}}); // tracks associated to the correct collision (considering the MC collision index) + histOriginTracks[3] = registry.add("histOriginWrongAssociatedTracks", ";origin;#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};#it{Z}_{vtx}^{reco}#minus#it{Z}_{vtx}^{gen} (cm)", HistType::kTHnSparseF, {{4, -1.5, 2.5}, {50, 0., 10.}, {40, -1., 1.}, {200, -1., 1.}}); // tracks associated to the wrong collision (considering the MC collision index) for (std::size_t iHist{0}; iHist < histOriginTracks.size(); ++iHist) { - histOriginTracks[iHist]->GetXaxis()->SetBinLabel(1, "no MC particle"); - histOriginTracks[iHist]->GetXaxis()->SetBinLabel(2, "no quark"); - histOriginTracks[iHist]->GetXaxis()->SetBinLabel(3, "charm"); - histOriginTracks[iHist]->GetXaxis()->SetBinLabel(4, "beauty"); + histOriginTracks[iHist]->GetAxis(0)->SetBinLabel(1, "no MC particle"); + histOriginTracks[iHist]->GetAxis(0)->SetBinLabel(2, "no quark"); + histOriginTracks[iHist]->GetAxis(0)->SetBinLabel(3, "charm"); + histOriginTracks[iHist]->GetAxis(0)->SetBinLabel(4, "beauty"); } for (auto iHad = 0; iHad < nCharmHadrons; ++iHad) { histDeltaPt[iHad] = registry.add(Form("histDeltaPt%s", particleNames[iHad].data()), Form("Pt difference reco - MC %s; #it{p}_{T}^{reco} - #it{p}_{T}^{gen} (GeV/#it{c}); entries", labels[iHad].data()), HistType::kTH1F, {{2000, -1., 1.}}); @@ -311,27 +311,33 @@ struct ValidationRecLevel { using HfCandProng2WithMCRec = soa::Join; using HfCandProng3WithMCRec = soa::Join; using CollisionsWithMCLabels = soa::Join; + using TracksWithSel = soa::Join; - void process(HfCandProng2WithMCRec const& cand2Prongs, HfCandProng3WithMCRec const& cand3Prongs, aod::BigTracksMC const& tracks, aod::McParticles const& particlesMC, aod::McCollisions const& mcCollisions, CollisionsWithMCLabels const& collisions) + void process(HfCandProng2WithMCRec const& cand2Prongs, HfCandProng3WithMCRec const& cand3Prongs, TracksWithSel const& tracks, aod::McParticles const& particlesMC, aod::McCollisions const& mcCollisions, CollisionsWithMCLabels const& collisions) { // loop over tracks for (auto& track : tracks) { + if (track.isGlobalTrackWoDCA() != (uint8_t) true) { + continue; + } uint index = uint(track.collisionId() >= 0); if (track.has_mcParticle()) { auto particle = track.mcParticle(); // get corresponding MC particle to check origin auto origin = RecoDecay::getCharmHadronOrigin(particlesMC, particle, true); - histOriginTracks[index]->Fill(origin, track.pt()); + float deltaZ = -999.f; if (index) { auto collision = track.collision_as(); auto mcCollision = particle.mcCollision(); + deltaZ = collision.posZ() - mcCollision.posZ(); uint index2 = 2; - if ((collision.mcCollisionId() == particle.mcCollisionId()) && std::abs(collision.posZ() - mcCollision.posZ()) < 0.02) { // 200 microns compatibility of Z vertex position also required + if (collision.mcCollisionId() == particle.mcCollisionId()) { index2 = 1; } - histOriginTracks[index + index2]->Fill(origin, track.pt()); + histOriginTracks[index + index2]->Fill(origin, track.pt(), track.eta(), deltaZ); } + histOriginTracks[index]->Fill(origin, track.pt(), track.eta(), deltaZ); } else { - histOriginTracks[index]->Fill(-1., track.pt()); + histOriginTracks[index]->Fill(-1.f, track.pt(), track.eta(), -999.f); } } @@ -359,8 +365,8 @@ struct ValidationRecLevel { if (whichHad >= 0 && whichOrigin >= 0) { int indexParticle = 0; - if (cand2Prong.index0_as().has_mcParticle()) { - indexParticle = RecoDecay::getMother(particlesMC, cand2Prong.index0_as().mcParticle(), PDGArrayParticle[whichHad], true); + if (cand2Prong.index0_as().has_mcParticle()) { + indexParticle = RecoDecay::getMother(particlesMC, cand2Prong.index0_as().mcParticle(), PDGArrayParticle[whichHad], true); } auto mother = particlesMC.rawIteratorAt(indexParticle); histDeltaPt[whichHad]->Fill(cand2Prong.pt() - mother.pt()); @@ -424,8 +430,8 @@ struct ValidationRecLevel { if (whichHad >= 0) { int indexParticle = 0; - if (cand3Prong.index0_as().has_mcParticle()) { - indexParticle = RecoDecay::getMother(particlesMC, cand3Prong.index0_as().mcParticle(), PDGArrayParticle[whichHad], true); + if (cand3Prong.index0_as().has_mcParticle()) { + indexParticle = RecoDecay::getMother(particlesMC, cand3Prong.index0_as().mcParticle(), PDGArrayParticle[whichHad], true); } auto mother = particlesMC.rawIteratorAt(indexParticle); histDeltaPt[whichHad]->Fill(cand3Prong.pt() - mother.pt()); From ab0b24ca06fc350b7c5af31bc9eb69bea5f23d77 Mon Sep 17 00:00:00 2001 From: mjongerh Date: Sat, 23 Jul 2022 00:29:57 +0200 Subject: [PATCH 29/31] PWGHF: Add Lb tree creator (#994) --- PWGHF/TableProducer/CMakeLists.txt | 5 + PWGHF/TableProducer/HFTreeCreatorLbToLcPi.cxx | 335 ++++++++++++++++++ 2 files changed, 340 insertions(+) create mode 100644 PWGHF/TableProducer/HFTreeCreatorLbToLcPi.cxx diff --git a/PWGHF/TableProducer/CMakeLists.txt b/PWGHF/TableProducer/CMakeLists.txt index 01fca030835..685a37d3413 100644 --- a/PWGHF/TableProducer/CMakeLists.txt +++ b/PWGHF/TableProducer/CMakeLists.txt @@ -74,6 +74,11 @@ o2physics_add_dpl_workflow(tree-creator-lc-topkpi PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2::DetectorsVertexing ROOT::EG COMPONENT_NAME Analysis) +o2physics_add_dpl_workflow(tree-creator-lb-tolcpi + SOURCES HFTreeCreatorLbToLcPi.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2::DetectorsVertexing ROOT::EG + COMPONENT_NAME Analysis) + o2physics_add_dpl_workflow(tree-creator-x-tojpsipipi SOURCES HFTreeCreatorXToJpsiPiPi.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2::DetectorsVertexing ROOT::EG diff --git a/PWGHF/TableProducer/HFTreeCreatorLbToLcPi.cxx b/PWGHF/TableProducer/HFTreeCreatorLbToLcPi.cxx new file mode 100644 index 00000000000..e4299936c89 --- /dev/null +++ b/PWGHF/TableProducer/HFTreeCreatorLbToLcPi.cxx @@ -0,0 +1,335 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +/// \file HFTreeCreatorLbToLcPi.cxx +/// \brief Writer of the 2 prong candidates in the form of flat tables to be stored in TTrees. +/// Intended for debug or for the local optimization of analysis on small samples. +/// In this file are defined and filled the output tables +/// \note Extended from HFTreeCreatorD0ToKPi, HFTreeCreatorLcToPKPi, HFTreeCreatorXToJpsiPiPi +/// +/// \author Panos Christakoglou , Nikhef +/// \author Maurice Jongerhuis , University Utrecht + +#include "Framework/runDataProcessing.h" +#include "Framework/AnalysisTask.h" +#include "DetectorsVertexing/DCAFitterN.h" +#include "PWGHF/DataModel/HFSecondaryVertex.h" +#include "PWGHF/DataModel/HFCandidateSelectionTables.h" +#include "Common/Core/trackUtilities.h" +#include "Common/Core/TrackSelectorPID.h" +#include "Common/DataModel/PIDResponse.h" +#include "ALICE3/DataModel/RICH.h" +#include "ReconstructionDataFormats/DCA.h" +#include "ReconstructionDataFormats/PID.h" + +using namespace o2; +using namespace o2::framework; +using namespace o2::aod::hf_cand; +using namespace o2::aod::hf_cand_lb; + +namespace o2::aod +{ +namespace full +{ +DECLARE_SOA_COLUMN(RSecondaryVertex, rSecondaryVertex, float); +DECLARE_SOA_COLUMN(PtProng0, ptProng0, float); +DECLARE_SOA_COLUMN(PProng0, pProng0, float); +DECLARE_SOA_COLUMN(ImpactParameterNormalised0, impactParameterNormalised0, float); +DECLARE_SOA_COLUMN(PtProng1, ptProng1, float); +DECLARE_SOA_COLUMN(PProng1, pProng1, float); +DECLARE_SOA_COLUMN(ImpactParameterNormalised1, impactParameterNormalised1, float); +DECLARE_SOA_COLUMN(CandidateSelFlag, candidateSelFlag, int8_t); +DECLARE_SOA_COLUMN(M, m, float); +DECLARE_SOA_COLUMN(Pt, pt, float); +DECLARE_SOA_COLUMN(P, p, float); +DECLARE_SOA_COLUMN(Eta, eta, float); +DECLARE_SOA_COLUMN(Phi, phi, float); +DECLARE_SOA_COLUMN(Y, y, float); +DECLARE_SOA_COLUMN(DecayLength, decayLength, float); +DECLARE_SOA_COLUMN(DecayLengthXY, decayLengthXY, float); +DECLARE_SOA_COLUMN(DecayLengthNormalised, decayLengthNormalised, float); +DECLARE_SOA_COLUMN(DecayLengthXYNormalised, decayLengthXYNormalised, float); +DECLARE_SOA_COLUMN(CPA, cpa, float); +DECLARE_SOA_COLUMN(CPAXY, cpaXY, float); +DECLARE_SOA_COLUMN(Ct, ct, float); +DECLARE_SOA_COLUMN(MCflag, mcflag, int8_t); +DECLARE_SOA_COLUMN(NSigRICHTrk0Pi, nsigRICHTrk0Pi, float); +DECLARE_SOA_COLUMN(NSigfRICHTrk0Pi, nsigfRICHTrk0Pi, float); +DECLARE_SOA_COLUMN(NSigTOFTrk0Pi, nsigTOFTrk0Pi, float); +// Lc selection parameters +DECLARE_SOA_COLUMN(LcM, lcM, float); +DECLARE_SOA_COLUMN(LcCt, lcCt, float); +DECLARE_SOA_COLUMN(LcY, lcY, float); +DECLARE_SOA_COLUMN(LcE, lcE, float); +DECLARE_SOA_COLUMN(LcEta, lcEta, float); +DECLARE_SOA_COLUMN(LcCPA, lcCPA, float); +DECLARE_SOA_COLUMN(LcCPAXY, lcCPAXY, float); +DECLARE_SOA_COLUMN(LcChi2PCA, lcChi2PCA, float); +DECLARE_SOA_COLUMN(LcDecayLength, lcDecayLength, float); +DECLARE_SOA_COLUMN(LcDecayLengthXY, lcDecayLengthXY, float); +DECLARE_SOA_COLUMN(LcDecayLengthNormalised, lcDecayLengthNormalised, float); +DECLARE_SOA_COLUMN(LcImpactParameter0, lcImpactParameter0, float); +DECLARE_SOA_COLUMN(LcImpactParameter1, lcImpactParameter1, float); +DECLARE_SOA_COLUMN(LcImpactParameter2, lcImpactParameter2, float); +DECLARE_SOA_COLUMN(NSigRICHTrk1Pi, nSigRICHTrk1Pi, float); +DECLARE_SOA_COLUMN(NSigRICHTrk1Pr, nSigRICHTrk1Pr, float); +DECLARE_SOA_COLUMN(NSigRICHTrk2Ka, nSigRICHTrk2Ka, float); +DECLARE_SOA_COLUMN(NSigRICHTrk3Pi, nSigRICHTrk3Pi, float); +DECLARE_SOA_COLUMN(NSigRICHTrk3Pr, nSigRICHTrk3Pr, float); +DECLARE_SOA_COLUMN(NSigfRICHTrk1Pi, nSigfRICHTrk1Pi, float); +DECLARE_SOA_COLUMN(NSigfRICHTrk1Pr, nSigfRICHTrk1Pr, float); +DECLARE_SOA_COLUMN(NSigfRICHTrk2Ka, nSigfRICHTrk2Ka, float); +DECLARE_SOA_COLUMN(NSigfRICHTrk3Pi, nSigfRICHTrk3Pi, float); +DECLARE_SOA_COLUMN(NSigfRICHTrk3Pr, nSigfRICHTrk3Pr, float); +DECLARE_SOA_COLUMN(NSigTOFTrk1Pi, nSigTOFrk1Pi, float); +DECLARE_SOA_COLUMN(NSigTOFTrk1Pr, nSigTOFrk1Pr, float); +DECLARE_SOA_COLUMN(NSigTOFTrk2Ka, nSigTOFrk2Ka, float); +DECLARE_SOA_COLUMN(NSigTOFTrk3Pi, nSigTOFrk3Pi, float); +DECLARE_SOA_COLUMN(NSigTOFTrk3Pr, nSigTOFrk3Pr, float); +} // namespace full + +// put the arguments into the table +DECLARE_SOA_TABLE(HfCandLbFull, "AOD", "HFCANDLbFull", + full::RSecondaryVertex, + full::DecayLength, + full::DecayLengthXY, + full::DecayLengthNormalised, + full::DecayLengthXYNormalised, + hf_cand::Chi2PCA, + full::ImpactParameterNormalised0, + full::PtProng0, + full::PProng0, + full::ImpactParameterNormalised1, + full::PtProng1, + full::PProng1, + hf_cand::PxProng0, + hf_cand::PyProng0, + hf_cand::PzProng0, + hf_cand::PxProng1, + hf_cand::PyProng1, + hf_cand::PzProng1, + hf_cand::ImpactParameter0, + hf_cand::ImpactParameter1, + hf_cand::ErrorImpactParameter0, + hf_cand::ErrorImpactParameter1, + full::NSigTOFTrk0Pi, + full::NSigRICHTrk0Pi, + full::NSigRICHTrk1Pi, + full::NSigRICHTrk1Pr, + full::NSigRICHTrk2Ka, + full::NSigRICHTrk3Pi, + full::NSigRICHTrk3Pr, + full::NSigfRICHTrk0Pi, + full::NSigfRICHTrk1Pi, + full::NSigfRICHTrk1Pr, + full::NSigfRICHTrk2Ka, + full::NSigfRICHTrk3Pi, + full::NSigfRICHTrk3Pr, + full::NSigTOFTrk1Pi, + full::NSigTOFTrk1Pr, + full::NSigTOFTrk2Ka, + full::NSigTOFTrk3Pi, + full::NSigTOFTrk3Pr, + full::LcM, + full::LcCt, + full::LcY, + full::LcE, + full::LcEta, + full::LcCPA, + full::LcCPAXY, + full::LcChi2PCA, + full::LcDecayLength, + full::LcDecayLengthXY, + full::LcDecayLengthNormalised, + full::LcImpactParameter0, + full::LcImpactParameter1, + full::LcImpactParameter2, + full::CandidateSelFlag, + full::M, + full::Pt, + full::P, + full::CPA, + full::CPAXY, + full::Ct, + full::Eta, + full::Phi, + full::Y, + full::MCflag); + +} // namespace o2::aod + +namespace o2::aod +{ +namespace hf_track_index_alice3_pid +{ +DECLARE_SOA_INDEX_COLUMN(Track, track); //! +DECLARE_SOA_INDEX_COLUMN(RICH, rich); //! +DECLARE_SOA_INDEX_COLUMN(FRICH, frich); //! +} // namespace hf_track_index_alice3_pid + +DECLARE_SOA_INDEX_TABLE_USER(HfTrackIndexALICE3PID, Tracks, "HFTRKIDXA3PID", //! + hf_track_index_alice3_pid::TrackId, + hf_track_index_alice3_pid::RICHId, + hf_track_index_alice3_pid::FRICHId); +} // namespace o2::aod + +struct Alice3PidIndexBuilder { + Builds index; + void init(o2::framework::InitContext&) {} +}; + +/// Writes the full information in an output TTree +struct HfTreeCreatorLbToLcPi { + Produces rowCandidateFull; + + using TracksExtendedPID = soa::Join; + + void process(soa::Join const& candidates, + soa::Join const&, + TracksExtendedPID const&, + aod::FRICHs const&, + aod::RICHs const&) + { + + // Filling candidate properties + rowCandidateFull.reserve(candidates.size()); + for (auto& candidate : candidates) { + auto fillTable = [&](int FunctionSelection, + float FunctionInvMass, + float FunctionCt, + float FunctionY) { + if (FunctionSelection >= 1) { + auto candLc = candidate.index0_as>(); + auto track0 = candidate.index1_as(); // daughter pion track + auto track1 = candLc.index0_as(); // granddaughter tracks (lc decay particles) + auto track2 = candLc.index1_as(); + auto track3 = candLc.index2_as(); + + auto RICHTrk0Pi = -5000.0; + auto RICHTrk1Pi = -5000.0; + auto RICHTrk1P = -5000.0; + auto RICHTrk2K = -5000.0; + auto RICHTrk3Pi = -5000.0; + auto RICHTrk3P = -5000.0; + + auto fRICHTrk0Pi = -5000.0; + auto fRICHTrk1Pi = -5000.0; + auto fRICHTrk1P = -5000.0; + auto fRICHTrk2K = -5000.0; + auto fRICHTrk3Pi = -5000.0; + auto fRICHTrk3P = -5000.0; + + if (track0.has_rich()) + RICHTrk0Pi = track0.rich().richNsigmaPi(); + if (track1.has_rich()) { + RICHTrk1Pi = track1.rich().richNsigmaPi(); + RICHTrk1P = track1.rich().richNsigmaPr(); + } + if (track2.has_rich()) + RICHTrk2K = track2.rich().richNsigmaKa(); + if (track3.has_rich()) { + RICHTrk3Pi = track3.rich().richNsigmaPi(); + RICHTrk3P = track3.rich().richNsigmaPr(); + } + + if (track0.has_frich()) + fRICHTrk0Pi = track0.frich().frichNsigmaPi(); + if (track1.has_frich()) { + fRICHTrk1Pi = track1.frich().frichNsigmaPi(); + fRICHTrk1P = track1.frich().frichNsigmaPr(); + } + if (track2.has_frich()) + fRICHTrk2K = track2.frich().frichNsigmaKa(); + if (track3.has_frich()) { + fRICHTrk3Pi = track3.frich().frichNsigmaPi(); + fRICHTrk3P = track3.frich().frichNsigmaPr(); + } + + rowCandidateFull( + candidate.rSecondaryVertex(), + candidate.decayLength(), + candidate.decayLengthXY(), + candidate.decayLengthNormalised(), + candidate.decayLengthXYNormalised(), + candidate.chi2PCA(), + candidate.impactParameterNormalised0(), + candidate.ptProng0(), + RecoDecay::p(candidate.pxProng0(), candidate.pyProng0(), candidate.pzProng0()), + candidate.impactParameterNormalised1(), + candidate.ptProng1(), + RecoDecay::p(candidate.pxProng1(), candidate.pyProng1(), candidate.pzProng1()), + candidate.pxProng0(), + candidate.pyProng0(), + candidate.pzProng0(), + candidate.pxProng1(), + candidate.pyProng1(), + candidate.pzProng1(), + candidate.impactParameter0(), + candidate.impactParameter1(), + candidate.errorImpactParameter0(), + candidate.errorImpactParameter1(), + track0.tofNSigmaPi(), + RICHTrk0Pi, + RICHTrk1Pi, + RICHTrk1P, + RICHTrk2K, + RICHTrk3Pi, + RICHTrk3P, + fRICHTrk0Pi, + fRICHTrk1Pi, + fRICHTrk1P, + fRICHTrk2K, + fRICHTrk3Pi, + fRICHTrk3P, + track1.tofNSigmaPi(), + track1.tofNSigmaPr(), + track2.tofNSigmaKa(), + track3.tofNSigmaPi(), + track3.tofNSigmaPr(), + o2::aod::hf_cand_prong3::InvMassLcpKpi(candLc), + o2::aod::hf_cand_prong3::CtLc(candLc), + o2::aod::hf_cand_prong3::YLc(candLc), + o2::aod::hf_cand_prong3::ELc(candLc), + candLc.eta(), + candLc.cpa(), + candLc.cpaXY(), + candLc.chi2PCA(), + candLc.decayLength(), + candLc.decayLengthXY(), + candLc.decayLengthXYNormalised(), + candLc.impactParameter0(), + candLc.impactParameter1(), + candLc.impactParameter2(), + FunctionSelection, + FunctionInvMass, + candidate.pt(), + candidate.p(), + candidate.cpa(), + candidate.cpaXY(), + FunctionCt, + candidate.eta(), + candidate.phi(), + FunctionY, + candidate.flagMCMatchRec()); + } + }; + fillTable(candidate.isSelLbToLcPi(), InvMassLbToLcPi(candidate), CtLb(candidate), YLb(candidate)); + } + } +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + WorkflowSpec workflow; + workflow.push_back(adaptAnalysisTask(cfgc)); + workflow.push_back(adaptAnalysisTask(cfgc)); + return workflow; +} From 70e93d9e4c75543e201fac42ccbd0471430760c8 Mon Sep 17 00:00:00 2001 From: Zuzanna Chochulska <87480906+zchochul@users.noreply.github.com> Date: Sun, 24 Jul 2022 18:20:47 +0200 Subject: [PATCH 30/31] Femtoworld (#1011) * FemtoWorld_v.21.07 * Femtoworld changes part 1 * FemtoWorld new folders --- PWGCF/CMakeLists.txt | 1 + PWGCF/FemtoWorld/CMakeLists.txt | 16 ++ PWGCF/FemtoWorld/Core/CMakeLists.txt | 10 + PWGCF/FemtoWorld/Core/FemtoWorldContainer.h | 140 ++++++++++ .../FemtoWorld/Core/FemtoWorldDetaDphiStar.h | 203 ++++++++++++++ PWGCF/FemtoWorld/Core/FemtoWorldEventHisto.h | 59 ++++ PWGCF/FemtoWorld/Core/FemtoWorldMath.h | 142 ++++++++++ PWGCF/FemtoWorld/Core/FemtoWorldPairCleaner.h | 93 +++++++ .../FemtoWorld/Core/FemtoWorldParticleHisto.h | 105 +++++++ PWGCF/FemtoWorld/Core/FemtoWorldUtils.h | 123 +++++++++ PWGCF/FemtoWorld/DataModel/CMakeLists.txt | 10 + PWGCF/FemtoWorld/TableProducer/CMakeLists.txt | 10 + PWGCF/FemtoWorld/Tasks/CMakeLists.txt | 15 + .../Tasks/femtoWorldPairTaskTrackTrack.cxx | 257 ++++++++++++++++++ 14 files changed, 1184 insertions(+) create mode 100644 PWGCF/FemtoWorld/CMakeLists.txt create mode 100644 PWGCF/FemtoWorld/Core/CMakeLists.txt create mode 100644 PWGCF/FemtoWorld/Core/FemtoWorldContainer.h create mode 100644 PWGCF/FemtoWorld/Core/FemtoWorldDetaDphiStar.h create mode 100644 PWGCF/FemtoWorld/Core/FemtoWorldEventHisto.h create mode 100644 PWGCF/FemtoWorld/Core/FemtoWorldMath.h create mode 100644 PWGCF/FemtoWorld/Core/FemtoWorldPairCleaner.h create mode 100644 PWGCF/FemtoWorld/Core/FemtoWorldParticleHisto.h create mode 100644 PWGCF/FemtoWorld/Core/FemtoWorldUtils.h create mode 100644 PWGCF/FemtoWorld/DataModel/CMakeLists.txt create mode 100644 PWGCF/FemtoWorld/TableProducer/CMakeLists.txt create mode 100644 PWGCF/FemtoWorld/Tasks/CMakeLists.txt create mode 100644 PWGCF/FemtoWorld/Tasks/femtoWorldPairTaskTrackTrack.cxx diff --git a/PWGCF/CMakeLists.txt b/PWGCF/CMakeLists.txt index e810577ed49..f31b23ad6a3 100644 --- a/PWGCF/CMakeLists.txt +++ b/PWGCF/CMakeLists.txt @@ -13,6 +13,7 @@ add_subdirectory(Core) # add_subdirectory(DataModel) add_subdirectory(GenericFramework) add_subdirectory(FemtoDream) +add_subdirectory(FemtoWorld) add_subdirectory(MultiparticleCorrelations) add_subdirectory(Tasks) add_subdirectory(TableProducer) diff --git a/PWGCF/FemtoWorld/CMakeLists.txt b/PWGCF/FemtoWorld/CMakeLists.txt new file mode 100644 index 00000000000..14a98889a2c --- /dev/null +++ b/PWGCF/FemtoWorld/CMakeLists.txt @@ -0,0 +1,16 @@ +# Copyright 2019-2020 CERN and copyright holders of ALICE O2. +# See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +# All rights not expressly granted are reserved. +# +# This software is distributed under the terms of the GNU General Public +# License v3 (GPL Version 3), copied verbatim in the file "COPYING". +# +# In applying this license CERN does not waive the privileges and immunities +# granted to it by virtue of its status as an Intergovernmental Organization +# or submit itself to any jurisdiction. + +add_subdirectory(Core) +add_subdirectory(DataModel) +add_subdirectory(TableProducer) +add_subdirectory(Tasks) + diff --git a/PWGCF/FemtoWorld/Core/CMakeLists.txt b/PWGCF/FemtoWorld/Core/CMakeLists.txt new file mode 100644 index 00000000000..bbfd7adac2b --- /dev/null +++ b/PWGCF/FemtoWorld/Core/CMakeLists.txt @@ -0,0 +1,10 @@ +# Copyright 2019-2020 CERN and copyright holders of ALICE O2. +# See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +# All rights not expressly granted are reserved. +# +# This software is distributed under the terms of the GNU General Public +# License v3 (GPL Version 3), copied verbatim in the file "COPYING". +# +# In applying this license CERN does not waive the privileges and immunities +# granted to it by virtue of its status as an Intergovernmental Organization +# or submit itself to any jurisdiction. diff --git a/PWGCF/FemtoWorld/Core/FemtoWorldContainer.h b/PWGCF/FemtoWorld/Core/FemtoWorldContainer.h new file mode 100644 index 00000000000..d3511f091df --- /dev/null +++ b/PWGCF/FemtoWorld/Core/FemtoWorldContainer.h @@ -0,0 +1,140 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +/// \file FemtoWorldContainer.h +/// \brief Definition of the FemtoWorldContainer +/// \author Andi Mathis, TU München, andreas.mathis@ph.tum.de +/// \author Valentina Mantovani Sarti, valentina.mantovani-sarti@tum.de + +#ifndef ANALYSIS_TASKS_PWGCF_FEMTOWORLD_FEMTOWORDLCONTAINER_H_ +#define ANALYSIS_TASKS_PWGCF_FEMTOWORLD_FEMTOWORDLCONTAINER_H_ + +#include "Framework/HistogramRegistry.h" +#include "FemtoWorldMath.h" + +#include "Math/Vector4D.h" +#include "TMath.h" +#include "TDatabasePDG.h" + +using namespace o2::framework; + +namespace o2::analysis::femtoWorld +{ + +namespace femtoWorldContainer +{ +/// Femtoscopic observable to be computed +enum Observable { kstar ///< kstar +}; + +/// Type of the event processind +enum EventType { same, ///< Pair from same event + mixed ///< Pair from mixed event +}; +}; // namespace femtoWorldContainer + +/// \class FemtoWorldContainer +/// \brief Container for all histogramming related to the correlation function. The two +/// particles of the pair are passed here, and the correlation function and QA histograms +/// are filled according to the specified observable +/// \tparam eventType Type of the event (same/mixed) +/// \tparam obs Observable to be computed (k*/Q_inv/...) +template +class FemtoWorldContainer +{ + public: + /// Destructor + virtual ~FemtoWorldContainer() = default; + + /// Initializes histograms for the task + /// \tparam T Type of the configurable for the axis configuration + /// \param registry Histogram registry to be passed + /// \param kstarBins k* binning for the histograms + /// \param multBins multiplicity binning for the histograms + /// \param kTBins kT binning for the histograms + /// \param mTBins mT binning for the histograms + template + void init(HistogramRegistry* registry, T& kstarBins, T& multBins, T& kTBins, T& mTBins) + { + mHistogramRegistry = registry; + std::string femtoObs; + if constexpr (mFemtoObs == femtoWorldContainer::Observable::kstar) { + femtoObs = "#it{k*} (GeV/#it{c})"; + } + std::vector tmpVecMult = multBins; + framework::AxisSpec multAxis = {tmpVecMult, "Multiplicity"}; + framework::AxisSpec femtoObsAxis = {kstarBins, femtoObs.c_str()}; + framework::AxisSpec kTAxis = {kTBins, "#it{k}_{T} (GeV/#it{c})"}; + framework::AxisSpec mTAxis = {mTBins, "#it{m}_{T} (GeV/#it{c}^{2})"}; + + std::string folderName = static_cast(mFolderSuffix[mEventType]); + mHistogramRegistry->add((folderName + "relPairDist").c_str(), ("; " + femtoObs + "; Entries").c_str(), kTH1F, {femtoObsAxis}); + mHistogramRegistry->add((folderName + "relPairkT").c_str(), "; #it{k}_{T} (GeV/#it{c}); Entries", kTH1F, {kTAxis}); + mHistogramRegistry->add((folderName + "relPairkstarkT").c_str(), ("; " + femtoObs + "; #it{k}_{T} (GeV/#it{c})").c_str(), kTH2F, {femtoObsAxis, kTAxis}); + mHistogramRegistry->add((folderName + "relPairkstarmT").c_str(), ("; " + femtoObs + "; #it{m}_{T} (GeV/#it{c}^{2})").c_str(), kTH2F, {femtoObsAxis, mTAxis}); + mHistogramRegistry->add((folderName + "relPairkstarMult").c_str(), ("; " + femtoObs + "; Multiplicity").c_str(), kTH2F, {femtoObsAxis, multAxis}); + mHistogramRegistry->add((folderName + "kstarPtPart1").c_str(), ("; " + femtoObs + "; #it{p} _{T} Particle 1 (GeV/#it{c})").c_str(), kTH2F, {femtoObsAxis, {375, 0., 7.5}}); + mHistogramRegistry->add((folderName + "kstarPtPart2").c_str(), ("; " + femtoObs + "; #it{p} _{T} Particle 2 (GeV/#it{c})").c_str(), kTH2F, {femtoObsAxis, {375, 0., 7.5}}); + mHistogramRegistry->add((folderName + "MultPtPart1").c_str(), "; #it{p} _{T} Particle 1 (GeV/#it{c}); Multiplicity", kTH2F, {{375, 0., 7.5}, multAxis}); + mHistogramRegistry->add((folderName + "MultPtPart2").c_str(), "; #it{p} _{T} Particle 2 (GeV/#it{c}); Multiplicity", kTH2F, {{375, 0., 7.5}, multAxis}); + mHistogramRegistry->add((folderName + "PtPart1PtPart2").c_str(), "; #it{p} _{T} Particle 1 (GeV/#it{c}); #it{p} _{T} Particle 2 (GeV/#it{c})", kTH2F, {{375, 0., 7.5}, {375, 0., 7.5}}); + } + + /// Set the PDG codes of the two particles involved + /// \param pdg1 PDG code of particle one + /// \param pdg2 PDG code of particle two + void setPDGCodes(const int pdg1, const int pdg2) + { + mMassOne = TDatabasePDG::Instance()->GetParticle(pdg1)->Mass(); + mMassTwo = TDatabasePDG::Instance()->GetParticle(pdg2)->Mass(); + } + + /// Pass a pair to the container and compute all the relevant observables + /// \tparam T type of the femtoworldparticle + /// \param part1 Particle one + /// \param part2 Particle two + /// \param mult Multiplicity of the event + template + void setPair(T const& part1, T const& part2, const int mult) + { + float femtoObs; + if constexpr (mFemtoObs == femtoWorldContainer::Observable::kstar) { + femtoObs = FemtoWorldMath::getkstar(part1, mMassOne, part2, mMassTwo); + } + const float kT = FemtoWorldMath::getkT(part1, mMassOne, part2, mMassTwo); + const float mT = FemtoWorldMath::getmT(part1, mMassOne, part2, mMassTwo); + + if (mHistogramRegistry) { + mHistogramRegistry->fill(HIST(mFolderSuffix[mEventType]) + HIST("relPairDist"), femtoObs); + mHistogramRegistry->fill(HIST(mFolderSuffix[mEventType]) + HIST("relPairkT"), kT); + mHistogramRegistry->fill(HIST(mFolderSuffix[mEventType]) + HIST("relPairkstarkT"), femtoObs, kT); + mHistogramRegistry->fill(HIST(mFolderSuffix[mEventType]) + HIST("relPairkstarmT"), femtoObs, mT); + mHistogramRegistry->fill(HIST(mFolderSuffix[mEventType]) + HIST("relPairkstarMult"), femtoObs, mult); + mHistogramRegistry->fill(HIST(mFolderSuffix[mEventType]) + HIST("kstarPtPart1"), femtoObs, part1.pt()); + mHistogramRegistry->fill(HIST(mFolderSuffix[mEventType]) + HIST("kstarPtPart2"), femtoObs, part2.pt()); + mHistogramRegistry->fill(HIST(mFolderSuffix[mEventType]) + HIST("MultPtPart1"), part1.pt(), mult); + mHistogramRegistry->fill(HIST(mFolderSuffix[mEventType]) + HIST("MultPtPart2"), part2.pt(), mult); + mHistogramRegistry->fill(HIST(mFolderSuffix[mEventType]) + HIST("PtPart1PtPart2"), part1.pt(), part2.pt()); + } + } + + protected: + HistogramRegistry* mHistogramRegistry = nullptr; ///< For QA output + static constexpr std::string_view mFolderSuffix[2] = {"SameEvent/", "MixedEvent/"}; ///< Folder naming for the output according to mEventType + static constexpr femtoWorldContainer::Observable mFemtoObs = obs; ///< Femtoscopic observable to be computed (according to femtoWorldContainer::Observable) + static constexpr int mEventType = eventType; ///< Type of the event (same/mixed, according to femtoWorldContainer::EventType) + float mMassOne = 0.f; ///< PDG mass of particle 1 + float mMassTwo = 0.f; ///< PDG mass of particle 2 +}; + +} // namespace o2::analysis::femtoWorld + +#endif /* ANALYSIS_TASKS_PWGCF_FEMTOWORLD_FEMTOWORDLCONTAINER_H_ */ diff --git a/PWGCF/FemtoWorld/Core/FemtoWorldDetaDphiStar.h b/PWGCF/FemtoWorld/Core/FemtoWorldDetaDphiStar.h new file mode 100644 index 00000000000..724374e3686 --- /dev/null +++ b/PWGCF/FemtoWorld/Core/FemtoWorldDetaDphiStar.h @@ -0,0 +1,203 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +/// \file FemtoWorldDetaDphiStar.h +/// \brief FemtoWorldDetaDphiStar - Checks particles for the close pair rejection. +/// \author Laura Serksnyte, TU München, laura.serksnyte@tum.de + +#ifndef ANALYSIS_TASKS_PWGCF_O2FEMTO_O2FEMTODETADPHISTAR_H_ +#define ANALYSIS_TASKS_PWGCF_O2FEMTO_O2FEMTODETADPHISTAR_H_ + +#include "PWGCF/DataModel/FemtoDerived.h" + +#include "Framework/HistogramRegistry.h" +#include + +namespace o2::analysis +{ +namespace femtoWorld +{ + +/// \class FemtoWorldDetaDphiStar +/// \brief Class to check particles for the close pair rejection. +/// \tparam partOne Type of particle 1 (Track/V0/Cascade/...) +/// \tparam partTwo Type of particle 2 (Track/V0/Cascade/...) +template +class FemtoWorldDetaDphiStar +{ + public: + /// Destructor + virtual ~FemtoWorldDetaDphiStar() = default; + /// Initalization of the histograms and setting required values + void init(HistogramRegistry* registry, HistogramRegistry* registryQA, float ldeltaPhiMax, float ldeltaEtaMax, bool lplotForEveryRadii) + { + deltaPhiMax = ldeltaPhiMax; + deltaEtaMax = ldeltaEtaMax; + plotForEveryRadii = lplotForEveryRadii; + mHistogramRegistry = registry; + mHistogramRegistryQA = registryQA; + + if constexpr (mPartOneType == o2::aod::femtodreamparticle::ParticleType::kTrack && mPartTwoType == o2::aod::femtodreamparticle::ParticleType::kTrack) { + std::string dirName = static_cast(dirNames[0]); + histdetadpi[0][0] = mHistogramRegistry->add((dirName + static_cast(histNames[0][0])).c_str(), "; #Delta #eta; #Delta #phi", kTH2F, {{100, -0.15, 0.15}, {100, -0.15, 0.15}}); + histdetadpi[0][1] = mHistogramRegistry->add((dirName + static_cast(histNames[1][0])).c_str(), "; #Delta #eta; #Delta #phi", kTH2F, {{100, -0.15, 0.15}, {100, -0.15, 0.15}}); + if (plotForEveryRadii) { + for (int i = 0; i < 9; i++) { + histdetadpiRadii[0][i] = mHistogramRegistryQA->add((dirName + static_cast(histNamesRadii[0][i])).c_str(), "; #Delta #eta; #Delta #phi", kTH2F, {{100, -0.15, 0.15}, {100, -0.15, 0.15}}); + } + } + } + if constexpr (mPartOneType == o2::aod::femtodreamparticle::ParticleType::kTrack && mPartTwoType == o2::aod::femtodreamparticle::ParticleType::kV0) { + for (int i = 0; i < 2; i++) { + std::string dirName = static_cast(dirNames[1]); + histdetadpi[i][0] = mHistogramRegistry->add((dirName + static_cast(histNames[0][i])).c_str(), "; #Delta #eta; #Delta #phi", kTH2F, {{100, -0.15, 0.15}, {100, -0.15, 0.15}}); + histdetadpi[i][1] = mHistogramRegistry->add((dirName + static_cast(histNames[1][i])).c_str(), "; #Delta #eta; #Delta #phi", kTH2F, {{100, -0.15, 0.15}, {100, -0.15, 0.15}}); + if (plotForEveryRadii) { + for (int j = 0; j < 9; j++) { + histdetadpiRadii[i][j] = mHistogramRegistryQA->add((dirName + static_cast(histNamesRadii[i][j])).c_str(), "; #Delta #eta; #Delta #phi", kTH2F, {{100, -0.15, 0.15}, {100, -0.15, 0.15}}); + } + } + } + } + } + /// Check if pair is close or not + template + bool isClosePair(Part const& part1, Part const& part2, Parts const& particles, float lmagfield) + { + magfield = lmagfield; + + if constexpr (mPartOneType == o2::aod::femtodreamparticle::ParticleType::kTrack && mPartTwoType == o2::aod::femtodreamparticle::ParticleType::kTrack) { + /// Track-Track combination + // check if provided particles are in agreement with the class instantiation + if (part1.partType() != o2::aod::femtodreamparticle::ParticleType::kTrack || part2.partType() != o2::aod::femtodreamparticle::ParticleType::kTrack) { + LOG(fatal) << "FemtoWorldDetaDphiStar: passed arguments don't agree with FemtoWorldDetaDphiStar instantiation! Please provide kTrack,kTrack candidates."; + return false; + } + auto deta = part1.eta() - part2.eta(); + auto dphiAvg = AveragePhiStar(part1, part2, 0); + histdetadpi[0][0]->Fill(deta, dphiAvg); + if (pow(dphiAvg, 2) / pow(deltaPhiMax, 2) + pow(deta, 2) / pow(deltaEtaMax, 2) < 1.) { + return true; + } else { + histdetadpi[0][1]->Fill(deta, dphiAvg); + return false; + } + + } else if constexpr (mPartOneType == o2::aod::femtodreamparticle::ParticleType::kTrack && mPartTwoType == o2::aod::femtodreamparticle::ParticleType::kV0) { + /// Track-V0 combination + // check if provided particles are in agreement with the class instantiation + if (part1.partType() != o2::aod::femtodreamparticle::ParticleType::kTrack || part2.partType() != o2::aod::femtodreamparticle::ParticleType::kV0) { + LOG(fatal) << "FemtoWorldDetaDphiStar: passed arguments don't agree with FemtoWorldDetaDphiStar instantiation! Please provide kTrack,kV0 candidates."; + return false; + } + + bool pass = false; + for (int i = 0; i < 2; i++) { + auto indexOfDaughter = part2.index() - 2 + i; + auto daughter = particles.begin() + indexOfDaughter; + auto deta = part1.eta() - daughter.eta(); + auto dphiAvg = AveragePhiStar(part1, *daughter, i); + histdetadpi[i][0]->Fill(deta, dphiAvg); + if (pow(dphiAvg, 2) / pow(deltaPhiMax, 2) + pow(deta, 2) / pow(deltaEtaMax, 2) < 1.) { + pass = true; + } else { + histdetadpi[i][1]->Fill(deta, dphiAvg); + } + } + return pass; + } else { + LOG(fatal) << "FemtoWorldPairCleaner: Combination of objects not defined - quitting!"; + return false; + } + } + + private: + HistogramRegistry* mHistogramRegistry = nullptr; ///< For main output + HistogramRegistry* mHistogramRegistryQA = nullptr; ///< For QA output + static constexpr std::string_view dirNames[2] = {"kTrack_kTrack/", "kTrack_kV0/"}; + + static constexpr std::string_view histNames[2][2] = {{"detadphidetadphi0Before_0", "detadphidetadphi0Before_1"}, + {"detadphidetadphi0After_0", "detadphidetadphi0After_1"}}; + static constexpr std::string_view histNamesRadii[2][9] = {{"detadphidetadphi0Before_0_0", "detadphidetadphi0Before_0_1", "detadphidetadphi0Before_0_2", + "detadphidetadphi0Before_0_3", "detadphidetadphi0Before_0_4", "detadphidetadphi0Before_0_5", + "detadphidetadphi0Before_0_6", "detadphidetadphi0Before_0_7", "detadphidetadphi0Before_0_8"}, + {"detadphidetadphi0Before_1_0", "detadphidetadphi0Before_1_1", "detadphidetadphi0Before_1_2", + "detadphidetadphi0Before_1_3", "detadphidetadphi0Before_1_4", "detadphidetadphi0Before_1_5", + "detadphidetadphi0Before_1_6", "detadphidetadphi0Before_1_7", "detadphidetadphi0Before_1_8"}}; + + static constexpr o2::aod::femtodreamparticle::ParticleType mPartOneType = partOne; ///< Type of particle 1 + static constexpr o2::aod::femtodreamparticle::ParticleType mPartTwoType = partTwo; ///< Type of particle 2 + + static constexpr float tmpRadiiTPC[9] = {85., 105., 125., 145., 165., 185., 205., 225., 245.}; + + static constexpr uint32_t kSignMinusMask = 1; + static constexpr uint32_t kSignPlusMask = 1 << 1; + static constexpr uint32_t kValue0 = 0; + + float deltaPhiMax; + float deltaEtaMax; + float magfield; + bool plotForEveryRadii = false; + + std::array, 2>, 2> histdetadpi{}; + std::array, 9>, 2> histdetadpiRadii{}; + + /// Calculate phi at all required radii stored in tmpRadiiTPC + /// Magnetic field to be provided in Tesla + template + void PhiAtRadiiTPC(const T& part, std::vector& tmpVec) + { + + float phi0 = part.phi(); + // Start: Get the charge from cutcontainer using masks + float charge = 0.; + if ((part.cut() & kSignMinusMask) == kValue0 && (part.cut() & kSignPlusMask) == kValue0) { + charge = 0; + } else if ((part.cut() & kSignPlusMask) == kSignPlusMask) { + charge = 1; + } else if ((part.cut() & kSignMinusMask) == kSignMinusMask) { + charge = -1; + } else { + LOG(fatal) << "FemtoWorldDetaDphiStar: Charge bits are set wrong!"; + } + // End: Get the charge from cutcontainer using masks + float pt = part.pt(); + for (size_t i = 0; i < 9; i++) { + tmpVec.push_back(phi0 - std::asin(0.3 * charge * 0.1 * magfield * tmpRadiiTPC[i] * 0.01 / (2. * pt))); + } + } + + /// Calculate average phi + template + float AveragePhiStar(const T1& part1, const T2& part2, int iHist) + { + std::vector tmpVec1; + std::vector tmpVec2; + PhiAtRadiiTPC(part1, tmpVec1); + PhiAtRadiiTPC(part2, tmpVec2); + const int num = tmpVec1.size(); + float dPhiAvg = 0; + for (int i = 0; i < num; i++) { + float dphi = tmpVec1.at(i) - tmpVec2.at(i); + dphi = TVector2::Phi_mpi_pi(dphi); + dPhiAvg += dphi; + if (plotForEveryRadii) { + histdetadpiRadii[iHist][i]->Fill(part1.eta() - part2.eta(), dphi); + } + } + return (dPhiAvg / (float)num); + } +}; + +} /* namespace femtoWorld */ +} /* namespace o2::analysis */ + +#endif /* ANALYSIS_TASKS_PWGCF_O2FEMTO_O2FEMTODETADPHISTAR_H_ */ diff --git a/PWGCF/FemtoWorld/Core/FemtoWorldEventHisto.h b/PWGCF/FemtoWorld/Core/FemtoWorldEventHisto.h new file mode 100644 index 00000000000..4c1e33027fb --- /dev/null +++ b/PWGCF/FemtoWorld/Core/FemtoWorldEventHisto.h @@ -0,0 +1,59 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +/// \file FemtoWorldEventHisto.h +/// \brief FemtoWorldEventHisto - Histogram class for tracks, V0s and cascades +/// \author Andi Mathis, TU München, andreas.mathis@ph.tum.de + +#ifndef ANALYSIS_TASKS_PWGCF_FEMTOWORLD_INCLUDE_FEMTOWORLD_FEMTOEVENTHISTO_H_ +#define ANALYSIS_TASKS_PWGCF_FEMTOWORLD_INCLUDE_FEMTOWORLD_FEMTOEVENTHISTO_H_ + +#include "PWGCF/DataModel/FemtoDerived.h" + +#include "Framework/HistogramRegistry.h" + +using namespace o2::framework; +namespace o2::analysis::femtoWorld +{ +/// \class FemtoWorldEventHisto +/// \brief Class for histogramming event properties +class FemtoWorldEventHisto +{ + public: + /// Destructor + virtual ~FemtoWorldEventHisto() = default; + /// Initializes histograms for the task + /// \param registry Histogram registry to be passed + void init(HistogramRegistry* registry) + { + mHistogramRegistry = registry; + mHistogramRegistry->add("Event/zvtxhist", "; vtx_{z} (cm); Entries", kTH1F, {{300, -12.5, 12.5}}); + mHistogramRegistry->add("Event/MultV0M", "; vMultV0M; Entries", kTH1F, {{600, 0, 600}}); + } + + /// Some basic QA of the event + /// \tparam T type of the collision + /// \param col Collision + template + void fillQA(T const& col) + { + if (mHistogramRegistry) { + mHistogramRegistry->fill(HIST("Event/zvtxhist"), col.posZ()); + mHistogramRegistry->fill(HIST("Event/MultV0M"), col.multV0M()); + } + } + + private: + HistogramRegistry* mHistogramRegistry; ///< For QA output +}; +} // namespace o2::analysis::femtoWorld + +#endif /* ANALYSIS_TASKS_PWGCF_FEMTOWORLD_INCLUDE_FEMTOWORLD_FEMTOEVENTHISTO_H_ */ diff --git a/PWGCF/FemtoWorld/Core/FemtoWorldMath.h b/PWGCF/FemtoWorld/Core/FemtoWorldMath.h new file mode 100644 index 00000000000..fcebe3d9eba --- /dev/null +++ b/PWGCF/FemtoWorld/Core/FemtoWorldMath.h @@ -0,0 +1,142 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +/// \file FemtoWorldMath.h +/// \brief Definition of the FemtoWorldMath Container for math calculations of quantities related to pairs +/// \author Valentina Mantovani Sarti, TU München, valentina.mantovani-sarti@tum.de, Laura Serksnyte, TU München, laura.serksnyte@cern.ch + +#ifndef ANALYSIS_TASKS_PWGCF_O2FEMTO_O2FEMTOMATH_H_ +#define ANALYSIS_TASKS_PWGCF_O2FEMTO_O2FEMTOMATH_H_ + +#include "Math/Vector4D.h" +#include "Math/Boost.h" +#include "TLorentzVector.h" +#include "TMath.h" + +#include + +namespace o2::analysis::femtoWorld +{ + +/// \class FemtoWorldMath +/// \brief Container for math calculations of quantities related to pairs +class FemtoWorldMath +{ + public: + /// Compute the k* of a pair of particles + /// \tparam T type of tracks + /// \param part1 Particle 1 + /// \param mass1 Mass of particle 1 + /// \param part2 Particle 2 + /// \param mass2 Mass of particle 2 + template + static float getkstar(const T& part1, const float mass1, const T& part2, const float mass2) + { + const ROOT::Math::PtEtaPhiMVector vecpart1(part1.pt(), part1.eta(), part1.phi(), mass1); + const ROOT::Math::PtEtaPhiMVector vecpart2(part2.pt(), part2.eta(), part2.phi(), mass2); + const ROOT::Math::PtEtaPhiMVector trackSum = vecpart1 + vecpart2; + + const float beta = trackSum.Beta(); + const float betax = beta * std::cos(trackSum.Phi()) * std::sin(trackSum.Theta()); + const float betay = beta * std::sin(trackSum.Phi()) * std::sin(trackSum.Theta()); + const float betaz = beta * std::cos(trackSum.Theta()); + + ROOT::Math::PxPyPzMVector PartOneCMS(vecpart1); + ROOT::Math::PxPyPzMVector PartTwoCMS(vecpart2); + + const ROOT::Math::Boost boostPRF = ROOT::Math::Boost(-betax, -betay, -betaz); + PartOneCMS = boostPRF(PartOneCMS); + PartTwoCMS = boostPRF(PartTwoCMS); + + const ROOT::Math::PxPyPzMVector trackRelK = PartOneCMS - PartTwoCMS; + return 0.5 * trackRelK.P(); + } + /// Compute the qij of a pair of particles + /// \tparam T type of tracks + /// \param vecparti Particle i PxPyPzMVector + /// \param vecpartj Particle j PxPyPzMVector + // The q12 components can be calculated as: + // q^mu = (p1-p2)^mu /2 - ((p1-p2)*P/(2P^2))*P^mu + // where P = p1+p2 + // Reference: https://www.annualreviews.org/doi/pdf/10.1146/annurev.nucl.55.090704.151533 + // In the following code the above written equation will be expressed as: + // q = trackDifference/2 - scaling * trackSum + // where scaling is a float number: + // scaling = trackDifference*trackSum/(2*trackSum^2) = ((p1-p2)*P/(2P^2)) + // We don't use the reduced vector - no division by 2 + template + static ROOT::Math::PxPyPzEVector getqij(const T& vecparti, const T& vecpartj) + { + ROOT::Math::PxPyPzEVector trackSum = vecparti + vecpartj; + ROOT::Math::PxPyPzEVector trackDifference = vecparti - vecpartj; + float scaling = trackDifference.Dot(trackSum) / trackSum.Dot(trackSum); + return trackDifference - scaling * trackSum; + } + + /// Compute the Q3 of a triplet of particles + /// \tparam T type of tracks + /// \param part1 Particle 1 + /// \param mass1 Mass of particle 1 + /// \param part2 Particle 2 + /// \param mass2 Mass of particle 2 + /// \param part3 Particle 3 + /// \param mass3 Mass of particle 3 + template + static float getQ3(const T& part1, const float mass1, const T& part2, const float mass2, const T& part3, const float mass3) + { + float E1 = sqrt(pow(part1.px(), 2) + pow(part1.py(), 2) + pow(part1.pz(), 2) + pow(mass1, 2)); + float E2 = sqrt(pow(part2.px(), 2) + pow(part2.py(), 2) + pow(part2.pz(), 2) + pow(mass2, 2)); + float E3 = sqrt(pow(part3.px(), 2) + pow(part3.py(), 2) + pow(part3.pz(), 2) + pow(mass3, 2)); + + const ROOT::Math::PxPyPzEVector vecpart1(part1.px(), part1.py(), part1.pz(), E1); + const ROOT::Math::PxPyPzEVector vecpart2(part2.px(), part2.py(), part2.pz(), E2); + const ROOT::Math::PxPyPzEVector vecpart3(part3.px(), part3.py(), part3.pz(), E3); + + ROOT::Math::PxPyPzEVector q12 = getqij(vecpart1, vecpart2); + ROOT::Math::PxPyPzEVector q23 = getqij(vecpart2, vecpart3); + ROOT::Math::PxPyPzEVector q31 = getqij(vecpart3, vecpart1); + + float Q32 = q12.M2() + q23.M2() + q31.M2(); + + return sqrt(-Q32); + } + + /// Compute the transverse momentum of a pair of particles + /// \tparam T type of tracks + /// \param part1 Particle 1 + /// \param mass1 Mass of particle 1 + /// \param part2 Particle 2 + /// \param mass2 Mass of particle 2 + template + static float getkT(const T& part1, const float mass1, const T& part2, const float mass2) + { + const ROOT::Math::PtEtaPhiMVector vecpart1(part1.pt(), part1.eta(), part1.phi(), mass1); + const ROOT::Math::PtEtaPhiMVector vecpart2(part2.pt(), part2.eta(), part2.phi(), mass2); + const ROOT::Math::PtEtaPhiMVector trackSum = vecpart1 + vecpart2; + return 0.5 * trackSum.Pt(); + } + + /// Compute the transverse mass of a pair of particles + /// \tparam T type of tracks + /// \param part1 Particle 1 + /// \param mass1 Mass of particle 1 + /// \param part2 Particle 2 + /// \param mass2 Mass of particle 2 + template + static float getmT(const T& part1, const float mass1, const T& part2, const float mass2) + { + return std::sqrt(std::pow(getkT(part1, mass1, part2, mass2), 2.) + std::pow(0.5 * (mass1 + mass2), 2.)); + } +}; + +} // namespace o2::analysis::femtoWorld + +#endif /* ANALYSIS_TASKS_PWGCF_O2FEMTO_O2FEMTOMATH_H_ */ diff --git a/PWGCF/FemtoWorld/Core/FemtoWorldPairCleaner.h b/PWGCF/FemtoWorld/Core/FemtoWorldPairCleaner.h new file mode 100644 index 00000000000..8a6b4565b88 --- /dev/null +++ b/PWGCF/FemtoWorld/Core/FemtoWorldPairCleaner.h @@ -0,0 +1,93 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +/// \file FemtoWorldPairCleaner.h +/// \brief FemtoWorldPairCleaner - Makes sure only proper candidates are paired +/// \author Andi Mathis, TU München, andreas.mathis@ph.tum.de, Laura Serksnyte , TU München + +#ifndef ANALYSIS_TASKS_PWGCF_FEMTOWORLD_INCLUDE_FEMTOWORLD_FEMTOWORLDPAIRCLEANER_H_ +#define ANALYSIS_TASKS_PWGCF_FEMTOWORLD_INCLUDE_FEMTOWORLD_FEMTOWORLDPAIRCLEANER_H_ + +#include "PWGCF/DataModel/FemtoDerived.h" + +#include "Framework/HistogramRegistry.h" + +using namespace o2::framework; + +namespace o2::analysis::femtoWorld +{ + +/// \class FemtoWorldPairCleaner +/// \brief Class taking care that no autocorrelations enter the same event distribution +/// \tparam partOne Type of particle 1 (Track/V0/Cascade/...) +/// \tparam partTwo Type of particle 2 (Track/V0/Cascade/...) +template +class FemtoWorldPairCleaner +{ + public: + /// Destructor + virtual ~FemtoWorldPairCleaner() = default; + + /// Initalization of the QA histograms + /// \param registry HistogramRegistry + void init(HistogramRegistry* registry) + { + if (registry) { + mHistogramRegistry = registry; + // \todo some QA histograms like in FemtoWorld + } + } + + /// Check whether a given pair has shared tracks + /// \tparam Part Data type of the particle + /// \tparam Parts Data type of the collection of all particles + /// \param part1 Particle 1 + /// \param part2 Particle 2 + /// \param particles Collection of all particles passed to the task + /// \return Whether the pair has shared tracks + template + bool isCleanPair(Part const& part1, Part const& part2, Parts const& particles) + { + if constexpr (mPartOneType == o2::aod::femtodreamparticle::ParticleType::kTrack && mPartTwoType == o2::aod::femtodreamparticle::ParticleType::kTrack) { + /// Track-Track combination + if (part1.partType() != o2::aod::femtodreamparticle::ParticleType::kTrack || part2.partType() != o2::aod::femtodreamparticle::ParticleType::kTrack) { + LOG(fatal) << "FemtoWorldPairCleaner: passed arguments don't agree with FemtoWorldPairCleaner instantiation! Please provide kTrack,kTrack candidates."; + return false; + } + return part1.globalIndex() != part2.globalIndex(); + } else if constexpr (mPartOneType == o2::aod::femtodreamparticle::ParticleType::kTrack && mPartTwoType == o2::aod::femtodreamparticle::ParticleType::kV0) { + /// Track-V0 combination + if (part2.partType() != o2::aod::femtodreamparticle::ParticleType::kV0) { + LOG(fatal) << "FemtoWorldPairCleaner: passed arguments don't agree with FemtoWorldPairCleaner instantiation! Please provide second argument kV0 candidate."; + return false; + } + uint64_t id1 = part2.index() - 2; + uint64_t id2 = part2.index() - 1; + auto daughter1 = particles.begin() + id1; + auto daughter2 = particles.begin() + id2; + if ((*daughter1).indices()[0] <= 0 && (*daughter1).indices()[1] <= 0 && (*daughter2).indices()[0] <= 0 && (*daughter2).indices()[1] <= 0) { + return true; + } + return false; + } else { + LOG(fatal) << "FemtoWorldPairCleaner: Combination of objects not defined - quitting!"; + return false; + } + } + + private: + HistogramRegistry* mHistogramRegistry; ///< For QA output + static constexpr o2::aod::femtodreamparticle::ParticleType mPartOneType = partOne; ///< Type of particle 1 + static constexpr o2::aod::femtodreamparticle::ParticleType mPartTwoType = partTwo; ///< Type of particle 2 +}; +} // namespace o2::analysis::femtoWorld + +#endif /* ANALYSIS_TASKS_PWGCF_FEMTOWORLD_INCLUDE_FEMTOWORLD_FEMTOWORLDPAIRCLEANER_H_ */ diff --git a/PWGCF/FemtoWorld/Core/FemtoWorldParticleHisto.h b/PWGCF/FemtoWorld/Core/FemtoWorldParticleHisto.h new file mode 100644 index 00000000000..8de8ad41e0a --- /dev/null +++ b/PWGCF/FemtoWorld/Core/FemtoWorldParticleHisto.h @@ -0,0 +1,105 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +/// \file FemtoWorldParticleHisto.h +/// \brief FemtoWorldParticleHisto - Histogram class for tracks, V0s and cascades +/// \author Andi Mathis, TU München, andreas.mathis@ph.tum.de + +#ifndef ANALYSIS_TASKS_PWGCF_FEMTOWORLD_INCLUDE_FEMTOWORLD_FEMTOPARTICLEHISTO_H_ +#define ANALYSIS_TASKS_PWGCF_FEMTOWORLD_INCLUDE_FEMTOWORLD_FEMTOPARTICLEHISTO_H_ + +#include "PWGCF/DataModel/FemtoDerived.h" +#include "Framework/HistogramRegistry.h" + +using namespace o2::framework; + +namespace o2::analysis::femtoWorld +{ + +/// \class FemtoWorldParticleHisto +/// \brief Class for histogramming particle properties +/// \tparam particleType Type of the particle (Track/V0/Cascade/...) +/// \tparam suffixType (optional) Takes care of the suffix for the folder name in case of analyses of pairs of the same kind (T-T, V-V, C-C) +template +class FemtoWorldParticleHisto +{ + public: + /// Destructor + virtual ~FemtoWorldParticleHisto() = default; + + /// Initalization of the QA histograms + /// \param registry HistogramRegistry + void init(HistogramRegistry* registry) + { + if (registry) { + mHistogramRegistry = registry; + /// The folder names are defined by the type of the object and the suffix (if applicable) + std::string folderName = static_cast(o2::aod::femtodreamparticle::ParticleTypeName[mParticleType]); + folderName += static_cast(mFolderSuffix[mFolderSuffixType]); + + /// Histograms of the kinematic properties + mHistogramRegistry->add((folderName + "/hPt").c_str(), "; #it{p}_{T} (GeV/#it{c}); Entries", kTH1F, {{240, 0, 6}}); + mHistogramRegistry->add((folderName + "/hEta").c_str(), "; #eta; Entries", kTH1F, {{200, -1.5, 1.5}}); + mHistogramRegistry->add((folderName + "/hPhi").c_str(), "; #phi; Entries", kTH1F, {{200, 0, 2. * M_PI}}); + + /// Particle-type specific histograms + if constexpr (mParticleType == o2::aod::femtodreamparticle::ParticleType::kTrack) { + /// Track histograms + mHistogramRegistry->add((folderName + "/hDCAxy").c_str(), "; #it{p}_{T} (GeV/#it{c}); DCA_{xy} (cm)", kTH2F, {{20, 0.5, 4.05}, {500, -5, 5}}); + } else if constexpr (mParticleType == o2::aod::femtodreamparticle::ParticleType::kV0) { + /// V0 histograms + mHistogramRegistry->add((folderName + "/hCPA").c_str(), "; #it{p}_{T} (GeV/#it{c}); cos#alpha", kTH2F, {{8, 0.3, 4.3}, {1000, 0.9, 1}}); + } else if constexpr (mParticleType == o2::aod::femtodreamparticle::ParticleType::kCascade) { + /// Cascade histograms + } else { + LOG(fatal) << "FemtoWorldParticleHisto: Histogramming for requested object not defined - quitting!"; + } + } + } + + /// Filling of the histograms + /// \tparam T Data type of the particle + /// \param part Particle + template + void fillQA(T const& part) + { + if (mHistogramRegistry) { + /// Histograms of the kinematic properties + mHistogramRegistry->fill(HIST(o2::aod::femtodreamparticle::ParticleTypeName[mParticleType]) + HIST(mFolderSuffix[mFolderSuffixType]) + HIST("/hPt"), part.pt()); + mHistogramRegistry->fill(HIST(o2::aod::femtodreamparticle::ParticleTypeName[mParticleType]) + HIST(mFolderSuffix[mFolderSuffixType]) + HIST("/hEta"), part.eta()); + mHistogramRegistry->fill(HIST(o2::aod::femtodreamparticle::ParticleTypeName[mParticleType]) + HIST(mFolderSuffix[mFolderSuffixType]) + HIST("/hPhi"), part.phi()); + + /// Particle-type specific histograms + if constexpr (mParticleType == o2::aod::femtodreamparticle::ParticleType::kTrack) { + /// Track histograms + mHistogramRegistry->fill(HIST(o2::aod::femtodreamparticle::ParticleTypeName[mParticleType]) + HIST(mFolderSuffix[mFolderSuffixType]) + HIST("/hDCAxy"), + part.pt(), part.tempFitVar()); + } else if constexpr (mParticleType == o2::aod::femtodreamparticle::ParticleType::kV0) { + /// V0 histograms + mHistogramRegistry->fill(HIST(o2::aod::femtodreamparticle::ParticleTypeName[mParticleType]) + HIST(mFolderSuffix[mFolderSuffixType]) + HIST("/hCPA"), + part.pt(), part.tempFitVar()); + } else if constexpr (mParticleType == o2::aod::femtodreamparticle::ParticleType::kCascade) { + /// Cascade histograms + } else { + LOG(fatal) << "FemtoWorldParticleHisto: Histogramming for requested object not defined - quitting!"; + } + } + } + + private: + HistogramRegistry* mHistogramRegistry; ///< For QA output + static constexpr o2::aod::femtodreamparticle::ParticleType mParticleType = particleType; ///< Type of the particle under analysis + static constexpr int mFolderSuffixType = suffixType; ///< Counter for the folder suffix specified below + static constexpr std::string_view mFolderSuffix[3] = {"", "_one", "_two"}; ///< Suffix for the folder name in case of analyses of pairs of the same kind (T-T, V-V, C-C) +}; +} // namespace o2::analysis::femtoWorld + +#endif /* ANALYSIS_TASKS_PWGCF_FEMTOWORLD_INCLUDE_FEMTOWORLD_FEMTOPARTICLEHISTO_H_ */ diff --git a/PWGCF/FemtoWorld/Core/FemtoWorldUtils.h b/PWGCF/FemtoWorld/Core/FemtoWorldUtils.h new file mode 100644 index 00000000000..6a4a3618e04 --- /dev/null +++ b/PWGCF/FemtoWorld/Core/FemtoWorldUtils.h @@ -0,0 +1,123 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +/// \file CFFilter.cxx +/// \brief Utilities for the FemtoWorld framework +/// +/// \author Luca Barioglio, TU München, luca.barioglio@cern.ch + +#ifndef ANALYSIS_TASKS_PWGCF_FEMTOWORLD_UTILS_H_ +#define ANALYSIS_TASKS_PWGCF_FEMTOWORLD_UTILS_H_ + +#include "Framework/ASoAHelpers.h" +#include "PWGCF/DataModel/FemtoDerived.h" + +#include + +#include + +namespace o2::analysis::femtoWorld +{ + +enum kPIDselection { + k3d5sigma = 0, + k3sigma = 1, + k2d5sigma = 2 +}; + +enum kDetector { + kTPC = 0, + kTPCTOF = 1, + kNdetectors = 2 +}; + +/// internal function that returns the kPIDselection element corresponding to a specifica n-sigma value +/// \param nSigma number of sigmas for PID +/// \param vNsigma vector with the number of sigmas of interest +/// \return kPIDselection corresponing to n-sigma +kPIDselection getPIDselection(const float nSigma, const std::vector& vNsigma) +{ + for (int i = 0; i < (int)vNsigma.size(); i++) { + if (abs(nSigma - vNsigma[i]) < 1e-3) { + return static_cast(i); + } + } + LOG(info) << "Invalid value of nSigma: " << nSigma << ". Standard 3 sigma returned." << std::endl; + return kPIDselection::k3sigma; +} + +/// function that checks whether the PID selection specified in the vectors is fulfilled +/// \param pidcut Bit-wise container for the PID +/// \param vSpecies vector with ID corresponding to the selected species (output from cutculator) +/// \param nSpecies number of available selected species (output from cutculator) +/// \param nSigma number of sigma selection fo PID +/// \param vNsigma vector with available n-sigma selections for PID +/// \param kDetector enum corresponding to the PID technique +/// \return Whether the PID selection specified in the vectors is fulfilled +bool isPIDSelected(aod::femtodreamparticle::cutContainerType const& pidcut, std::vector const& vSpecies, int nSpecies, float nSigma, const std::vector& vNsigma, const kDetector iDet = kDetector::kTPC) +{ + bool pidSelection = true; + kPIDselection iNsigma = getPIDselection(nSigma, vNsigma); + for (auto iSpecies : vSpecies) { + //\todo we also need the possibility to specify whether the bit is true/false ->std>>vector> + // if (!((pidcut >> it.first) & it.second)) { + int bit_to_check = nSpecies * kDetector::kNdetectors * iNsigma + iSpecies * kDetector::kNdetectors + iDet; + if (!(pidcut & (1UL << bit_to_check))) { + pidSelection = false; + } + } + return pidSelection; +}; + +/// function that checks whether the PID selection specified in the vectors is fulfilled, depending on the momentum TPC or TPC+TOF PID is conducted +/// \param pidcut Bit-wise container for the PID +/// \param momentum Momentum of the track +/// \param pidThresh Momentum threshold that separates between TPC and TPC+TOF PID +/// \param vSpecies Vector with the species of interest (number returned by the CutCulator) +/// \param nSpecies number of available selected species (output from cutculator) +/// \param nSigmaTPC Number of TPC sigmas for selection +/// \param nSigmaTPCTOF Number of TPC+TOF sigmas for selection (circular selection) +/// \return Whether the PID selection is fulfilled +bool isFullPIDSelected(aod::femtodreamparticle::cutContainerType const& pidCut, float const momentum, float const pidThresh, std::vector const& vSpecies, int nSpecies, const std::vector& vNsigma = {3.5, 3., 2.5}, const float nSigmaTPC = 3.5, const float nSigmaTPCTOF = 3.5) +{ + bool pidSelection = true; + if (momentum < pidThresh) { + /// TPC PID only + pidSelection = isPIDSelected(pidCut, vSpecies, nSpecies, nSigmaTPC, vNsigma, kDetector::kTPC); + } else { + /// TPC + TOF PID + pidSelection = isPIDSelected(pidCut, vSpecies, nSpecies, nSigmaTPCTOF, vNsigma, kDetector::kTPCTOF); + } + return pidSelection; +}; + +/// function to retrieve the nominal mgnetic field in kG (0.1T) and convert it directly to T +/// \param timestamp timestamp corresponding the the collision +/// \param ccdb CCDB object that contains the configuration for the event +/// \return magnetic field in Tesla + +float getMagneticFieldTesla(const uint64_t& timestamp, const Service& ccdb) +{ + // TODO done only once (and not per run). Will be replaced by CCDBConfigurable + static o2::parameters::GRPObject* grpo = ccdb->getForTimeStamp("GLO/GRP/GRP", timestamp); + if (!grpo) { + LOGF(fatal, "GRP object not found for timestamp %llu", timestamp); + return 0; + } else { + LOGF(info, "Retrieved GRP for timestamp %llu with magnetic field of %d kG", timestamp, grpo->getNominalL3Field()); + } + + return 0.1 * (grpo->getNominalL3Field()); +} + +} // namespace o2::analysis::femtoWorld + +#endif diff --git a/PWGCF/FemtoWorld/DataModel/CMakeLists.txt b/PWGCF/FemtoWorld/DataModel/CMakeLists.txt new file mode 100644 index 00000000000..bbfd7adac2b --- /dev/null +++ b/PWGCF/FemtoWorld/DataModel/CMakeLists.txt @@ -0,0 +1,10 @@ +# Copyright 2019-2020 CERN and copyright holders of ALICE O2. +# See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +# All rights not expressly granted are reserved. +# +# This software is distributed under the terms of the GNU General Public +# License v3 (GPL Version 3), copied verbatim in the file "COPYING". +# +# In applying this license CERN does not waive the privileges and immunities +# granted to it by virtue of its status as an Intergovernmental Organization +# or submit itself to any jurisdiction. diff --git a/PWGCF/FemtoWorld/TableProducer/CMakeLists.txt b/PWGCF/FemtoWorld/TableProducer/CMakeLists.txt new file mode 100644 index 00000000000..bbfd7adac2b --- /dev/null +++ b/PWGCF/FemtoWorld/TableProducer/CMakeLists.txt @@ -0,0 +1,10 @@ +# Copyright 2019-2020 CERN and copyright holders of ALICE O2. +# See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +# All rights not expressly granted are reserved. +# +# This software is distributed under the terms of the GNU General Public +# License v3 (GPL Version 3), copied verbatim in the file "COPYING". +# +# In applying this license CERN does not waive the privileges and immunities +# granted to it by virtue of its status as an Intergovernmental Organization +# or submit itself to any jurisdiction. diff --git a/PWGCF/FemtoWorld/Tasks/CMakeLists.txt b/PWGCF/FemtoWorld/Tasks/CMakeLists.txt new file mode 100644 index 00000000000..77bea9b453b --- /dev/null +++ b/PWGCF/FemtoWorld/Tasks/CMakeLists.txt @@ -0,0 +1,15 @@ +# Copyright 2019-2020 CERN and copyright holders of ALICE O2. +# See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +# All rights not expressly granted are reserved. +# +# This software is distributed under the terms of the GNU General Public +# License v3 (GPL Version 3), copied verbatim in the file "COPYING". +# +# In applying this license CERN does not waive the privileges and immunities +# granted to it by virtue of its status as an Intergovernmental Organization +# or submit itself to any jurisdiction. + +o2physics_add_dpl_workflow(femto-world-pair-track-track + SOURCES femtoWorldPairTaskTrackTrack.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore + COMPONENT_NAME Analysis) diff --git a/PWGCF/FemtoWorld/Tasks/femtoWorldPairTaskTrackTrack.cxx b/PWGCF/FemtoWorld/Tasks/femtoWorldPairTaskTrackTrack.cxx new file mode 100644 index 00000000000..439dc2504b1 --- /dev/null +++ b/PWGCF/FemtoWorld/Tasks/femtoWorldPairTaskTrackTrack.cxx @@ -0,0 +1,257 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +/// \file femtoWorldPairTaskTrackTrack.cxx +/// \brief Tasks that reads the track tables used for the pairing and builds pairs of two tracks +/// \author Andi Mathis, TU München, andreas.mathis@ph.tum.de + +#include "Framework/AnalysisTask.h" +#include "Framework/runDataProcessing.h" +#include "Framework/HistogramRegistry.h" +#include "Framework/ASoAHelpers.h" +#include "Framework/RunningWorkflowInfo.h" +#include "Framework/StepTHn.h" +#include +#include "DataFormatsParameters/GRPObject.h" + +#include "PWGCF/DataModel/FemtoDerived.h" +#include "PWGCF/FemtoWorld/Core/FemtoWorldParticleHisto.h" +#include "PWGCF/FemtoWorld/Core/FemtoWorldEventHisto.h" +#include "PWGCF/FemtoWorld/Core/FemtoWorldPairCleaner.h" +#include "PWGCF/FemtoWorld/Core/FemtoWorldContainer.h" +#include "PWGCF/FemtoWorld/Core/FemtoWorldDetaDphiStar.h" +#include "PWGCF/FemtoWorld/Core/FemtoWorldUtils.h" + +using namespace o2; +using namespace o2::analysis::femtoWorld; +using namespace o2::framework; +using namespace o2::framework::expressions; +using namespace o2::soa; + +namespace +{ +static constexpr int nPart = 2; +static constexpr int nCuts = 5; +static const std::vector partNames{"PartOne", "PartTwo"}; +static const std::vector cutNames{"MaxPt", "PIDthr", "nSigmaTPC", "nSigmaTPCTOF", "MaxP"}; +static const float cutsTable[nPart][nCuts]{ + {4.05f, 1.f, 3.f, 3.f, 100.f}, + {4.05f, 1.f, 3.f, 3.f, 100.f}}; + +static const std::vector kNsigma = {3.5f, 3.f, 2.5f}; + +} // namespace + +struct femtoWorldPairTaskTrackTrack { + + /// Particle selection part + + /// Table for both particles + Configurable> cfgCutTable{"cfgCutTable", {cutsTable[0], nPart, nCuts, partNames, cutNames}, "Particle selections"}; + Configurable cfgNspecies{"ccfgNspecies", 4, "Number of particle spieces with PID info"}; + + /// Particle 1 + Configurable ConfPDGCodePartOne{"ConfPDGCodePartOne", 2212, "Particle 1 - PDG code"}; + Configurable ConfCutPartOne{"ConfCutPartOne", 84035877, "Particle 1 - Selection bit from cutCulator"}; + Configurable> ConfPIDPartOne{"ConfPIDPartOne", std::vector{2}, "Particle 1 - Read from cutCulator"}; // we also need the possibility to specify whether the bit is true/false ->std>>vector>int>> + + /// Partition for particle 1 + Partition partsOne = (aod::femtodreamparticle::partType == uint8_t(aod::femtodreamparticle::ParticleType::kTrack)) && ((aod::femtodreamparticle::cut & ConfCutPartOne) == ConfCutPartOne); + + /// Histogramming for particle 1 + FemtoWorldParticleHisto trackHistoPartOne; + + /// Particle 2 + Configurable ConfIsSame{"ConfIsSame", false, "Pairs of the same particle"}; + Configurable ConfPDGCodePartTwo{"ConfPDGCodePartTwo", 2212, "Particle 2 - PDG code"}; + Configurable ConfCutPartTwo{"ConfCutPartTwo", 84035877, "Particle 2 - Selection bit"}; + Configurable> ConfPIDPartTwo{"ConfPIDPartTwo", std::vector{2}, "Particle 2 - Read from cutCulator"}; // we also need the possibility to specify whether the bit is true/false ->std>>vector> + + /// Partition for particle 2 + Partition partsTwo = (aod::femtodreamparticle::partType == uint8_t(aod::femtodreamparticle::ParticleType::kTrack)) && + // (aod::femtodreamparticle::pt < cfgCutTable->get("PartTwo", "MaxPt")) && + ((aod::femtodreamparticle::cut & ConfCutPartTwo) == ConfCutPartTwo); + + /// Histogramming for particle 2 + FemtoWorldParticleHisto trackHistoPartTwo; + + /// Histogramming for Event + FemtoWorldEventHisto eventHisto; + + /// The configurables need to be passed to an std::vector + std::vector vPIDPartOne, vPIDPartTwo; + + /// Correlation part + // ConfigurableAxis CfgMultBins{"CfgMultBins", {VARIABLE_WIDTH, 0.0f, 4.0f, 8.0f, 12.0f, 16.0f, 20.0f, 24.0f, 28.0f, 32.0f, 36.0f, 40.0f, 44.0f, 48.0f, 52.0f, 56.0f, 60.0f, 64.0f, 68.0f, 72.0f, 76.0f, 80.0f, 84.0f, 88.0f, 92.0f, 96.0f, 100.0f, 200.0f, 99999.f}, "Mixing bins - multiplicity"}; // \todo to be obtained from the hash task + ConfigurableAxis CfgMultBins{"CfgMultBins", {VARIABLE_WIDTH, 0.0f, 20.0f, 40.0f, 60.0f, 80.0f, 100.0f, 200.0f, 99999.f}, "Mixing bins - multiplicity"}; + ConfigurableAxis CfgVtxBins{"CfgVtxBins", {VARIABLE_WIDTH, -10.0f, -8.f, -6.f, -4.f, -2.f, 0.f, 2.f, 4.f, 6.f, 8.f, 10.f}, "Mixing bins - z-vertex"}; + ConfigurableAxis CfgkstarBins{"CfgkstarBins", {1500, 0., 6.}, "binning kstar"}; + ConfigurableAxis CfgkTBins{"CfgkTBins", {150, 0., 9.}, "binning kT"}; + ConfigurableAxis CfgmTBins{"CfgmTBins", {225, 0., 7.5}, "binning mT"}; + Configurable ConfNEventsMix{"ConfNEventsMix", 5, "Number of events for mixing"}; + Configurable ConfIsCPR{"ConfIsCPR", true, "Close Pair Rejection"}; + Configurable ConfCPRPlotPerRadii{"ConfCPRPlotPerRadii", false, "Plot CPR per radii"}; + + FemtoWorldContainer sameEventCont; + + FemtoWorldContainer mixedEventCont; + FemtoWorldPairCleaner pairCleaner; + FemtoWorldDetaDphiStar pairCloseRejection; + /// Histogram output + HistogramRegistry qaRegistry{"TrackQA", {}, OutputObjHandlingPolicy::AnalysisObject}; + HistogramRegistry resultRegistry{"Correlations", {}, OutputObjHandlingPolicy::AnalysisObject}; + + Service ccdb; /// Accessing the CCDB + + void init(InitContext&) + { + eventHisto.init(&qaRegistry); + trackHistoPartOne.init(&qaRegistry); + if (!ConfIsSame) { + trackHistoPartTwo.init(&qaRegistry); + } + + sameEventCont.init(&resultRegistry, CfgkstarBins, CfgMultBins, CfgkTBins, CfgmTBins); + sameEventCont.setPDGCodes(ConfPDGCodePartOne, ConfPDGCodePartTwo); + mixedEventCont.init(&resultRegistry, CfgkstarBins, CfgMultBins, CfgkTBins, CfgmTBins); + mixedEventCont.setPDGCodes(ConfPDGCodePartOne, ConfPDGCodePartTwo); + pairCleaner.init(&qaRegistry); + if (ConfIsCPR) { + pairCloseRejection.init(&resultRegistry, &qaRegistry, 0.01, 0.01, ConfCPRPlotPerRadii); /// \todo add config for Δη and ΔΦ cut values + } + + vPIDPartOne = ConfPIDPartOne; + vPIDPartTwo = ConfPIDPartTwo; + + /// Initializing CCDB + ccdb->setURL("http://alice-ccdb.cern.ch"); + ccdb->setCaching(true); + ccdb->setLocalObjectValidityChecking(); + + long now = std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()).count(); + ccdb->setCreatedNotAfter(now); + } + + /// This function processes the same event and takes care of all the histogramming + /// \todo the trivial loops over the tracks should be factored out since they will be common to all combinations of T-T, T-V0, V0-V0, ... + void processSameEvent(o2::aod::FemtoDreamCollision& col, + o2::aod::FemtoDreamParticles& parts) + { + const auto& tmstamp = col.timestamp(); + const auto& magFieldTesla = getMagneticFieldTesla(tmstamp, ccdb); + + auto groupPartsOne = partsOne->sliceByCached(aod::femtodreamparticle::femtoDreamCollisionId, col.globalIndex()); + + auto groupPartsTwo = partsTwo->sliceByCached(aod::femtodreamparticle::femtoDreamCollisionId, col.globalIndex()); + + const int multCol = col.multV0M(); + eventHisto.fillQA(col); + /// Histogramming same event + for (auto& part : groupPartsOne) { + if (part.p() > cfgCutTable->get("PartOne", "MaxP") || part.pt() > cfgCutTable->get("PartOne", "MaxPt")) { + continue; + } + if (!isFullPIDSelected(part.pidcut(), part.p(), cfgCutTable->get("PartOne", "PIDthr"), vPIDPartOne, cfgNspecies, kNsigma, cfgCutTable->get("PartOne", "nSigmaTPC"), cfgCutTable->get("PartOne", "nSigmaTPCTOF"))) { + continue; + } + trackHistoPartOne.fillQA(part); + } + if (!ConfIsSame) { + for (auto& part : groupPartsTwo) { + if (part.p() > cfgCutTable->get("PartTwo", "MaxP") || part.pt() > cfgCutTable->get("PartTwo", "MaxPt")) { + continue; + } + if (!isFullPIDSelected(part.pidcut(), part.p(), cfgCutTable->get("PartTwo", "PIDthr"), vPIDPartTwo, cfgNspecies, kNsigma, cfgCutTable->get("PartTwo", "nSigmaTPC"), cfgCutTable->get("PartTwo", "nSigmaTPCTOF"))) { + continue; + } + trackHistoPartTwo.fillQA(part); + } + } + /// Now build the combinations + for (auto& [p1, p2] : combinations(groupPartsOne, groupPartsTwo)) { + if (p1.p() > cfgCutTable->get("PartOne", "MaxP") || p1.pt() > cfgCutTable->get("PartOne", "MaxPt") || p2.p() > cfgCutTable->get("PartTwo", "MaxP") || p2.pt() > cfgCutTable->get("PartTwo", "MaxPt")) { + continue; + } + if (!isFullPIDSelected(p1.pidcut(), p1.p(), cfgCutTable->get("PartOne", "PIDthr"), vPIDPartOne, cfgNspecies, kNsigma, cfgCutTable->get("PartOne", "nSigmaTPC"), cfgCutTable->get("PartOne", "nSigmaTPCTOF")) || !isFullPIDSelected(p2.pidcut(), p2.p(), cfgCutTable->get("PartTwo", "PIDthr"), vPIDPartTwo, cfgNspecies, kNsigma, cfgCutTable->get("PartTwo", "nSigmaTPC"), cfgCutTable->get("PartTwo", "nSigmaTPCTOF"))) { + continue; + } + + if (ConfIsCPR) { + if (pairCloseRejection.isClosePair(p1, p2, parts, magFieldTesla)) { + continue; + } + } + + // track cleaning + if (!pairCleaner.isCleanPair(p1, p2, parts)) { + continue; + } + sameEventCont.setPair(p1, p2, multCol); + } + } + + PROCESS_SWITCH(femtoWorldPairTaskTrackTrack, processSameEvent, "Enable processing same event", true); + + /// This function processes the mixed event + /// \todo the trivial loops over the collisions and tracks should be factored out since they will be common to all combinations of T-T, T-V0, V0-V0, ... + void processMixedEvent(o2::aod::FemtoDreamCollisions& cols, + o2::aod::FemtoDreamParticles& parts) + { + + BinningPolicy colBinning{{CfgVtxBins, CfgMultBins}, true}; + + for (auto& [collision1, collision2] : soa::selfCombinations(colBinning, 5, -1, cols, cols)) { + + auto groupPartsOne = partsOne->sliceByCached(aod::femtodreamparticle::femtoDreamCollisionId, collision1.globalIndex()); + + auto groupPartsTwo = partsTwo->sliceByCached(aod::femtodreamparticle::femtoDreamCollisionId, collision2.globalIndex()); + + const auto& tmstamp1 = collision1.timestamp(); + const auto& magFieldTesla1 = getMagneticFieldTesla(tmstamp1, ccdb); + + const auto& tmstamp2 = collision2.timestamp(); + const auto& magFieldTesla2 = getMagneticFieldTesla(tmstamp2, ccdb); + + if (magFieldTesla1 != magFieldTesla2) { + continue; + } + + /// \todo before mixing we should check whether both collisions contain a pair of particles! + // if (partsOne.size() == 0 || nPart2Evt1 == 0 || nPart1Evt2 == 0 || partsTwo.size() == 0 ) continue; + + for (auto& [p1, p2] : combinations(CombinationsFullIndexPolicy(groupPartsOne, groupPartsTwo))) { + if (p1.p() > cfgCutTable->get("PartOne", "MaxP") || p1.pt() > cfgCutTable->get("PartOne", "MaxPt") || p2.p() > cfgCutTable->get("PartTwo", "MaxP") || p2.pt() > cfgCutTable->get("PartTwo", "MaxPt")) { + continue; + } + if (!isFullPIDSelected(p1.pidcut(), p1.p(), cfgCutTable->get("PartOne", "PIDthr"), vPIDPartOne, cfgNspecies, kNsigma, cfgCutTable->get("PartOne", "nSigmaTPC"), cfgCutTable->get("PartOne", "nSigmaTPCTOF")) || !isFullPIDSelected(p2.pidcut(), p2.p(), cfgCutTable->get("PartTwo", "PIDthr"), vPIDPartTwo, cfgNspecies, kNsigma, cfgCutTable->get("PartTwo", "nSigmaTPC"), cfgCutTable->get("PartTwo", "nSigmaTPCTOF"))) { + continue; + } + + if (ConfIsCPR) { + if (pairCloseRejection.isClosePair(p1, p2, parts, magFieldTesla1)) { + continue; + } + } + mixedEventCont.setPair(p1, p2, collision1.multV0M()); + } + } + } + + PROCESS_SWITCH(femtoWorldPairTaskTrackTrack, processMixedEvent, "Enable processing mixed events", true); +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + WorkflowSpec workflow{ + adaptAnalysisTask(cfgc), + }; + return workflow; +} From 817e57bc36debd217f2fa626689c9bd4584540bd Mon Sep 17 00:00:00 2001 From: Mattia Faggin Date: Mon, 25 Jul 2022 13:30:59 +0200 Subject: [PATCH 31/31] DPG: add per-event qa plots for mismatched tracks (MC). (#1050) Co-authored-by: Mattia Faggin --- DPG/Tasks/qaEventTrack.cxx | 54 +++++++++++++++++++++++++++----------- 1 file changed, 39 insertions(+), 15 deletions(-) diff --git a/DPG/Tasks/qaEventTrack.cxx b/DPG/Tasks/qaEventTrack.cxx index 0aac0158e18..e5bde3fba99 100644 --- a/DPG/Tasks/qaEventTrack.cxx +++ b/DPG/Tasks/qaEventTrack.cxx @@ -269,6 +269,7 @@ struct qaEventTrack { } /// check correct track-to-vertex matching exploiting MC info + std::vector vec_coll_index_mismatched = {}; for (auto& track : tracks) { histos.fill(HIST("Tracks/TestMCtrackToVtxMatch/ptAllTracks"), track.pt()); bool has_MCparticle = track.has_mcParticle(); @@ -302,6 +303,20 @@ struct qaEventTrack { } else { histos.fill(HIST("Tracks/TestMCtrackToVtxMatch/ptVsDpvZbadMatchMaterial"), pvZdiff, track.pt()); } + /// event properties for collisions containing mismathced tracks + auto it = std::find(vec_coll_index_mismatched.begin(), vec_coll_index_mismatched.end(), collReco.globalIndex()); + if (it == vec_coll_index_mismatched.end()) { + /// collision not yet considered, fill the distributions + // LOG(info) << "===> collision " << collReco.globalIndex() << " not found yet! Fill the distributions"; + // LOG(info) << " vector dim: " << vec_coll_index_mismatched.size(); + const double nTracksInColl = tracks.sliceBy(perRecoCollision, collReco.globalIndex()).size(); + histos.fill(HIST("Tracks/TestMCtrackToVtxMatch/hPVxCollWithMismTrk"), collReco.posX()); + histos.fill(HIST("Tracks/TestMCtrackToVtxMatch/hPVyCollWithMismTrk"), collReco.posY()); + histos.fill(HIST("Tracks/TestMCtrackToVtxMatch/hPVzCollWithMismTrk"), collReco.posZ()); + histos.fill(HIST("Tracks/TestMCtrackToVtxMatch/hPVcontrCollWithMismTrk"), collReco.numContrib()); + histos.fill(HIST("Tracks/TestMCtrackToVtxMatch/hNTracksCollWithMismTrk"), nTracksInColl); + vec_coll_index_mismatched.push_back(collReco.globalIndex()); + } } } @@ -556,21 +571,30 @@ void qaEventTrack::init(InitContext const&) histos.add("Tracks/KineUnmatchTracks/eta", "#eta", kTH1D, {axisEta}); histos.add("Tracks/KineUnmatchTracks/phi", "#varphi", kTH1D, {axisPhi}); - /// check correct track-to-vertex matching - histos.add("Tracks/TestMCtrackToVtxMatch/ptAllTracks", "all tracks (MC)", kTH1D, {axisPt}); - histos.add("Tracks/TestMCtrackToVtxMatch/ptAllTracksInColl", "all tracks in collision (MC)", kTH1D, {axisPt}); - histos.add("Tracks/TestMCtrackToVtxMatch/ptAllTracksWoColl", "all tracks w/o collision (MC)", kTH1D, {axisPt}); - auto hUnmatched = histos.add("Tracks/TestMCtrackToVtxMatch/ptVsOriginUnmatchedwithMCpart", "tracks with part. not matched to reco. coll. (MC)", kTH2D, {{4, -1.5, 2.5}, axisPt}); - hUnmatched->GetXaxis()->SetBinLabel(hUnmatched->GetXaxis()->FindBin(-1.), "not found"); - hUnmatched->GetXaxis()->SetBinLabel(hUnmatched->GetXaxis()->FindBin(0.), "Phys. prim."); - hUnmatched->GetXaxis()->SetBinLabel(hUnmatched->GetXaxis()->FindBin(1.), "Secondary"); - hUnmatched->GetXaxis()->SetBinLabel(hUnmatched->GetXaxis()->FindBin(2.), "Material"); - histos.add("Tracks/TestMCtrackToVtxMatch/ptVsDpvZgoodMatchPhysPrim", "good track-to-vtx matching phys. prim. (MC)", kTH2D, {{100, -0.1, 0.1, "pvZ(reco coll.) - pvZ(MC coll.)"}, axisPt}); - histos.add("Tracks/TestMCtrackToVtxMatch/ptVsDpvZbadMatchPhysPrim", "bad track-to-vtx matching phys. prim. (MC)", kTH2D, {{100, -0.1, 0.1, "pvZ(reco coll.) - pvZ(MC coll.)"}, axisPt}); - histos.add("Tracks/TestMCtrackToVtxMatch/ptVsDpvZgoodMatchSecondary", "good track-to-vtx matching secondary (MC)", kTH2D, {{100, -0.1, 0.1, "pvZ(reco coll.) - pvZ(MC coll.)"}, axisPt}); - histos.add("Tracks/TestMCtrackToVtxMatch/ptVsDpvZbadMatchSecondary", "bad track-to-vtx matching secondary (MC)", kTH2D, {{100, -0.1, 0.1, "pvZ(reco coll.) - pvZ(MC coll.)"}, axisPt}); - histos.add("Tracks/TestMCtrackToVtxMatch/ptVsDpvZgoodMatchMaterial", "good track-to-vtx matching material (MC)", kTH2D, {{100, -0.1, 0.1, "pvZ(reco coll.) - pvZ(MC coll.)"}, axisPt}); - histos.add("Tracks/TestMCtrackToVtxMatch/ptVsDpvZbadMatchMaterial", "bad track-to-vtx matching material (MC)", kTH2D, {{100, -0.1, 0.1, "pvZ(reco coll.) - pvZ(MC coll.)"}, axisPt}); + /// check correct track-to-vertex matching (MC) + if (doprocessMC) { + histos.add("Tracks/TestMCtrackToVtxMatch/ptAllTracks", "all tracks (MC)", kTH1D, {axisPt}); + histos.add("Tracks/TestMCtrackToVtxMatch/ptAllTracksInColl", "all tracks in collision (MC)", kTH1D, {axisPt}); + histos.add("Tracks/TestMCtrackToVtxMatch/ptAllTracksWoColl", "all tracks w/o collision (MC)", kTH1D, {axisPt}); + auto hUnmatched = histos.add("Tracks/TestMCtrackToVtxMatch/ptVsOriginUnmatchedwithMCpart", "tracks with part. not matched to reco. coll. (MC)", kTH2D, {{4, -1.5, 2.5}, axisPt}); + hUnmatched->GetXaxis()->SetBinLabel(hUnmatched->GetXaxis()->FindBin(-1.), "not found"); + hUnmatched->GetXaxis()->SetBinLabel(hUnmatched->GetXaxis()->FindBin(0.), "Phys. prim."); + hUnmatched->GetXaxis()->SetBinLabel(hUnmatched->GetXaxis()->FindBin(1.), "Secondary"); + hUnmatched->GetXaxis()->SetBinLabel(hUnmatched->GetXaxis()->FindBin(2.), "Material"); + histos.add("Tracks/TestMCtrackToVtxMatch/ptVsDpvZgoodMatchPhysPrim", "good track-to-vtx matching phys. prim. (MC)", kTH2D, {{100, -0.1, 0.1, "pvZ(reco coll.) - pvZ(MC coll.)"}, axisPt}); + histos.add("Tracks/TestMCtrackToVtxMatch/ptVsDpvZbadMatchPhysPrim", "bad track-to-vtx matching phys. prim. (MC)", kTH2D, {{100, -0.1, 0.1, "pvZ(reco coll.) - pvZ(MC coll.)"}, axisPt}); + histos.add("Tracks/TestMCtrackToVtxMatch/ptVsDpvZgoodMatchSecondary", "good track-to-vtx matching secondary (MC)", kTH2D, {{100, -0.1, 0.1, "pvZ(reco coll.) - pvZ(MC coll.)"}, axisPt}); + histos.add("Tracks/TestMCtrackToVtxMatch/ptVsDpvZbadMatchSecondary", "bad track-to-vtx matching secondary (MC)", kTH2D, {{100, -0.1, 0.1, "pvZ(reco coll.) - pvZ(MC coll.)"}, axisPt}); + histos.add("Tracks/TestMCtrackToVtxMatch/ptVsDpvZgoodMatchMaterial", "good track-to-vtx matching material (MC)", kTH2D, {{100, -0.1, 0.1, "pvZ(reco coll.) - pvZ(MC coll.)"}, axisPt}); + histos.add("Tracks/TestMCtrackToVtxMatch/ptVsDpvZbadMatchMaterial", "bad track-to-vtx matching material (MC)", kTH2D, {{100, -0.1, 0.1, "pvZ(reco coll.) - pvZ(MC coll.)"}, axisPt}); + + // event properties for collisions containing mismathced tracks + histos.add("Tracks/TestMCtrackToVtxMatch/hPVxCollWithMismTrk", "x coordinate of PV for collisions containing a mismatched track;;counts;", kTH1D, {axisVertexPosX}); + histos.add("Tracks/TestMCtrackToVtxMatch/hPVyCollWithMismTrk", "y coordinate of PV for collisions containing a mismatched track;;counts;", kTH1D, {axisVertexPosY}); + histos.add("Tracks/TestMCtrackToVtxMatch/hPVzCollWithMismTrk", "z coordinate of PV for collisions containing a mismatched track;;counts;", kTH1D, {axisVertexPosZ}); + histos.add("Tracks/TestMCtrackToVtxMatch/hPVcontrCollWithMismTrk", "number of PV contributors for collisions containing a mismatched track;;counts;", kTH1D, {axisVertexNumContrib}); + histos.add("Tracks/TestMCtrackToVtxMatch/hNTracksCollWithMismTrk", "number of tracks for collisions containing a mismatched track;;counts;", kTH1D, {axisTrackMultiplicity}); + } // track histograms auto hselAxis = histos.add("Tracks/selection", "trackSelection", kTH1F, {{40, 0.5, 40.5}})->GetXaxis();