From ba99301f546c9617239476bc1857c52ee4dea1c5 Mon Sep 17 00:00:00 2001 From: Marvin Hemmer Date: Wed, 23 Jul 2025 16:10:52 +0200 Subject: [PATCH] [PWGJE,EMCAL-689] Add DeltaEta and DeltaPhi values to `EMCALMatchedTracks` table - Add DeltaEta and DeltaPhi values to `EMCALMatchedTracks` table - Add PWGJE/Core/utilsTrackMatchingEMC.h where we do simple track matching. Previously we used the jetutils which matched tracks to clusters and clusters to track both. To save time we now use our own utils header and do only one. Also to make the code more easily understandble added struct `MatchResult` instead of using a complex tuple of vector abomination. - Fix PWGJE/Tasks/emcTmMonitor.cxx O2linter warnings and includes --- PWGJE/Core/CMakeLists.txt | 1 + PWGJE/Core/JetUtilities.h | 5 - PWGJE/Core/utilsTrackMatchingEMC.h | 119 ++++++ PWGJE/DataModel/EMCALClusters.h | 9 +- PWGJE/TableProducer/emcalCorrectionTask.cxx | 77 ++-- PWGJE/Tasks/emcTmMonitor.cxx | 452 ++++++++++---------- 6 files changed, 387 insertions(+), 276 deletions(-) create mode 100644 PWGJE/Core/utilsTrackMatchingEMC.h diff --git a/PWGJE/Core/CMakeLists.txt b/PWGJE/Core/CMakeLists.txt index 7eb4bc8ea97..b6ccafb2be2 100644 --- a/PWGJE/Core/CMakeLists.txt +++ b/PWGJE/Core/CMakeLists.txt @@ -25,5 +25,6 @@ o2physics_target_root_dictionary(PWGJECore JetBkgSubUtils.h JetDerivedDataUtilities.h emcalCrossTalkEmulation.h + utilsTrackMatchingEMC.h LINKDEF PWGJECoreLinkDef.h) endif() diff --git a/PWGJE/Core/JetUtilities.h b/PWGJE/Core/JetUtilities.h index 358e1d1dd46..0efaf1fd8f9 100644 --- a/PWGJE/Core/JetUtilities.h +++ b/PWGJE/Core/JetUtilities.h @@ -76,11 +76,6 @@ std::tuple>, std::vector>> MatchCl throw std::invalid_argument("track collection eta and phi sizes don't match. Check the inputs."); } - // for (std::size_t iTrack = 0; iTrack < nTracks; iTrack++) { - // if (trackEta[iTrack] == 0) - // LOG(warning) << "Track eta is 0!"; - // } - // Build the KD-trees using vectors // We build two trees: // treeBase, which contains the base collection. diff --git a/PWGJE/Core/utilsTrackMatchingEMC.h b/PWGJE/Core/utilsTrackMatchingEMC.h new file mode 100644 index 00000000000..6256c712ff3 --- /dev/null +++ b/PWGJE/Core/utilsTrackMatchingEMC.h @@ -0,0 +1,119 @@ +// 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 utilsTrackMatchingEMC.h +/// \brief EMCal track matching related utils +/// \author Marvin Hemmer + +#ifndef PWGJE_CORE_UTILSTRACKMATCHINGEMC_H_ +#define PWGJE_CORE_UTILSTRACKMATCHINGEMC_H_ + +#include + +#include +#include +#include +#include +#include +#include +#include + +namespace tmemcutilities +{ + +struct MatchResult { + std::vector> matchIndexTrack; + std::vector> matchDeltaPhi; + std::vector> matchDeltaEta; +}; + +/** + * Match clusters and tracks. + * + * Match cluster with tracks, where maxNumberMatches are considered in dR=maxMatchingDistance. + * If no unique match was found for a jet, an index of -1 is stored. + * The same map is created for clusters matched to tracks e.g. for electron analyses. + * + * @param clusterPhi cluster collection phi. + * @param clusterEta cluster collection eta. + * @param trackPhi track collection phi. + * @param trackEta track collection eta. + * @param maxMatchingDistance Maximum matching distance. + * @param maxNumberMatches Maximum number of matches (e.g. 5 closest). + * + * @returns (cluster to track index map, track to cluster index map) + */ +MatchResult matchTracksToCluster( + std::span clusterPhi, + std::span clusterEta, + std::span trackPhi, + std::span trackEta, + double maxMatchingDistance, + int maxNumberMatches) +{ + const std::size_t nClusters = clusterEta.size(); + const std::size_t nTracks = trackEta.size(); + MatchResult result; + + result.matchIndexTrack.resize(nClusters); + result.matchDeltaPhi.resize(nClusters); + result.matchDeltaEta.resize(nClusters); + + if (nClusters == 0 || nTracks == 0) { + // There are no jets, so nothing to be done. + return result; + } + // Input sizes must match + if (clusterPhi.size() != clusterEta.size()) { + throw std::invalid_argument("cluster collection eta and phi sizes don't match. Check the inputs."); + } + if (trackPhi.size() != trackEta.size()) { + throw std::invalid_argument("track collection eta and phi sizes don't match. Check the inputs."); + } + + // Build the KD-trees using vectors + // We build two trees: + // treeBase, which contains the base collection. + // treeTag, which contains the tag collection. + // The trees are built to match in two dimensions (eta, phi) + TKDTree treeTrack(trackEta.size(), 2, 1); + treeTrack.SetData(0, trackEta.data()); + treeTrack.SetData(1, trackPhi.data()); + treeTrack.Build(); + + // Find the track closest to each cluster. + for (std::size_t iCluster = 0; iCluster < nClusters; iCluster++) { + float point[2] = {clusterEta[iCluster], clusterPhi[iCluster]}; + int index[50]; // size 50 for safety + float distance[50]; // size 50 for safery + std::fill_n(index, 50, -1); + std::fill_n(distance, 50, std::numeric_limits::max()); + treeTrack.FindNearestNeighbors(point, maxNumberMatches, index, distance); + + // allocate enough memory + result.matchIndexTrack[iCluster].reserve(maxNumberMatches); + result.matchDeltaPhi[iCluster].reserve(maxNumberMatches); + result.matchDeltaEta[iCluster].reserve(maxNumberMatches); + + // test whether indices are matching: + for (int m = 0; m < maxNumberMatches; m++) { + if (index[m] >= 0 && distance[m] < maxMatchingDistance) { + result.matchIndexTrack[iCluster].push_back(index[m]); + result.matchDeltaPhi[iCluster].push_back(trackPhi[index[m]] - clusterPhi[iCluster]); + result.matchDeltaEta[iCluster].push_back(trackEta[index[m]] - clusterEta[iCluster]); + } + } + } + return result; +} +}; // namespace tmemcutilities + +#endif // PWGJE_CORE_UTILSTRACKMATCHINGEMC_H_ diff --git a/PWGJE/DataModel/EMCALClusters.h b/PWGJE/DataModel/EMCALClusters.h index ca42b0ae68e..56edf634628 100644 --- a/PWGJE/DataModel/EMCALClusters.h +++ b/PWGJE/DataModel/EMCALClusters.h @@ -162,10 +162,13 @@ using EMCALClusterCell = EMCALClusterCells::iterator; using EMCALAmbiguousClusterCell = EMCALAmbiguousClusterCells::iterator; namespace emcalmatchedtrack { -DECLARE_SOA_INDEX_COLUMN(Track, track); //! linked to Track table only for tracks that were matched +DECLARE_SOA_INDEX_COLUMN(Track, track); //! linked to Track table only for tracks that were matched +DECLARE_SOA_COLUMN(DeltaPhi, deltaPhi, float); //! difference between matched track and cluster azimuthal angle +DECLARE_SOA_COLUMN(DeltaEta, deltaEta, float); //! difference between matched track and cluster pseudorapidity } // namespace emcalmatchedtrack -DECLARE_SOA_TABLE(EMCALMatchedTracks, "AOD", "EMCMATCHTRACKS", //! - o2::soa::Index<>, emcalclustercell::EMCALClusterId, emcalmatchedtrack::TrackId); //! +DECLARE_SOA_TABLE(EMCALMatchedTracks, "AOD", "EMCMATCHTRACKS", //! + o2::soa::Index<>, emcalclustercell::EMCALClusterId, emcalmatchedtrack::TrackId, + emcalmatchedtrack::DeltaPhi, emcalmatchedtrack::DeltaEta); //! using EMCALMatchedTrack = EMCALMatchedTracks::iterator; } // namespace o2::aod #endif // PWGJE_DATAMODEL_EMCALCLUSTERS_H_ diff --git a/PWGJE/TableProducer/emcalCorrectionTask.cxx b/PWGJE/TableProducer/emcalCorrectionTask.cxx index 33efa53dad7..72f7941fa9e 100644 --- a/PWGJE/TableProducer/emcalCorrectionTask.cxx +++ b/PWGJE/TableProducer/emcalCorrectionTask.cxx @@ -18,12 +18,13 @@ /// \author Raymond Ehlers (raymond.ehlers@cern.ch) ORNL, Florian Jonas (florian.jonas@cern.ch) /// -#include "PWGJE/Core/JetUtilities.h" #include "PWGJE/Core/emcalCrossTalkEmulation.h" +#include "PWGJE/Core/utilsTrackMatchingEMC.h" #include "PWGJE/DataModel/EMCALClusterDefinition.h" #include "PWGJE/DataModel/EMCALClusters.h" #include "PWGJE/DataModel/EMCALMatchedCollisions.h" +#include "Common/Core/RecoDecay.h" #include "Common/DataModel/EventSelection.h" #include "Common/DataModel/TrackSelectionTables.h" @@ -65,6 +66,7 @@ #include #include #include +#include #include #include #include @@ -76,6 +78,7 @@ using namespace o2; using namespace o2::framework; using namespace o2::framework::expressions; using namespace o2::emccrosstalk; +using namespace tmemcutilities; using MyGlobTracks = o2::soa::Join; using BcEvSels = o2::soa::Join; using CollEventSels = o2::soa::Join; @@ -83,6 +86,13 @@ using FilteredCells = o2::soa::Filtered; using McCells = o2::soa::Join; using FilteredMcCells = o2::soa::Filtered; +enum CellScaleMode { + ModeNone = 0, + ModeSMWise = 1, + ModeColumnWise = 2, + NumberModes = 3 +}; + struct EmcalCorrectionTask { Produces clusters; Produces mcclusters; @@ -442,9 +452,9 @@ struct EmcalCorrectionTask { std::vector> clusterToTrackIndexMap; std::vector> trackToClusterIndexMap; - std::tuple>, std::vector>> indexMapPair{clusterToTrackIndexMap, trackToClusterIndexMap}; + MatchResult indexMapPair; std::vector trackGlobalIndex; - doTrackMatching(col, tracks, indexMapPair, vertexPos, trackGlobalIndex); + doTrackMatching(col, tracks, indexMapPair, trackGlobalIndex); // Store the clusters in the table where a matching collision could // be identified. @@ -612,9 +622,9 @@ struct EmcalCorrectionTask { std::vector> clusterToTrackIndexMap; std::vector> trackToClusterIndexMap; - std::tuple>, std::vector>> indexMapPair{clusterToTrackIndexMap, trackToClusterIndexMap}; + MatchResult indexMapPair; std::vector trackGlobalIndex; - doTrackMatching(col, tracks, indexMapPair, vertexPos, trackGlobalIndex); + doTrackMatching(col, tracks, indexMapPair, trackGlobalIndex); // Store the clusters in the table where a matching collision could // be identified. @@ -798,16 +808,16 @@ struct EmcalCorrectionTask { } template - void fillClusterTable(Collision const& col, math_utils::Point3D const& vertexPos, size_t iClusterizer, const gsl::span cellIndicesBC, const std::tuple>, std::vector>>* indexMapPair = nullptr, const std::vector* trackGlobalIndex = nullptr) + void fillClusterTable(Collision const& col, math_utils::Point3D const& vertexPos, size_t iClusterizer, const gsl::span cellIndicesBC, MatchResult* indexMapPair = nullptr, const std::vector* trackGlobalIndex = nullptr) { // average number of cells per cluster, only used the reseve a reasonable amount for the clustercells table - const size_t NAvgNcells = 3; + const size_t nAvgNcells = 3; // we found a collision, put the clusters into the none ambiguous table clusters.reserve(mAnalysisClusters.size()); if (!mClusterLabels.empty()) { mcclusters.reserve(mClusterLabels.size()); } - clustercells.reserve(mAnalysisClusters.size() * NAvgNcells); + clustercells.reserve(mAnalysisClusters.size() * nAvgNcells); // get the clusterType once const auto clusterType = static_cast(mClusterDefinitions[iClusterizer]); @@ -867,10 +877,10 @@ struct EmcalCorrectionTask { mHistManager.fill(HIST("hClusterFCrossSigmaShortE"), cluster.E(), cluster.getFCross(), cluster.getM20()); } if (indexMapPair && trackGlobalIndex) { - for (unsigned int iTrack = 0; iTrack < std::get<0>(*indexMapPair)[iCluster].size(); iTrack++) { - if (std::get<0>(*indexMapPair)[iCluster][iTrack] >= 0) { - LOG(debug) << "Found track " << (*trackGlobalIndex)[std::get<0>(*indexMapPair)[iCluster][iTrack]] << " in cluster " << cluster.getID(); - matchedTracks(clusters.lastIndex(), (*trackGlobalIndex)[std::get<0>(*indexMapPair)[iCluster][iTrack]]); + for (unsigned int iTrack = 0; iTrack < indexMapPair->matchIndexTrack[iCluster].size(); iTrack++) { + if (indexMapPair->matchIndexTrack[iCluster][iTrack] >= 0) { + LOG(debug) << "Found track " << (*trackGlobalIndex)[indexMapPair->matchIndexTrack[iCluster][iTrack]] << " in cluster " << cluster.getID(); + matchedTracks(clusters.lastIndex(), (*trackGlobalIndex)[indexMapPair->matchIndexTrack[iCluster][iTrack]], indexMapPair->matchDeltaPhi[iCluster][iTrack], indexMapPair->matchDeltaEta[iCluster][iTrack]); } } } @@ -882,13 +892,13 @@ struct EmcalCorrectionTask { void fillAmbigousClusterTable(BC const& bc, size_t iClusterizer, const gsl::span cellIndicesBC, bool hasCollision) { // average number of cells per cluster, only used the reseve a reasonable amount for the clustercells table - const size_t NAvgNcells = 3; + const size_t nAvgNcells = 3; int cellindex = -1; clustersAmbiguous.reserve(mAnalysisClusters.size()); if (mClusterLabels.size() > 0) { mcclustersAmbiguous.reserve(mClusterLabels.size()); } - clustercellsambiguous.reserve(mAnalysisClusters.size() * NAvgNcells); + clustercellsambiguous.reserve(mAnalysisClusters.size() * nAvgNcells); unsigned int iCluster = 0; float energy = 0.f; for (const auto& cluster : mAnalysisClusters) { @@ -933,12 +943,12 @@ struct EmcalCorrectionTask { } template - void doTrackMatching(Collision const& col, MyGlobTracks const& tracks, std::tuple>, std::vector>>& indexMapPair, math_utils::Point3D& vertexPos, std::vector& trackGlobalIndex) + void doTrackMatching(Collision const& col, MyGlobTracks const& tracks, MatchResult& indexMapPair, std::vector& trackGlobalIndex) { auto groupedTracks = tracks.sliceBy(perCollision, col.globalIndex()); int nTracksInCol = groupedTracks.size(); - std::vector trackPhi; - std::vector trackEta; + std::vector trackPhi; + std::vector trackEta; // reserve memory to reduce on the fly memory allocation trackPhi.reserve(nTracksInCol); trackEta.reserve(nTracksInCol); @@ -946,8 +956,8 @@ struct EmcalCorrectionTask { fillTrackInfo(groupedTracks, trackPhi, trackEta, trackGlobalIndex); int nClusterInCol = mAnalysisClusters.size(); - std::vector clusterPhi; - std::vector clusterEta; + std::vector clusterPhi; + std::vector clusterEta; clusterPhi.reserve(nClusterInCol); clusterEta.reserve(nClusterInCol); @@ -957,20 +967,14 @@ struct EmcalCorrectionTask { // Determine the cluster eta, phi, correcting for the vertex // position. auto pos = cluster.getGlobalPosition(); - pos = pos - vertexPos; - // Normalize the vector and rescale by energy. - pos *= (cluster.E() / std::sqrt(pos.Mag2())); clusterPhi.emplace_back(TVector2::Phi_0_2pi(pos.Phi())); clusterEta.emplace_back(pos.Eta()); } - indexMapPair = - jetutilities::MatchClustersAndTracks(clusterPhi, clusterEta, - trackPhi, trackEta, - maxMatchingDistance, 20); + indexMapPair = matchTracksToCluster(clusterPhi, clusterEta, trackPhi, trackEta, maxMatchingDistance, 20); } template - void fillTrackInfo(Tracks const& tracks, std::vector& trackPhi, std::vector& trackEta, std::vector& trackGlobalIndex) + void fillTrackInfo(Tracks const& tracks, std::vector& trackPhi, std::vector& trackEta, std::vector& trackGlobalIndex) { int nTrack = 0; for (const auto& track : tracks) { @@ -986,10 +990,10 @@ struct EmcalCorrectionTask { continue; } nTrack++; - trackPhi.emplace_back(TVector2::Phi_0_2pi(track.trackPhiEmcal())); + trackPhi.emplace_back(RecoDecay::constrainAngle(track.trackPhiEmcal())); trackEta.emplace_back(track.trackEtaEmcal()); mHistManager.fill(HIST("hGlobalTrackEtaPhi"), track.trackEtaEmcal(), - TVector2::Phi_0_2pi(track.trackPhiEmcal())); + RecoDecay::constrainAngle(track.trackPhiEmcal())); trackGlobalIndex.emplace_back(track.globalIndex()); } mHistManager.fill(HIST("hGlobalTrackMult"), nTrack); @@ -1040,12 +1044,12 @@ struct EmcalCorrectionTask { { // Apply cell scale based on SM types (Full, Half (not used), EMC 1/3, DCal, DCal 1/3) // Same as in Run2 data - if (applyCellAbsScale == 1) { + if (applyCellAbsScale == CellScaleMode::ModeSMWise) { int iSM = mClusterizers.at(0)->getGeometry()->GetSuperModuleNumber(cellID); return cellAbsScaleFactors.value[mClusterizers.at(0)->getGeometry()->GetSMType(iSM)]; // Apply cell scale based on columns to accoutn for material of TRD structures - } else if (applyCellAbsScale == 2) { + } else if (applyCellAbsScale == CellScaleMode::ModeColumnWise) { auto res = mClusterizers.at(0)->getGeometry()->GlobalRowColFromIndex(cellID); return cellAbsScaleFactors.value[std::get<1>(res)]; } else { @@ -1063,6 +1067,9 @@ struct EmcalCorrectionTask { } float timeshift = 0.f; float timesmear = 0.f; + const float minLeaderEnergy = 0.3f; + const float lowEnergyRegime = 4.f; + const float highEnergyRegime = 30.f; if (isMC) { // ---> MC // Shift the time to 0, as the TOF was simulated -> eta dependent shift (as larger eta values are further away from collision point) // Use distance between vertex and EMCal (at eta = 0) and distance on EMCal surface (cell size times column) to calculate distance to cell @@ -1071,7 +1078,7 @@ struct EmcalCorrectionTask { timeshift = -std::sqrt(215.f + timeCol * timeCol); // 215 is 14.67ns^2 (time it takes to get the cell at eta = 0) // Also smear the time to account for the broader time resolution in data than in MC - if (cellEnergy < 0.3) // Cells with tless than 300 MeV cannot be the leading cell in the cluster, so their time does not require precise calibration + if (cellEnergy < minLeaderEnergy) // Cells with tless than 300 MeV cannot be the leading cell in the cluster, so their time does not require precise calibration timesmear = 0.; // They will therefore not be smeared and only get their shift else if (cellType == emcal::ChannelType_t::HIGH_GAIN) // High gain cells -> Low energies timesmear = normalgaus(rdgen) * (1.6 + 9.5 * std::exp(-3. * cellEnergy)); // Parameters extracted from LHC24f3b & LHC22o (pp), but also usable for other periods @@ -1079,15 +1086,15 @@ struct EmcalCorrectionTask { timesmear = normalgaus(rdgen) * (5.0); // Parameters extracted from LHC24g4 & LHC24aj (pp), but also usable for other periods } else { // ---> Data - if (cellEnergy < 0.3) { // Cells with tless than 300 MeV cannot be the leading cell in the cluster, so their time does not require precise calibration + if (cellEnergy < minLeaderEnergy) { // Cells with tless than 300 MeV cannot be the leading cell in the cluster, so their time does not require precise calibration timeshift = 0.; // In data they will not be shifted (they are close to 0 anyways) } else if (cellType == emcal::ChannelType_t::HIGH_GAIN) { // High gain cells -> Low energies - if (cellEnergy < 4.) // Low energy regime + if (cellEnergy < lowEnergyRegime) // Low energy regime timeshift = 0.8 * std::log(2.7 * cellEnergy); // Parameters extracted from LHC22o (pp), but also usable for other periods else // Medium energy regime timeshift = 1.5 * std::log(0.9 * cellEnergy); // Parameters extracted from LHC22o (pp), but also usable for other periods } else if (cellType == emcal::ChannelType_t::LOW_GAIN) { // Low gain cells -> High energies - if (cellEnergy < 30.) // High energy regime + if (cellEnergy < highEnergyRegime) // High energy regime timeshift = 1.9 * std::log(0.09 * cellEnergy); // Parameters extracted from LHC24aj (pp), but also usable for other periods else // Very high energy regime timeshift = 1.9; // Parameters extracted from LHC24aj (pp), but also usable for other periods diff --git a/PWGJE/Tasks/emcTmMonitor.cxx b/PWGJE/Tasks/emcTmMonitor.cxx index 9fa8df59dec..3d6baefda3b 100644 --- a/PWGJE/Tasks/emcTmMonitor.cxx +++ b/PWGJE/Tasks/emcTmMonitor.cxx @@ -9,6 +9,20 @@ // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. +/// \file emcTmMonitor.cxx +/// \brief Simple monitoring task for EMCal clusters +/// \author Marvin Hemmer +/// \since 24.02.2023 +/// +/// This task is meant to be used for monitoring the matching between global tracks and EMCal clusters +/// properties, such as: +/// - cluster energy over track momentum +/// - difference in eta +/// - difference in phi +/// Simple event selection using the flag doEventSel is provided, which selects INT7 events if set to 1 +/// For pilot beam data, instead of relying on the event selection, one can veto specific BC IDS using the flag +/// fDoVetoBCID. + #include "PWGJE/DataModel/EMCALClusters.h" #include "Common/CCDB/TriggerAliases.h" @@ -16,23 +30,19 @@ #include "Common/DataModel/PIDResponseTPC.h" #include "Common/DataModel/TrackSelectionTables.h" -#include "EMCALBase/Geometry.h" -#include "Framework/ASoA.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/AnalysisTask.h" -#include "Framework/HistogramRegistry.h" +#include #include +#include +#include +#include #include +#include #include #include #include #include #include -#include - -#include - #include #include #include @@ -40,27 +50,13 @@ #include #include -// \struct TrackMatchingMonitor -/// \brief Simple monitoring task for EMCal clusters -/// \author Marvin Hemmer -/// \since 24.02.2023 -/// -/// This task is meant to be used for monitoring the matching between global tracks and EMCal clusters -/// properties, such as: -/// - cluster energy over track momentum -/// - difference in eta -/// - difference in phi -/// Simple event selection using the flag doEventSel is provided, which selects INT7 events if set to 1 -/// For pilot beam data, instead of relying on the event selection, one can veto specific BC IDS using the flag -/// fDoVetoBCID. using namespace o2::framework; using namespace o2::framework::expressions; -using collisionEvSelIt = o2::soa::Join::iterator; -using bcEvSelIt = o2::soa::Join::iterator; -using selectedClusters = o2::soa::Filtered; -using selectedAmbiguousClusters = o2::soa::Filtered; -using tracksPID = o2::soa::Join; -struct TrackMatchingMonitor { +using CollisionEvSelIt = o2::soa::Join::iterator; +using BcEvSelIt = o2::soa::Join::iterator; +using SelectedClusters = o2::soa::Filtered; +using TracksPID = o2::soa::Join; +struct EmcTmMonitor { HistogramRegistry mHistManager{"TrackMatchingMonitorHistograms", {}, OutputObjHandlingPolicy::AnalysisObject}; o2::emcal::Geometry* mGeometry = nullptr; @@ -68,14 +64,13 @@ struct TrackMatchingMonitor { Preslice perClusterAmb = o2::aod::emcalclustercell::emcalambiguousclusterId; Preslice perClusterMatchedTracks = o2::aod::emcalclustercell::emcalclusterId; // configurable parameters - // TODO adapt mDoEventSel switch to also allow selection of other triggers (e.g. EMC7) - Configurable mDoEventSel{"doEventSel", 0, "demand kINT7"}; - Configurable mVetoBCID{"vetoBCID", "", "BC ID(s) to be excluded, this should be used as an alternative to the event selection"}; - Configurable mSelectBCID{"selectBCID", "all", "BC ID(s) to be included, this should be used as an alternative to the event selection"}; - Configurable mVertexCut{"vertexCut", -1, "apply z-vertex cut with value in cm"}; - Configurable mClusterDefinition{"clusterDefinition", 10, "cluster definition to be selected, e.g. 10=kV3Default"}; - ConfigurableAxis mClusterTimeBinning{"clustertime-binning", {1500, -600, 900}, ""}; - Configurable hasPropagatedTracks{"hasPropagatedTracks", false, "temporary flag, only set to true when running over data which has the tracks propagated to EMCal/PHOS!"}; + // TODO adapt doEventSel switch to also allow selection of other triggers (e.g. EMC7) + Configurable doEventSel{"doEventSel", 0, "demand kINT7"}; + Configurable vetoBCID{"vetoBCID", "", "BC ID(s) to be excluded, this should be used as an alternative to the event selection"}; + Configurable selectBCID{"selectBCID", "all", "BC ID(s) to be included, this should be used as an alternative to the event selection"}; + Configurable vertexCut{"vertexCut", -1, "apply z-vertex cut with value in cm"}; + Configurable clusterDefinition{"clusterDefinition", 10, "cluster definition to be selected, e.g. 10=kV3Default"}; + ConfigurableAxis clusterTimeBinning{"clusterTimeBinning", {1500, -600, 900}, ""}; Configurable usePionRejection{"usePionRejection", false, "demand pion rection for electron signal with TPC PID"}; Configurable> tpcNsigmaElectron{"tpcNsigmaElectron", {-1., +3.}, "TPC PID NSigma range for electron signal (first <= NSigma <= second)"}; Configurable> tpcNsigmaBack{"tpcNsigmaBack", {-10., -4.}, "TPC PID NSigma range for electron background (first <= NSigma <= second)"}; @@ -85,7 +80,7 @@ struct TrackMatchingMonitor { Configurable minM02{"minM02", 0.1, "Minimum M02 for M02 cut"}; Configurable maxM02{"maxM02", 0.9, "Maximum M02 for M02 cut"}; Configurable maxM02HighPt{"maxM02HighPt", 0.6, "Maximum M02 for M02 cut for high pT"}; - Configurable M02highPt{"M02highPt", 15., "pT threshold for maxM02HighPt cut. Set to negative value to disable it!"}; + Configurable m02highPt{"m02highPt", 15., "pT threshold for maxM02HighPt cut. Set to negative value to disable it!"}; Configurable minDEta{"minDEta", 0.01, "Minimum dEta between track and cluster"}; Configurable minDPhi{"minDPhi", 0.01, "Minimum dPhi between track and cluster"}; Configurable> eOverPRange{"eOverPRange", {0.9, 1.2}, "E/p range where one would search for electrons (first <= E/p <= second)"}; @@ -97,101 +92,98 @@ struct TrackMatchingMonitor { /// \brief Create output histograms and initialize geometry void init(InitContext const&) { - // create histograms - using o2HistType = HistType; - using o2Axis = AxisSpec; - // load geometry just in case we need it mGeometry = o2::emcal::Geometry::GetInstanceFromRunNumber(300000); // create common axes LOG(info) << "Creating histograms"; - const o2Axis bcAxis{3501, -0.5, 3500.5}; - const o2Axis energyAxis{makeEnergyBinningAliPhysics(), "E_{clus} (GeV)"}; - const o2Axis amplitudeAxisLarge{1000, 0., 100., "amplitudeLarge", "Amplitude (GeV)"}; - const o2Axis dEtaAxis{100, -1.f * minDEta, minDEta, "d#it{#eta}"}; - const o2Axis dPhiAxis{100, -1.f * minDPhi, minDPhi, "d#it{#varphi} (rad)"}; - const o2Axis dRAxis{150, 0.0, 0.015, "d#it{R}"}; - const o2Axis eoverpAxis{500, 0, 10, "#it{E}_{cluster}/#it{p}_{track}"}; - const o2Axis nSigmaAxis{400, -10., +30., "N#sigma"}; - const o2Axis trackptAxis{makePtBinning(), "#it{p}_{T,track}"}; - const o2Axis trackpAxis{200, 0, 100, "#it{p}_{track}"}; - const o2Axis clusterptAxis{makePtBinning(), "#it{p}_{T}"}; - const o2Axis etaAxis{160, -0.8, 0.8, "#eta"}; - const o2Axis phiAxis{72, 0, 2 * 3.14159, "#varphi (rad)"}; - const o2Axis smAxis{20, -0.5, 19.5, "SM"}; - o2Axis timeAxis{mClusterTimeBinning, "t_{cl} (ns)"}; + const AxisSpec bcAxis{3501, -0.5, 3500.5}; + const AxisSpec energyAxis{makeEnergyBinningAliPhysics(), "E_{clus} (GeV)"}; + const AxisSpec amplitudeAxisLarge{1000, 0., 100., "amplitudeLarge", "Amplitude (GeV)"}; + const AxisSpec dEtaAxis{100, -1.f * minDEta, minDEta, "d#it{#eta}"}; + const AxisSpec dPhiAxis{100, -1.f * minDPhi, minDPhi, "d#it{#varphi} (rad)"}; + const AxisSpec dRAxis{150, 0.0, 0.015, "d#it{R}"}; + const AxisSpec eoverpAxis{500, 0, 10, "#it{E}_{cluster}/#it{p}_{track}"}; + const AxisSpec nSigmaAxis{400, -10., +30., "N#sigma"}; + const AxisSpec trackptAxis{makePtBinning(), "#it{p}_{T,track}"}; + const AxisSpec trackpAxis{200, 0, 100, "#it{p}_{track}"}; + const AxisSpec clusterptAxis{makePtBinning(), "#it{p}_{T}"}; + const AxisSpec etaAxis{160, -0.8, 0.8, "#eta"}; + const AxisSpec phiAxis{72, 0, 2 * 3.14159, "#varphi (rad)"}; + const AxisSpec smAxis{20, -0.5, 19.5, "SM"}; + AxisSpec timeAxis{clusterTimeBinning, "t_{cl} (ns)"}; - int MaxMatched = 20; // maximum number of matched tracks, hardcoded in emcalCorrectionTask.cxx! - const o2Axis nmatchedtrack{MaxMatched, -0.5, MaxMatched + 0.5}; + const int maxMatched = 20; // maximum number of matched tracks, hardcoded in emcalCorrectionTask.cxx! + const AxisSpec nmatchedtrack{maxMatched, -0.5, maxMatched + 0.5}; + // create histograms // event properties - mHistManager.add("eventsAll", "Number of events", o2HistType::kTH1F, {{1, 0.5, 1.5}}); - mHistManager.add("eventsSelected", "Number of events", o2HistType::kTH1F, {{1, 0.5, 1.5}}); - mHistManager.add("eventVertexZAll", "z-vertex of event (all events)", o2HistType::kTH1F, {{200, -20, 20}}); - mHistManager.add("eventVertexZSelected", "z-vertex of event (selected events)", o2HistType::kTH1F, {{200, -20, 20}}); + mHistManager.add("eventsAll", "Number of events", HistType::kTH1F, {{1, 0.5, 1.5}}); + mHistManager.add("eventsSelected", "Number of events", HistType::kTH1F, {{1, 0.5, 1.5}}); + mHistManager.add("eventVertexZAll", "z-vertex of event (all events)", HistType::kTH1F, {{200, -20, 20}}); + mHistManager.add("eventVertexZSelected", "z-vertex of event (selected events)", HistType::kTH1F, {{200, -20, 20}}); // cluster properties (matched clusters) - mHistManager.add("TrackEtaPhi", "#eta vs #varphi of all selected tracks", o2HistType::kTH2F, {etaAxis, phiAxis}); // eta vs phi of all selected tracks - mHistManager.add("TrackEtaPhi_Neg", "#eta vs #varphi of all selected negative tracks", o2HistType::kTH2F, {etaAxis, phiAxis}); // eta vs phi of all selected negative tracks - mHistManager.add("TrackEtaPhi_Pos", "#eta vs #varphi of all selected positive tracks", o2HistType::kTH2F, {etaAxis, phiAxis}); // eta vs phi of all selected positive tracks - mHistManager.add("clusterEMatched", "Energy of cluster (with match)", o2HistType::kTH1F, {energyAxis}); // energy of matched clusters - mHistManager.add("MatchedTrackEtaPhi_BeforeCut", "#eta vs #varphi of all selected matched tracks before d#eta and #dvarphi cut", o2HistType::kTH2F, {etaAxis, phiAxis}); // eta vs phi of all selected matched tracks before dEta and dPhi cut - mHistManager.add("MatchedTrackEtaPhi_Neg_BeforeCut", "#eta vs #varphi of all selected negative matched tracks before d#eta and #dvarphi cut", o2HistType::kTH2F, {etaAxis, phiAxis}); // eta vs phi of all selected negative matched tracks before dEta and dPhi cut - mHistManager.add("MatchedTrackEtaPhi_Pos_BeforeCut", "#eta vs #varphi of all selected positive matched tracks before d#eta and #dvarphi cut", o2HistType::kTH2F, {etaAxis, phiAxis}); // eta vs phi of all selected positive matched tracks before dEta and dPhi cut - mHistManager.add("MatchedTrackEtaPhi", "#eta vs #varphi of all selected matched tracks", o2HistType::kTH2F, {etaAxis, phiAxis}); // eta vs phi of all selected matched tracks - mHistManager.add("MatchedTrackEtaPhi_Neg", "#eta vs #varphi of all selected negative matched tracks", o2HistType::kTH2F, {etaAxis, phiAxis}); // eta vs phi of all selected negative matched tracks - mHistManager.add("MatchedTrackEtaPhi_Pos", "#eta vs #varphi of all selected positive matched tracks", o2HistType::kTH2F, {etaAxis, phiAxis}); // eta vs phi of all selected positive matched tracks - mHistManager.add("clusterTM_dEtadPhi", "cluster trackmatching dEta/dPhi", o2HistType::kTH3F, {dEtaAxis, dPhiAxis, smAxis}); // dEta dPhi per SM - mHistManager.add("clusterTM_dEtadPhi_ASide", "cluster trackmatching in A-Side dEta/dPhi", o2HistType::kTH3F, {dEtaAxis, dPhiAxis, smAxis}); // dEta dPhi per SM in A-Aside - mHistManager.add("clusterTM_dEtadPhi_CSide", "cluster trackmatching in C-Side tracks dEta/dPhi", o2HistType::kTH3F, {dEtaAxis, dPhiAxis, smAxis}); // dEta dPhi per SM in C-Side - mHistManager.add("clusterTM_PosdEtadPhi", "cluster trackmatching positive tracks dEta/dPhi", o2HistType::kTH3F, {dEtaAxis, dPhiAxis, smAxis}); // dEta dPhi per SM positive track - mHistManager.add("clusterTM_NegdEtadPhi", "cluster trackmatching negative tracks dEta/dPhi", o2HistType::kTH3F, {dEtaAxis, dPhiAxis, smAxis}); // dEta dPhi per SM negative track - mHistManager.add("clusterTM_PosdEtadPhi_Pl0_75", "cluster trackmatching positive tracks, p < 0.75 dEta/dPhi", o2HistType::kTH3F, {dEtaAxis, dPhiAxis, smAxis}); // dEta dPhi per SM positive track with p < 0.75 GeV/c - mHistManager.add("clusterTM_NegdEtadPhi_Pl0_75", "cluster trackmatching negative tracks, p < 0.75 dEta/dPhi", o2HistType::kTH3F, {dEtaAxis, dPhiAxis, smAxis}); // dEta dPhi per SM negative track with p < 0.75 GeV/c - mHistManager.add("clusterTM_PosdEtadPhi_0_75leqPl1_25", "cluster trackmatching positive tracks, 0.75 <= p < 1.25 dEta/dPhi", o2HistType::kTH3F, {dEtaAxis, dPhiAxis, smAxis}); // dEta dPhi per SM positive track with 0.75 <= p < 1.25 GeV/c - mHistManager.add("clusterTM_NegdEtadPhi_0_75leqPl1_25", "cluster trackmatching negative tracks, 0.75 <= p < 1.25 dEta/dPhi", o2HistType::kTH3F, {dEtaAxis, dPhiAxis, smAxis}); // dEta dPhi per SM negative track with 0.75 <= p < 1.25 GeV/c - mHistManager.add("clusterTM_PosdEtadPhi_Pgeq1_25", "cluster trackmatching positive tracks, p >= 1.25 dEta/dPhi", o2HistType::kTH3F, {dEtaAxis, dPhiAxis, smAxis}); // dEta dPhi per SM positive track with p >= 1.25 GeV/c - mHistManager.add("clusterTM_NegdEtadPhi_Pgeq1_25", "cluster trackmatching negative tracks, p >= 1.25 dEta/dPhi", o2HistType::kTH3F, {dEtaAxis, dPhiAxis, smAxis}); // dEta dPhi per SM negative track with p >= 1.25 GeV/c - mHistManager.add("clusterTM_dEtaPt", "cluster trackmatching dEta/#it{p}_{T};d#it{#eta};#it{p}_{T} (GeV/#it{c})", o2HistType::kTH3F, {dEtaAxis, clusterptAxis, smAxis}); // dEta vs pT per SM - mHistManager.add("clusterTM_PosdPhiPt", "cluster trackmatching positive tracks dPhi/#it{p}_{T}", o2HistType::kTH3F, {dPhiAxis, clusterptAxis, smAxis}); // dPhi vs pT per SM positive track - mHistManager.add("clusterTM_NegdPhiPt", "cluster trackmatching negative tracks dPh/#it{p}_{T}", o2HistType::kTH3F, {dPhiAxis, clusterptAxis, smAxis}); // dPhi vs pT per SM negative track - mHistManager.add("clusterTM_dEtaTN", "cluster trackmatching dEta/TN;d#it{#eta};#it{N}_{matched tracks}", o2HistType::kTH2F, {dEtaAxis, nmatchedtrack}); // dEta compared to the Nth closest track - mHistManager.add("clusterTM_dPhiTN", "cluster trackmatching dPhi/TN;d#it{#varphi} (rad);#it{N}_{matched tracks}", o2HistType::kTH2F, {dPhiAxis, nmatchedtrack}); // dPhi compared to the Nth closest track - mHistManager.add("clusterTM_dRTN", "cluster trackmatching dR/TN;d#it{R};#it{N}_{matched tracks}", o2HistType::kTH2F, {dRAxis, nmatchedtrack}); // dR compared to the Nth closest track - mHistManager.add("clusterTM_NTrack", "cluster trackmatching NMatchedTracks", o2HistType::kTH1I, {nmatchedtrack}); // how many tracks are matched - mHistManager.add("clusterTM_EoverP_E", "E/p ", o2HistType::kTH3F, {eoverpAxis, energyAxis, nmatchedtrack}); // E/p vs p for the Nth closest track - mHistManager.add("clusterTM_EoverP_Pt", "E/p vs track pT", o2HistType::kTH3F, {eoverpAxis, trackptAxis, nmatchedtrack}); // E/p vs track pT for the Nth closest track - mHistManager.add("clusterTM_EvsP", "cluster E/track p", o2HistType::kTH3F, {energyAxis, trackpAxis, nmatchedtrack}); // E vs p for the Nth closest track - mHistManager.add("clusterTM_EoverP_ep", "cluster E/electron p", o2HistType::kTH3F, {eoverpAxis, trackptAxis, nmatchedtrack}); // E over p vs track pT for the Nth closest electron/positron track - mHistManager.add("clusterTM_EoverP_e", "cluster E/electron p", o2HistType::kTH3F, {eoverpAxis, trackptAxis, nmatchedtrack}); // E over p vs track pT for the Nth closest electron track - mHistManager.add("clusterTM_EoverP_p", "cluster E/electron p", o2HistType::kTH3F, {eoverpAxis, trackptAxis, nmatchedtrack}); // E over p vs track pT for the Nth closest positron track - mHistManager.add("clusterTM_EoverP_electron_ASide", "cluster E/electron p in A-Side", o2HistType::kTH3F, {eoverpAxis, trackptAxis, nmatchedtrack}); // E over p vs track pT for the Nth closest electron/positron track in A-Side - mHistManager.add("clusterTM_EoverP_electron_CSide", "cluster E/electron p in C-Side", o2HistType::kTH3F, {eoverpAxis, trackptAxis, nmatchedtrack}); // E over p vs track pT for the Nth closest electron/positron track in C-Side - mHistManager.add("clusterTM_NSigma_BeforeCut", "electron NSigma for matched tracks before d#eta and #dvarphi cut", o2HistType::kTH3F, {nSigmaAxis, trackptAxis, nmatchedtrack}); // NSigma_electron vs track pT for the Nth closest track before dEta and dPhi cut - mHistManager.add("clusterTM_NSigma_neg_BeforeCut", "electron NSigma for matched negative tracks before d#eta and #dvarphi cut", o2HistType::kTH3F, {nSigmaAxis, trackptAxis, nmatchedtrack}); // NSigma_electron vs track pT for the Nth closest negative tracks before dEta and dPhi cut - mHistManager.add("clusterTM_NSigma_pos_BeforeCut", "electron NSigma for matched positive tracks before d#eta and #dvarphi cut", o2HistType::kTH3F, {nSigmaAxis, trackptAxis, nmatchedtrack}); // NSigma_electron vs track pT for the Nth closest positive tracks before dEta and dPhi cut - mHistManager.add("clusterTM_NSigma", "electron NSigma for matched track", o2HistType::kTH3F, {nSigmaAxis, trackptAxis, nmatchedtrack}); // NSigma_electron vs track pT for the Nth closest track - mHistManager.add("clusterTM_NSigma_neg", "electron NSigma for matched negative track", o2HistType::kTH3F, {nSigmaAxis, trackptAxis, nmatchedtrack}); // NSigma_electron vs track pT for the Nth closest negative tracks - mHistManager.add("clusterTM_NSigma_pos", "electron NSigma for matched positive track", o2HistType::kTH3F, {nSigmaAxis, trackptAxis, nmatchedtrack}); // NSigma_electron vs track pT for the Nth closest positive tracks - mHistManager.add("clusterTM_NSigma_cut", "electron NSigma for matched track with cuts", o2HistType::kTH3F, {nSigmaAxis, trackptAxis, nmatchedtrack}); // NSigma_electron vs track pT for the Nth closest track with cuts on E/p and cluster cuts - mHistManager.add("clusterTM_NSigma_e", "NSigma electron", o2HistType::kTH3F, {nSigmaAxis, trackptAxis, nmatchedtrack}); // NSigma vs track pT for the Nth closest electron track - mHistManager.add("clusterTM_NSigma_p", "NSigma positron", o2HistType::kTH3F, {nSigmaAxis, trackptAxis, nmatchedtrack}); // NSigma vs track pT for the Nth closest positron track - mHistManager.add("clusterTM_NSigma_e_cut", "NSigma electron with E over p cut", o2HistType::kTH3F, {nSigmaAxis, trackptAxis, nmatchedtrack}); // NSigma vs track pT for the Nth closest electron track with E/p cut - mHistManager.add("clusterTM_NSigma_p_cut", "NSigma positron with E over p cut", o2HistType::kTH3F, {nSigmaAxis, trackptAxis, nmatchedtrack}); // NSigma vs track pT for the Nth closest positron track with E/p cut - mHistManager.add("TrackTM_NSigma", "electron NSigma for global tracks", o2HistType::kTH2F, {nSigmaAxis, trackptAxis}); // NSigma_electron vs track pT for global track - mHistManager.add("TrackTM_NSigma_e", "NSigma e for global negative tracks", o2HistType::kTH2F, {nSigmaAxis, trackptAxis}); // NSigma vs track pT for negative global track - mHistManager.add("TrackTM_NSigma_p", "NSigma e for global positive tracks", o2HistType::kTH2F, {nSigmaAxis, trackptAxis}); // NSigma vs track pT for positive global track - mHistManager.add("clusterTM_NSigma_electron_ASide", "NSigma electron in A-Side", o2HistType::kTH3F, {nSigmaAxis, trackptAxis, nmatchedtrack}); // NSigma vs track pT for the Nth closest electron/positron track in A-Side - mHistManager.add("clusterTM_NSigma_electron_CSide", "NSigma positron in C-Side", o2HistType::kTH3F, {nSigmaAxis, trackptAxis, nmatchedtrack}); // NSigma vs track pT for the Nth closest electron/positron track in C-Side - mHistManager.add("clusterTM_EoverP_hadron", "cluster E/hadron p", o2HistType::kTH3F, {eoverpAxis, trackpAxis, nmatchedtrack}); // E over p vs track pT for the Nth closest hadron track - mHistManager.add("clusterTM_EoverP_hn", "cluster E/hadron p", o2HistType::kTH3F, {eoverpAxis, trackpAxis, nmatchedtrack}); // E over p vs track pT for the Nth closest negative hadron track - mHistManager.add("clusterTM_EoverP_hp", "cluster E/hadron p", o2HistType::kTH3F, {eoverpAxis, trackpAxis, nmatchedtrack}); // E over p vs track pT for the Nth closest positive hadron track - mHistManager.add("clusterTM_EoverP_hadron_ASide", "cluster E/hadron p in A-Side", o2HistType::kTH3F, {eoverpAxis, trackpAxis, nmatchedtrack}); // E over p vs track pT for the Nth closest hadron track in A-Side - mHistManager.add("clusterTM_EoverP_hadron_CSide", "cluster E/hadron p in C-Side", o2HistType::kTH3F, {eoverpAxis, trackpAxis, nmatchedtrack}); // E over p vs track pT for the Nth closest hadron track in C-Side + mHistManager.add("TrackEtaPhi", "#eta vs #varphi of all selected tracks", HistType::kTH2F, {etaAxis, phiAxis}); // eta vs phi of all selected tracks + mHistManager.add("TrackEtaPhi_Neg", "#eta vs #varphi of all selected negative tracks", HistType::kTH2F, {etaAxis, phiAxis}); // eta vs phi of all selected negative tracks + mHistManager.add("TrackEtaPhi_Pos", "#eta vs #varphi of all selected positive tracks", HistType::kTH2F, {etaAxis, phiAxis}); // eta vs phi of all selected positive tracks + mHistManager.add("clusterEMatched", "Energy of cluster (with match)", HistType::kTH1F, {energyAxis}); // energy of matched clusters + mHistManager.add("MatchedTrackEtaPhi_BeforeCut", "#eta vs #varphi of all selected matched tracks before d#eta and #dvarphi cut", HistType::kTH2F, {etaAxis, phiAxis}); // eta vs phi of all selected matched tracks before dEta and dPhi cut + mHistManager.add("MatchedTrackEtaPhi_Neg_BeforeCut", "#eta vs #varphi of all selected negative matched tracks before d#eta and #dvarphi cut", HistType::kTH2F, {etaAxis, phiAxis}); // eta vs phi of all selected negative matched tracks before dEta and dPhi cut + mHistManager.add("MatchedTrackEtaPhi_Pos_BeforeCut", "#eta vs #varphi of all selected positive matched tracks before d#eta and #dvarphi cut", HistType::kTH2F, {etaAxis, phiAxis}); // eta vs phi of all selected positive matched tracks before dEta and dPhi cut + mHistManager.add("MatchedTrackEtaPhi", "#eta vs #varphi of all selected matched tracks", HistType::kTH2F, {etaAxis, phiAxis}); // eta vs phi of all selected matched tracks + mHistManager.add("MatchedTrackEtaPhi_Neg", "#eta vs #varphi of all selected negative matched tracks", HistType::kTH2F, {etaAxis, phiAxis}); // eta vs phi of all selected negative matched tracks + mHistManager.add("MatchedTrackEtaPhi_Pos", "#eta vs #varphi of all selected positive matched tracks", HistType::kTH2F, {etaAxis, phiAxis}); // eta vs phi of all selected positive matched tracks + mHistManager.add("clusterTM_dEtadPhi", "cluster trackmatching dEta/dPhi", HistType::kTH3F, {dEtaAxis, dPhiAxis, smAxis}); // dEta dPhi per SM + mHistManager.add("clusterTM_dEtadPhi_ASide", "cluster trackmatching in A-Side dEta/dPhi", HistType::kTH3F, {dEtaAxis, dPhiAxis, smAxis}); // dEta dPhi per SM in A-Aside + mHistManager.add("clusterTM_dEtadPhi_CSide", "cluster trackmatching in C-Side tracks dEta/dPhi", HistType::kTH3F, {dEtaAxis, dPhiAxis, smAxis}); // dEta dPhi per SM in C-Side + mHistManager.add("clusterTM_PosdEtadPhi", "cluster trackmatching positive tracks dEta/dPhi", HistType::kTH3F, {dEtaAxis, dPhiAxis, smAxis}); // dEta dPhi per SM positive track + mHistManager.add("clusterTM_NegdEtadPhi", "cluster trackmatching negative tracks dEta/dPhi", HistType::kTH3F, {dEtaAxis, dPhiAxis, smAxis}); // dEta dPhi per SM negative track + mHistManager.add("clusterTM_PosdEtadPhi_Pl0_75", "cluster trackmatching positive tracks, p < 0.75 dEta/dPhi", HistType::kTH3F, {dEtaAxis, dPhiAxis, smAxis}); // dEta dPhi per SM positive track with p < 0.75 GeV/c + mHistManager.add("clusterTM_NegdEtadPhi_Pl0_75", "cluster trackmatching negative tracks, p < 0.75 dEta/dPhi", HistType::kTH3F, {dEtaAxis, dPhiAxis, smAxis}); // dEta dPhi per SM negative track with p < 0.75 GeV/c + mHistManager.add("clusterTM_PosdEtadPhi_0_75leqPl1_25", "cluster trackmatching positive tracks, 0.75 <= p < 1.25 dEta/dPhi", HistType::kTH3F, {dEtaAxis, dPhiAxis, smAxis}); // dEta dPhi per SM positive track with 0.75 <= p < 1.25 GeV/c + mHistManager.add("clusterTM_NegdEtadPhi_0_75leqPl1_25", "cluster trackmatching negative tracks, 0.75 <= p < 1.25 dEta/dPhi", HistType::kTH3F, {dEtaAxis, dPhiAxis, smAxis}); // dEta dPhi per SM negative track with 0.75 <= p < 1.25 GeV/c + mHistManager.add("clusterTM_PosdEtadPhi_Pgeq1_25", "cluster trackmatching positive tracks, p >= 1.25 dEta/dPhi", HistType::kTH3F, {dEtaAxis, dPhiAxis, smAxis}); // dEta dPhi per SM positive track with p >= 1.25 GeV/c + mHistManager.add("clusterTM_NegdEtadPhi_Pgeq1_25", "cluster trackmatching negative tracks, p >= 1.25 dEta/dPhi", HistType::kTH3F, {dEtaAxis, dPhiAxis, smAxis}); // dEta dPhi per SM negative track with p >= 1.25 GeV/c + mHistManager.add("clusterTM_dEtaPt", "cluster trackmatching dEta/#it{p}_{T};d#it{#eta};#it{p}_{T} (GeV/#it{c})", HistType::kTH3F, {dEtaAxis, clusterptAxis, smAxis}); // dEta vs pT per SM + mHistManager.add("clusterTM_PosdPhiPt", "cluster trackmatching positive tracks dPhi/#it{p}_{T}", HistType::kTH3F, {dPhiAxis, clusterptAxis, smAxis}); // dPhi vs pT per SM positive track + mHistManager.add("clusterTM_NegdPhiPt", "cluster trackmatching negative tracks dPh/#it{p}_{T}", HistType::kTH3F, {dPhiAxis, clusterptAxis, smAxis}); // dPhi vs pT per SM negative track + mHistManager.add("clusterTM_dEtaTN", "cluster trackmatching dEta/TN;d#it{#eta};#it{N}_{matched tracks}", HistType::kTH2F, {dEtaAxis, nmatchedtrack}); // dEta compared to the Nth closest track + mHistManager.add("clusterTM_dPhiTN", "cluster trackmatching dPhi/TN;d#it{#varphi} (rad);#it{N}_{matched tracks}", HistType::kTH2F, {dPhiAxis, nmatchedtrack}); // dPhi compared to the Nth closest track + mHistManager.add("clusterTM_dRTN", "cluster trackmatching dR/TN;d#it{R};#it{N}_{matched tracks}", HistType::kTH2F, {dRAxis, nmatchedtrack}); // dR compared to the Nth closest track + mHistManager.add("clusterTM_NTrack", "cluster trackmatching NMatchedTracks", HistType::kTH1I, {nmatchedtrack}); // how many tracks are matched + mHistManager.add("clusterTM_EoverP_E", "E/p ", HistType::kTH3F, {eoverpAxis, energyAxis, nmatchedtrack}); // E/p vs p for the Nth closest track + mHistManager.add("clusterTM_EoverP_Pt", "E/p vs track pT", HistType::kTH3F, {eoverpAxis, trackptAxis, nmatchedtrack}); // E/p vs track pT for the Nth closest track + mHistManager.add("clusterTM_EvsP", "cluster E/track p", HistType::kTH3F, {energyAxis, trackpAxis, nmatchedtrack}); // E vs p for the Nth closest track + mHistManager.add("clusterTM_EoverP_ep", "cluster E/electron p", HistType::kTH3F, {eoverpAxis, trackptAxis, nmatchedtrack}); // E over p vs track pT for the Nth closest electron/positron track + mHistManager.add("clusterTM_EoverP_e", "cluster E/electron p", HistType::kTH3F, {eoverpAxis, trackptAxis, nmatchedtrack}); // E over p vs track pT for the Nth closest electron track + mHistManager.add("clusterTM_EoverP_p", "cluster E/electron p", HistType::kTH3F, {eoverpAxis, trackptAxis, nmatchedtrack}); // E over p vs track pT for the Nth closest positron track + mHistManager.add("clusterTM_EoverP_electron_ASide", "cluster E/electron p in A-Side", HistType::kTH3F, {eoverpAxis, trackptAxis, nmatchedtrack}); // E over p vs track pT for the Nth closest electron/positron track in A-Side + mHistManager.add("clusterTM_EoverP_electron_CSide", "cluster E/electron p in C-Side", HistType::kTH3F, {eoverpAxis, trackptAxis, nmatchedtrack}); // E over p vs track pT for the Nth closest electron/positron track in C-Side + mHistManager.add("clusterTM_NSigma_BeforeCut", "electron NSigma for matched tracks before d#eta and #dvarphi cut", HistType::kTH3F, {nSigmaAxis, trackptAxis, nmatchedtrack}); // NSigma_electron vs track pT for the Nth closest track before dEta and dPhi cut + mHistManager.add("clusterTM_NSigma_neg_BeforeCut", "electron NSigma for matched negative tracks before d#eta and #dvarphi cut", HistType::kTH3F, {nSigmaAxis, trackptAxis, nmatchedtrack}); // NSigma_electron vs track pT for the Nth closest negative tracks before dEta and dPhi cut + mHistManager.add("clusterTM_NSigma_pos_BeforeCut", "electron NSigma for matched positive tracks before d#eta and #dvarphi cut", HistType::kTH3F, {nSigmaAxis, trackptAxis, nmatchedtrack}); // NSigma_electron vs track pT for the Nth closest positive tracks before dEta and dPhi cut + mHistManager.add("clusterTM_NSigma", "electron NSigma for matched track", HistType::kTH3F, {nSigmaAxis, trackptAxis, nmatchedtrack}); // NSigma_electron vs track pT for the Nth closest track + mHistManager.add("clusterTM_NSigma_neg", "electron NSigma for matched negative track", HistType::kTH3F, {nSigmaAxis, trackptAxis, nmatchedtrack}); // NSigma_electron vs track pT for the Nth closest negative tracks + mHistManager.add("clusterTM_NSigma_pos", "electron NSigma for matched positive track", HistType::kTH3F, {nSigmaAxis, trackptAxis, nmatchedtrack}); // NSigma_electron vs track pT for the Nth closest positive tracks + mHistManager.add("clusterTM_NSigma_cut", "electron NSigma for matched track with cuts", HistType::kTH3F, {nSigmaAxis, trackptAxis, nmatchedtrack}); // NSigma_electron vs track pT for the Nth closest track with cuts on E/p and cluster cuts + mHistManager.add("clusterTM_NSigma_e", "NSigma electron", HistType::kTH3F, {nSigmaAxis, trackptAxis, nmatchedtrack}); // NSigma vs track pT for the Nth closest electron track + mHistManager.add("clusterTM_NSigma_p", "NSigma positron", HistType::kTH3F, {nSigmaAxis, trackptAxis, nmatchedtrack}); // NSigma vs track pT for the Nth closest positron track + mHistManager.add("clusterTM_NSigma_e_cut", "NSigma electron with E over p cut", HistType::kTH3F, {nSigmaAxis, trackptAxis, nmatchedtrack}); // NSigma vs track pT for the Nth closest electron track with E/p cut + mHistManager.add("clusterTM_NSigma_p_cut", "NSigma positron with E over p cut", HistType::kTH3F, {nSigmaAxis, trackptAxis, nmatchedtrack}); // NSigma vs track pT for the Nth closest positron track with E/p cut + mHistManager.add("TrackTM_NSigma", "electron NSigma for global tracks", HistType::kTH2F, {nSigmaAxis, trackptAxis}); // NSigma_electron vs track pT for global track + mHistManager.add("TrackTM_NSigma_e", "NSigma e for global negative tracks", HistType::kTH2F, {nSigmaAxis, trackptAxis}); // NSigma vs track pT for negative global track + mHistManager.add("TrackTM_NSigma_p", "NSigma e for global positive tracks", HistType::kTH2F, {nSigmaAxis, trackptAxis}); // NSigma vs track pT for positive global track + mHistManager.add("clusterTM_NSigma_electron_ASide", "NSigma electron in A-Side", HistType::kTH3F, {nSigmaAxis, trackptAxis, nmatchedtrack}); // NSigma vs track pT for the Nth closest electron/positron track in A-Side + mHistManager.add("clusterTM_NSigma_electron_CSide", "NSigma positron in C-Side", HistType::kTH3F, {nSigmaAxis, trackptAxis, nmatchedtrack}); // NSigma vs track pT for the Nth closest electron/positron track in C-Side + mHistManager.add("clusterTM_EoverP_hadron", "cluster E/hadron p", HistType::kTH3F, {eoverpAxis, trackpAxis, nmatchedtrack}); // E over p vs track pT for the Nth closest hadron track + mHistManager.add("clusterTM_EoverP_hn", "cluster E/hadron p", HistType::kTH3F, {eoverpAxis, trackpAxis, nmatchedtrack}); // E over p vs track pT for the Nth closest negative hadron track + mHistManager.add("clusterTM_EoverP_hp", "cluster E/hadron p", HistType::kTH3F, {eoverpAxis, trackpAxis, nmatchedtrack}); // E over p vs track pT for the Nth closest positive hadron track + mHistManager.add("clusterTM_EoverP_hadron_ASide", "cluster E/hadron p in A-Side", HistType::kTH3F, {eoverpAxis, trackpAxis, nmatchedtrack}); // E over p vs track pT for the Nth closest hadron track in A-Side + mHistManager.add("clusterTM_EoverP_hadron_CSide", "cluster E/hadron p in C-Side", HistType::kTH3F, {eoverpAxis, trackpAxis, nmatchedtrack}); // E over p vs track pT for the Nth closest hadron track in C-Side - if (mVetoBCID->length()) { - std::stringstream parser(mVetoBCID.value); + if (vetoBCID->length()) { + std::stringstream parser(vetoBCID.value); std::string token; int bcid; while (std::getline(parser, token, ',')) { @@ -200,8 +192,8 @@ struct TrackMatchingMonitor { mVetoBCIDs.push_back(bcid); } } - if (mSelectBCID.value != "all") { - std::stringstream parser(mSelectBCID.value); + if (selectBCID.value != "all") { + std::stringstream parser(selectBCID.value); std::string token; int bcid; while (std::getline(parser, token, ',')) { @@ -215,19 +207,22 @@ struct TrackMatchingMonitor { // define cluster filter. It selects only those clusters which are of the type // sadly passing of the string at runtime is not possible for technical region so cluster definition is // an integer instead - Filter clusterDefinitionSelection = (o2::aod::emcalcluster::definition == mClusterDefinition) && (o2::aod::emcalcluster::time >= minTime) && (o2::aod::emcalcluster::time <= maxTime) && (o2::aod::emcalcluster::m02 > minM02) && (o2::aod::emcalcluster::m02 < maxM02); + Filter clusterDefinitionSelection = (o2::aod::emcalcluster::definition == clusterDefinition) && (o2::aod::emcalcluster::time >= minTime) && (o2::aod::emcalcluster::time <= maxTime) && (o2::aod::emcalcluster::m02 > minM02) && (o2::aod::emcalcluster::m02 < maxM02); /// \brief Process EMCAL clusters that are matched to a collisions - void processCollisions(collisionEvSelIt const& theCollision, selectedClusters const& clusters, o2::aod::EMCALClusterCells const&, o2::aod::Calos const&, o2::aod::EMCALMatchedTracks const& matchedtracks, tracksPID const& alltracks) + void processCollisions(CollisionEvSelIt const& theCollision, SelectedClusters const& clusters, o2::aod::EMCALClusterCells const&, o2::aod::Calos const&, o2::aod::EMCALMatchedTracks const& matchedtracks, TracksPID const& alltracks) { mHistManager.fill(HIST("eventsAll"), 1); - // do event selection if mDoEventSel is specified + // do event selection if doEventSel is specified // currently the event selection is hard coded to kINT7 // but other selections are possible that are defined in TriggerAliases.h bool isSelected = true; - if (mDoEventSel) { - if (theCollision.bc().runNumber() < 300000) { + const int beginningRun3 = 300000; + float lowP = 0.75f; + float midP = 1.25f; + if (doEventSel) { + if (theCollision.bc().runNumber() < beginningRun3) { if (!theCollision.alias_bit(kINT7)) { isSelected = false; } @@ -242,8 +237,8 @@ struct TrackMatchingMonitor { return; } mHistManager.fill(HIST("eventVertexZAll"), theCollision.posZ()); - if (mVertexCut > 0 && TMath::Abs(theCollision.posZ()) > mVertexCut) { - LOG(debug) << "Event not selected because of z-vertex cut z= " << theCollision.posZ() << " > " << mVertexCut << " cm, skipping"; + if (vertexCut > 0 && std::abs(theCollision.posZ()) > vertexCut) { + LOG(debug) << "Event not selected because of z-vertex cut z= " << theCollision.posZ() << " > " << vertexCut << " cm, skipping"; return; } mHistManager.fill(HIST("eventsSelected"), 1); @@ -251,13 +246,8 @@ struct TrackMatchingMonitor { for (const auto& alltrack : alltracks) { double trackEta, trackPhi; - if (hasPropagatedTracks) { // only temporarily while not every data has the tracks propagated to EMCal/PHOS - trackEta = alltrack.trackEtaEmcal(); - trackPhi = alltrack.trackPhiEmcal(); - } else { - trackEta = alltrack.eta(); - trackPhi = alltrack.phi(); - } + trackEta = alltrack.trackEtaEmcal(); + trackPhi = alltrack.trackPhiEmcal(); if (alltrack.isGlobalTrack()) { // NSigma of all global tracks without matching mHistManager.fill(HIST("TrackTM_NSigma"), alltrack.tpcNSigmaEl(), alltrack.pt()); mHistManager.fill(HIST("TrackEtaPhi"), trackEta, trackPhi); @@ -294,7 +284,7 @@ struct TrackMatchingMonitor { // match.track_as() with // using globTracks = o2::soa::Join; // In this example the counter t is just used to only look at the closest match - double dEta, dPhi, pT, abs_p, trackEta, trackPhi, NSigmaEl; + float dEta, dPhi, pT, abs_p, trackEta, trackPhi, nSigmaEl; int supermoduleID; try { supermoduleID = mGeometry->SuperModuleNumberFromEtaPhi(cluster.eta(), cluster.phi()); @@ -304,40 +294,35 @@ struct TrackMatchingMonitor { continue; } - pT = cluster.energy() / cosh(cluster.eta()); - if (M02highPt > 0. && cluster.m02() >= maxM02HighPt && pT >= M02highPt) { // high pT M02 cut + pT = cluster.energy() / std::cosh(cluster.eta()); + if (m02highPt > 0. && cluster.m02() >= maxM02HighPt && pT >= m02highPt) { // high pT M02 cut continue; } auto tracksofcluster = matchedtracks.sliceBy(perClusterMatchedTracks, cluster.globalIndex()); int t = 0; for (const auto& match : tracksofcluster) { - NSigmaEl = match.track_as().tpcNSigmaEl(); + nSigmaEl = match.track_as().tpcNSigmaEl(); // exmple of how to access any property of the matched tracks (tracks are sorted by how close they are to cluster) - LOG(debug) << "Pt of match" << match.track_as().pt(); - abs_p = abs(match.track_as().p()); + LOG(debug) << "Pt of match" << match.track_as().pt(); + abs_p = std::abs(match.track_as().p()); // only consider closest match - if (hasPropagatedTracks) { // only temporarily while not every data has the tracks propagated to EMCal/PHOS - trackEta = match.track_as().trackEtaEmcal(); - trackPhi = match.track_as().trackPhiEmcal(); - } else { - trackEta = match.track_as().eta(); - trackPhi = match.track_as().phi(); - } - dPhi = trackPhi - cluster.phi(); - dEta = trackEta - cluster.eta(); + trackEta = match.track_as().trackEtaEmcal(); + trackPhi = match.track_as().trackPhiEmcal(); + dPhi = match.deltaPhi(); + dEta = match.deltaEta(); mHistManager.fill(HIST("MatchedTrackEtaPhi_BeforeCut"), trackEta, trackPhi); - mHistManager.fill(HIST("clusterTM_NSigma_BeforeCut"), NSigmaEl, match.track_as().pt(), t); - if (match.track_as().sign() == -1) { + mHistManager.fill(HIST("clusterTM_NSigma_BeforeCut"), nSigmaEl, match.track_as().pt(), t); + if (match.track_as().sign() == -1) { mHistManager.fill(HIST("MatchedTrackEtaPhi_Neg_BeforeCut"), trackEta, trackPhi); - mHistManager.fill(HIST("clusterTM_NSigma_neg_BeforeCut"), NSigmaEl, match.track_as().pt(), t); - } else if (match.track_as().sign() == 1) { + mHistManager.fill(HIST("clusterTM_NSigma_neg_BeforeCut"), nSigmaEl, match.track_as().pt(), t); + } else if (match.track_as().sign() == 1) { mHistManager.fill(HIST("MatchedTrackEtaPhi_Pos_BeforeCut"), trackEta, trackPhi); - mHistManager.fill(HIST("clusterTM_NSigma_pos_BeforeCut"), NSigmaEl, match.track_as().pt(), t); + mHistManager.fill(HIST("clusterTM_NSigma_pos_BeforeCut"), nSigmaEl, match.track_as().pt(), t); } - if (fabs(dEta) >= minDEta || fabs(dPhi) >= minDPhi) { // dEta and dPhi cut + if (std::abs(dEta) >= minDEta || std::abs(dPhi) >= minDPhi) { // dEta and dPhi cut continue; } - if (hasTRD && !(match.track_as().hasTRD())) { // request TRD hit cut + if (hasTRD && !(match.track_as().hasTRD())) { // request TRD hit cut continue; } // only fill these for the first matched track: @@ -353,105 +338,105 @@ struct TrackMatchingMonitor { mHistManager.fill(HIST("clusterTM_dEtadPhi"), dEta, dPhi, t); mHistManager.fill(HIST("clusterEMatched"), cluster.energy(), t); mHistManager.fill(HIST("clusterTM_EvsP"), cluster.energy(), abs_p, t); - mHistManager.fill(HIST("clusterTM_EoverP_Pt"), eOverP, match.track_as().pt(), t); - mHistManager.fill(HIST("clusterTM_NSigma"), NSigmaEl, match.track_as().pt(), t); + mHistManager.fill(HIST("clusterTM_EoverP_Pt"), eOverP, match.track_as().pt(), t); + mHistManager.fill(HIST("clusterTM_NSigma"), nSigmaEl, match.track_as().pt(), t); mHistManager.fill(HIST("MatchedTrackEtaPhi"), trackEta, trackPhi); if (eOverPRange->at(0) <= eOverP && eOverP <= eOverPRange->at(1)) { - mHistManager.fill(HIST("clusterTM_NSigma_cut"), NSigmaEl, match.track_as().pt(), t); + mHistManager.fill(HIST("clusterTM_NSigma_cut"), nSigmaEl, match.track_as().pt(), t); } // A- and C-side - if (match.track_as().eta() > 0.0 && t == 0) { + if (match.track_as().eta() > 0.0 && t == 0) { mHistManager.fill(HIST("clusterTM_dEtadPhi_ASide"), dEta, dPhi, supermoduleID); - } else if (match.track_as().eta() < 0.0 && t == 0) { + } else if (match.track_as().eta() < 0.0 && t == 0) { mHistManager.fill(HIST("clusterTM_dEtadPhi_CSide"), dEta, dPhi, supermoduleID); } // positive and negative tracks seperate, with three different track momentum ranges - if (match.track_as().sign() == 1) { - mHistManager.fill(HIST("clusterTM_NSigma_pos"), NSigmaEl, match.track_as().pt(), t); + if (match.track_as().sign() == 1) { + mHistManager.fill(HIST("clusterTM_NSigma_pos"), nSigmaEl, match.track_as().pt(), t); mHistManager.fill(HIST("MatchedTrackEtaPhi_Pos"), trackEta, trackPhi); if (t == 0) { mHistManager.fill(HIST("clusterTM_PosdPhiPt"), dPhi, pT, supermoduleID); mHistManager.fill(HIST("clusterTM_PosdEtadPhi"), dEta, dPhi, supermoduleID); - if (abs_p < 0.75) { + if (abs_p < lowP) { mHistManager.fill(HIST("clusterTM_PosdEtadPhi_Pl0_75"), dEta, dPhi, supermoduleID); - } else if (abs_p >= 1.25) { + } else if (abs_p >= midP) { mHistManager.fill(HIST("clusterTM_PosdEtadPhi_Pgeq1_25"), dEta, dPhi, supermoduleID); } else { mHistManager.fill(HIST("clusterTM_PosdEtadPhi_0_75leqPl1_25"), dEta, dPhi, supermoduleID); } } - } else if (match.track_as().sign() == -1) { - mHistManager.fill(HIST("clusterTM_NSigma_neg"), NSigmaEl, match.track_as().pt(), t); + } else if (match.track_as().sign() == -1) { + mHistManager.fill(HIST("clusterTM_NSigma_neg"), nSigmaEl, match.track_as().pt(), t); mHistManager.fill(HIST("MatchedTrackEtaPhi_Neg"), trackEta, trackPhi); if (t == 0) { mHistManager.fill(HIST("clusterTM_NegdPhiPt"), dPhi, pT, supermoduleID); mHistManager.fill(HIST("clusterTM_NegdEtadPhi"), dEta, dPhi, supermoduleID); - if (abs_p < 0.75) { + if (abs_p < lowP) { mHistManager.fill(HIST("clusterTM_NegdEtadPhi_Pl0_75"), dEta, dPhi, supermoduleID); - } else if (abs_p >= 1.25) { + } else if (abs_p >= midP) { mHistManager.fill(HIST("clusterTM_NegdEtadPhi_Pgeq1_25"), dEta, dPhi, supermoduleID); } else { mHistManager.fill(HIST("clusterTM_NegdEtadPhi_0_75leqPl1_25"), dEta, dPhi, supermoduleID); } } } - if (tpcNsigmaElectron->at(0) <= NSigmaEl && NSigmaEl <= tpcNsigmaElectron->at(1)) { // E/p for e+/e- - if (usePionRejection && (tpcNsigmaPion->at(0) <= match.track_as().tpcNSigmaPi() || match.track_as().tpcNSigmaPi() <= tpcNsigmaPion->at(1))) { // with pion rejection - mHistManager.fill(HIST("clusterTM_EoverP_ep"), eOverP, match.track_as().pt(), t); - if (match.track_as().eta() >= 0.) { - mHistManager.fill(HIST("clusterTM_EoverP_electron_ASide"), eOverP, match.track_as().pt(), t); - mHistManager.fill(HIST("clusterTM_NSigma_electron_ASide"), NSigmaEl, match.track_as().pt(), t); + if (tpcNsigmaElectron->at(0) <= nSigmaEl && nSigmaEl <= tpcNsigmaElectron->at(1)) { // E/p for e+/e- + if (usePionRejection && (tpcNsigmaPion->at(0) <= match.track_as().tpcNSigmaPi() || match.track_as().tpcNSigmaPi() <= tpcNsigmaPion->at(1))) { // with pion rejection + mHistManager.fill(HIST("clusterTM_EoverP_ep"), eOverP, match.track_as().pt(), t); + if (match.track_as().eta() >= 0.) { + mHistManager.fill(HIST("clusterTM_EoverP_electron_ASide"), eOverP, match.track_as().pt(), t); + mHistManager.fill(HIST("clusterTM_NSigma_electron_ASide"), nSigmaEl, match.track_as().pt(), t); } else { - mHistManager.fill(HIST("clusterTM_EoverP_electron_CSide"), eOverP, match.track_as().pt(), t); - mHistManager.fill(HIST("clusterTM_NSigma_electron_CSide"), NSigmaEl, match.track_as().pt(), t); + mHistManager.fill(HIST("clusterTM_EoverP_electron_CSide"), eOverP, match.track_as().pt(), t); + mHistManager.fill(HIST("clusterTM_NSigma_electron_CSide"), nSigmaEl, match.track_as().pt(), t); } - if (match.track_as().sign() == -1) { - mHistManager.fill(HIST("clusterTM_EoverP_e"), eOverP, match.track_as().pt(), t); - mHistManager.fill(HIST("clusterTM_NSigma_e"), NSigmaEl, match.track_as().pt(), t); + if (match.track_as().sign() == -1) { + mHistManager.fill(HIST("clusterTM_EoverP_e"), eOverP, match.track_as().pt(), t); + mHistManager.fill(HIST("clusterTM_NSigma_e"), nSigmaEl, match.track_as().pt(), t); if (eOverPRange->at(0) <= eOverP && eOverP <= eOverPRange->at(1)) { - mHistManager.fill(HIST("clusterTM_NSigma_e_cut"), NSigmaEl, match.track_as().pt(), t); + mHistManager.fill(HIST("clusterTM_NSigma_e_cut"), nSigmaEl, match.track_as().pt(), t); } - } else if (match.track_as().sign() == +1) { - mHistManager.fill(HIST("clusterTM_EoverP_p"), eOverP, match.track_as().pt(), t); - mHistManager.fill(HIST("clusterTM_NSigma_p"), NSigmaEl, match.track_as().pt(), t); + } else if (match.track_as().sign() == +1) { + mHistManager.fill(HIST("clusterTM_EoverP_p"), eOverP, match.track_as().pt(), t); + mHistManager.fill(HIST("clusterTM_NSigma_p"), nSigmaEl, match.track_as().pt(), t); if (eOverPRange->at(0) <= eOverP && eOverP <= eOverPRange->at(1)) { - mHistManager.fill(HIST("clusterTM_NSigma_p_cut"), NSigmaEl, match.track_as().pt(), t); + mHistManager.fill(HIST("clusterTM_NSigma_p_cut"), nSigmaEl, match.track_as().pt(), t); } } } else { // without pion rejection - mHistManager.fill(HIST("clusterTM_EoverP_ep"), eOverP, match.track_as().pt(), t); - if (match.track_as().eta() >= 0.) { - mHistManager.fill(HIST("clusterTM_EoverP_electron_ASide"), eOverP, match.track_as().pt(), t); - mHistManager.fill(HIST("clusterTM_NSigma_electron_ASide"), NSigmaEl, match.track_as().pt(), t); + mHistManager.fill(HIST("clusterTM_EoverP_ep"), eOverP, match.track_as().pt(), t); + if (match.track_as().eta() >= 0.) { + mHistManager.fill(HIST("clusterTM_EoverP_electron_ASide"), eOverP, match.track_as().pt(), t); + mHistManager.fill(HIST("clusterTM_NSigma_electron_ASide"), nSigmaEl, match.track_as().pt(), t); } else { - mHistManager.fill(HIST("clusterTM_EoverP_electron_CSide"), eOverP, match.track_as().pt(), t); - mHistManager.fill(HIST("clusterTM_NSigma_electron_CSide"), NSigmaEl, match.track_as().pt(), t); + mHistManager.fill(HIST("clusterTM_EoverP_electron_CSide"), eOverP, match.track_as().pt(), t); + mHistManager.fill(HIST("clusterTM_NSigma_electron_CSide"), nSigmaEl, match.track_as().pt(), t); } - if (match.track_as().sign() == -1) { - mHistManager.fill(HIST("clusterTM_EoverP_e"), eOverP, match.track_as().pt(), t); - mHistManager.fill(HIST("clusterTM_NSigma_e"), NSigmaEl, match.track_as().pt(), t); + if (match.track_as().sign() == -1) { + mHistManager.fill(HIST("clusterTM_EoverP_e"), eOverP, match.track_as().pt(), t); + mHistManager.fill(HIST("clusterTM_NSigma_e"), nSigmaEl, match.track_as().pt(), t); if (eOverPRange->at(0) <= eOverP && eOverP <= eOverPRange->at(1)) { - mHistManager.fill(HIST("clusterTM_NSigma_e_cut"), NSigmaEl, match.track_as().pt(), t); + mHistManager.fill(HIST("clusterTM_NSigma_e_cut"), nSigmaEl, match.track_as().pt(), t); } - } else if (match.track_as().sign() == +1) { - mHistManager.fill(HIST("clusterTM_EoverP_p"), eOverP, match.track_as().pt(), t); - mHistManager.fill(HIST("clusterTM_NSigma_p"), NSigmaEl, match.track_as().pt(), t); + } else if (match.track_as().sign() == +1) { + mHistManager.fill(HIST("clusterTM_EoverP_p"), eOverP, match.track_as().pt(), t); + mHistManager.fill(HIST("clusterTM_NSigma_p"), nSigmaEl, match.track_as().pt(), t); if (eOverPRange->at(0) <= eOverP && eOverP <= eOverPRange->at(1)) { - mHistManager.fill(HIST("clusterTM_NSigma_p_cut"), NSigmaEl, match.track_as().pt(), t); + mHistManager.fill(HIST("clusterTM_NSigma_p_cut"), nSigmaEl, match.track_as().pt(), t); } } } - } else if (tpcNsigmaBack->at(0) <= NSigmaEl && NSigmaEl <= tpcNsigmaBack->at(1)) { // E/p for hadrons / background - mHistManager.fill(HIST("clusterTM_EoverP_hadron"), eOverP, match.track_as().pt(), t); - if (match.track_as().eta() >= 0.) { - mHistManager.fill(HIST("clusterTM_EoverP_hadron_ASide"), eOverP, match.track_as().pt(), t); + } else if (tpcNsigmaBack->at(0) <= nSigmaEl && nSigmaEl <= tpcNsigmaBack->at(1)) { // E/p for hadrons / background + mHistManager.fill(HIST("clusterTM_EoverP_hadron"), eOverP, match.track_as().pt(), t); + if (match.track_as().eta() >= 0.) { + mHistManager.fill(HIST("clusterTM_EoverP_hadron_ASide"), eOverP, match.track_as().pt(), t); } else { - mHistManager.fill(HIST("clusterTM_EoverP_hadron_CSide"), eOverP, match.track_as().pt(), t); + mHistManager.fill(HIST("clusterTM_EoverP_hadron_CSide"), eOverP, match.track_as().pt(), t); } - if (match.track_as().sign() == -1) { - mHistManager.fill(HIST("clusterTM_EoverP_hn"), eOverP, match.track_as().pt(), t); - } else if (match.track_as().sign() == +1) { - mHistManager.fill(HIST("clusterTM_EoverP_hp"), eOverP, match.track_as().pt(), t); + if (match.track_as().sign() == -1) { + mHistManager.fill(HIST("clusterTM_EoverP_hn"), eOverP, match.track_as().pt(), t); + } else if (match.track_as().sign() == +1) { + mHistManager.fill(HIST("clusterTM_EoverP_hp"), eOverP, match.track_as().pt(), t); } } t++; @@ -459,12 +444,11 @@ struct TrackMatchingMonitor { mHistManager.fill(HIST("clusterTM_NTrack"), t); } } - PROCESS_SWITCH(TrackMatchingMonitor, processCollisions, "Process clusters from collision", true); + PROCESS_SWITCH(EmcTmMonitor, processCollisions, "Process clusters from collision", true); /// \brief Create binning for cluster energy axis (variable bin size) /// \return vector with bin limits - std::vector - makeEnergyBinning() const + std::vector makeEnergyBinning() const { auto fillBinLimits = [](std::vector& binlimits, double max, double binwidth) { auto current = *binlimits.rbegin(); @@ -491,26 +475,27 @@ struct TrackMatchingMonitor { { std::vector result; - Int_t nBinsClusterE = 235; - for (Int_t i = 0; i < nBinsClusterE + 1; i++) { - if (i < 1) + int nBinsClusterE = 235; + for (int i = 0; i < nBinsClusterE + 1; i++) { + if (i < 1) { // o2-linter: disable=magic-number (just numbers for binning) result.emplace_back(0.3 * i); - else if (i < 55) + } else if (i < 55) { // o2-linter: disable=magic-number (just numbers for binning) result.emplace_back(0.3 + 0.05 * (i - 1)); - else if (i < 105) + } else if (i < 105) { // o2-linter: disable=magic-number (just numbers for binning) result.emplace_back(3. + 0.1 * (i - 55)); - else if (i < 140) + } else if (i < 140) { // o2-linter: disable=magic-number (just numbers for binning) result.emplace_back(8. + 0.2 * (i - 105)); - else if (i < 170) + } else if (i < 170) { // o2-linter: disable=magic-number (just numbers for binning) result.emplace_back(15. + 0.5 * (i - 140)); - else if (i < 190) + } else if (i < 190) { // o2-linter: disable=magic-number (just numbers for binning) result.emplace_back(30. + 1.0 * (i - 170)); - else if (i < 215) + } else if (i < 215) { // o2-linter: disable=magic-number (just numbers for binning) result.emplace_back(50. + 2.0 * (i - 190)); - else if (i < 235) + } else if (i < 235) { // o2-linter: disable=magic-number (just numbers for binning) result.emplace_back(100. + 5.0 * (i - 215)); - else if (i < 245) + } else if (i < 245) { // o2-linter: disable=magic-number (just numbers for binning) result.emplace_back(200. + 10.0 * (i - 235)); + } } return result; } @@ -524,20 +509,21 @@ struct TrackMatchingMonitor { result.reserve(1000); double epsilon = 1e-6; double valGammaPt = 0; - for (int i = 0; i < 1000; ++i) { + for (int i = 0; i < 1000; ++i) { // o2-linter: disable=magic-number (just numbers for binning) result.push_back(valGammaPt); - if (valGammaPt < 1.0 - epsilon) + if (valGammaPt < 1.0 - epsilon) { // o2-linter: disable=magic-number (just numbers for binning) valGammaPt += 0.1; - else if (valGammaPt < 5 - epsilon) + } else if (valGammaPt < 5 - epsilon) { // o2-linter: disable=magic-number (just numbers for binning) valGammaPt += 0.2; - else if (valGammaPt < 10 - epsilon) + } else if (valGammaPt < 10 - epsilon) { // o2-linter: disable=magic-number (just numbers for binning) valGammaPt += 0.5; - else if (valGammaPt < 50 - epsilon) + } else if (valGammaPt < 50 - epsilon) { // o2-linter: disable=magic-number (just numbers for binning) valGammaPt += 1; - else if (valGammaPt < 100 - epsilon) + } else if (valGammaPt < 100 - epsilon) { // o2-linter: disable=magic-number (just numbers for binning) valGammaPt += 5; - else + } else { break; + } } return result; } @@ -546,6 +532,6 @@ struct TrackMatchingMonitor { WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) { WorkflowSpec workflow{ - adaptAnalysisTask(cfgc, TaskName{"emc-tmmonitor"})}; + adaptAnalysisTask(cfgc)}; return workflow; }