Skip to content

Commit b1b7e8d

Browse files
authored
[PWGJE,EMCAL-670] Fix emcalcorrectiontask when running over JJ MC (#12381)
1 parent f84b010 commit b1b7e8d

File tree

5 files changed

+212
-12
lines changed

5 files changed

+212
-12
lines changed

PWGJE/Core/utilsBcSelEMC.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ enum EventRejection {
4444
NEventRejection
4545
};
4646

47-
o2::framework::AxisSpec axisEvents = {EventRejection::NEventRejection, -0.5f, +EventRejection::NEventRejection - 0.5f, ""};
47+
inline o2::framework::AxisSpec axisEvents = {EventRejection::NEventRejection, -0.5f, +EventRejection::NEventRejection - 0.5f, ""};
4848

4949
/// \brief Function to put labels on monitoring histogram
5050
/// \param hRejection monitoring histogram

PWGJE/Core/utilsTrackMatchingEMC.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -63,10 +63,6 @@ MatchResult matchTracksToCluster(
6363
const std::size_t nTracks = trackEta.size();
6464
MatchResult result;
6565

66-
result.matchIndexTrack.resize(nClusters);
67-
result.matchDeltaPhi.resize(nClusters);
68-
result.matchDeltaEta.resize(nClusters);
69-
7066
if (nClusters == 0 || nTracks == 0) {
7167
// There are no jets, so nothing to be done.
7268
return result;
@@ -79,6 +75,10 @@ MatchResult matchTracksToCluster(
7975
throw std::invalid_argument("track collection eta and phi sizes don't match. Check the inputs.");
8076
}
8177

78+
result.matchIndexTrack.resize(nClusters);
79+
result.matchDeltaPhi.resize(nClusters);
80+
result.matchDeltaEta.resize(nClusters);
81+
8282
// Build the KD-trees using vectors
8383
// We build two trees:
8484
// treeBase, which contains the base collection.

PWGJE/TableProducer/emcalCorrectionTask.cxx

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -577,9 +577,8 @@ struct EmcalCorrectionTask {
577577
// Adding -1 and later when filling the clusterID<->cellID table skip all cases where this is -1
578578
if (cellIndicesBC.size() < cellsBC.size()) {
579579
cellIndicesBC.reserve(cellsBC.size());
580-
for (size_t iMissing = 0; iMissing < (cellsBC.size() - cellIndicesBC.size()); ++iMissing) {
581-
cellIndicesBC.emplace_back(-1);
582-
}
580+
size_t nMissing = cellsBC.size() - cellIndicesBC.size();
581+
cellIndicesBC.insert(cellIndicesBC.end(), nMissing, -1);
583582
}
584583
if (emcCrossTalkConf.createHistograms.value) {
585584
for (const auto& cell : cellsBC) {
@@ -877,10 +876,12 @@ struct EmcalCorrectionTask {
877876
mHistManager.fill(HIST("hClusterFCrossSigmaShortE"), cluster.E(), cluster.getFCross(), cluster.getM20());
878877
}
879878
if (indexMapPair && trackGlobalIndex) {
880-
for (unsigned int iTrack = 0; iTrack < indexMapPair->matchIndexTrack[iCluster].size(); iTrack++) {
881-
if (indexMapPair->matchIndexTrack[iCluster][iTrack] >= 0) {
882-
LOG(debug) << "Found track " << (*trackGlobalIndex)[indexMapPair->matchIndexTrack[iCluster][iTrack]] << " in cluster " << cluster.getID();
883-
matchedTracks(clusters.lastIndex(), (*trackGlobalIndex)[indexMapPair->matchIndexTrack[iCluster][iTrack]], indexMapPair->matchDeltaPhi[iCluster][iTrack], indexMapPair->matchDeltaEta[iCluster][iTrack]);
879+
if (iCluster < indexMapPair->matchIndexTrack.size() && indexMapPair->matchIndexTrack.size() > 0) {
880+
for (unsigned int iTrack = 0; iTrack < indexMapPair->matchIndexTrack[iCluster].size(); iTrack++) {
881+
if (indexMapPair->matchIndexTrack[iCluster][iTrack] >= 0) {
882+
LOG(debug) << "Found track " << (*trackGlobalIndex)[indexMapPair->matchIndexTrack[iCluster][iTrack]] << " in cluster " << cluster.getID();
883+
matchedTracks(clusters.lastIndex(), (*trackGlobalIndex)[indexMapPair->matchIndexTrack[iCluster][iTrack]], indexMapPair->matchDeltaPhi[iCluster][iTrack], indexMapPair->matchDeltaEta[iCluster][iTrack]);
884+
}
884885
}
885886
}
886887
}

PWGJE/Tasks/CMakeLists.txt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,10 @@ o2physics_add_dpl_workflow(photon-charged-trigger-correlation
5454
SOURCES photonChargedTriggerCorrelation.cxx
5555
PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore
5656
COMPONENT_NAME Analysis)
57+
o2physics_add_dpl_workflow(task-emc-extensive-mc-qa
58+
SOURCES taskEmcExtensiveMcQa.cxx
59+
PUBLIC_LINK_LIBRARIES O2::Framework O2::EMCALBase O2Physics::AnalysisCore O2Physics::EventFilteringUtils
60+
COMPONENT_NAME Analysis)
5761

5862
if(FastJet_FOUND)
5963
o2physics_add_dpl_workflow(jet-background-analysis
Lines changed: 195 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,195 @@
1+
// Copyright 2019-2020 CERN and copyright holders of ALICE O2.
2+
// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders.
3+
// All rights not expressly granted are reserved.
4+
//
5+
// This software is distributed under the terms of the GNU General Public
6+
// License v3 (GPL Version 3), copied verbatim in the file "COPYING".
7+
//
8+
// In applying this license CERN does not waive the privileges and immunities
9+
// granted to it by virtue of its status as an Intergovernmental Organization
10+
// or submit itself to any jurisdiction.
11+
12+
/// \file taskEmcExtensiveMcQa.cxx
13+
/// \brief Exensive monitoring task for EMCal clusters in MC
14+
/// \author Marvin Hemmer <marvin.hemmer@cern.ch>, Goethe University Frankfurt
15+
/// \since 31.07.2025
16+
17+
#include "PWGJE/DataModel/EMCALClusters.h"
18+
// HF headers for event selection
19+
#include "PWGHF/Core/CentralityEstimation.h"
20+
#include "PWGHF/Utils/utilsEvSelHf.h"
21+
22+
#include "Common/CCDB/ctpRateFetcher.h"
23+
#include "Common/DataModel/EventSelection.h"
24+
25+
#include <CCDB/BasicCCDBManager.h>
26+
#include <CommonConstants/MathConstants.h>
27+
#include <EMCALBase/Geometry.h>
28+
#include <Framework/ASoA.h>
29+
#include <Framework/AnalysisDataModel.h>
30+
#include <Framework/AnalysisHelpers.h>
31+
#include <Framework/AnalysisTask.h>
32+
#include <Framework/Configurable.h>
33+
#include <Framework/HistogramRegistry.h>
34+
#include <Framework/HistogramSpec.h>
35+
#include <Framework/InitContext.h>
36+
#include <Framework/runDataProcessing.h>
37+
38+
#include <algorithm>
39+
#include <array>
40+
#include <climits>
41+
#include <cmath>
42+
#include <cstdlib>
43+
#include <string>
44+
#include <vector>
45+
46+
using namespace o2::aod;
47+
using namespace o2::framework;
48+
using namespace o2::framework::expressions;
49+
using namespace o2::hf_evsel;
50+
using namespace o2::hf_centrality;
51+
using CollisionEvSels = o2::soa::Join<o2::aod::Collisions, o2::aod::EvSels>;
52+
using BcEvSelIt = o2::soa::Join<o2::aod::BCs, o2::aod::BcSels>::iterator;
53+
using SelectedClusters = o2::soa::Filtered<o2::soa::Join<o2::aod::EMCALClusters, o2::aod::EMCALMCClusters>>;
54+
55+
enum PoI {
56+
kPhoton = 0,
57+
kElectron = 1,
58+
kHadron = 2,
59+
kNPoI = 3
60+
};
61+
62+
/// \struct TaskEmcExtensiveMcQa
63+
struct TaskEmcExtensiveMcQa {
64+
65+
static constexpr int NSM = 20; // there 20 supermodlues for the EMCal
66+
std::array<int, 2> arrPoIPDG = {22, 11};
67+
68+
SliceCache cache;
69+
Preslice<SelectedClusters> psClusterPerCollision = o2::aod::emcalcluster::collisionId;
70+
Preslice<o2::aod::EMCALClusterCells> perCluster = o2::aod::emcalclustercell::emcalclusterId;
71+
72+
HistogramRegistry mHistManager{"EMCalExtensiveMCQAHistograms"};
73+
74+
o2::emcal::Geometry* mGeometry = nullptr;
75+
o2::framework::Service<o2::ccdb::BasicCCDBManager> ccdb;
76+
77+
ctpRateFetcher rateFetcher;
78+
HfEventSelection hfEvSel;
79+
HfEventSelectionMc hfEvSelMc;
80+
81+
// configurable parameters
82+
Configurable<bool> applyEvSels{"applyEvSels", true, "Flag to apply event selection."};
83+
Configurable<int> clusterDefinition{"clusterDefinition", 10, "cluster definition to be selected, e.g. 10=kV3Default"};
84+
Configurable<std::string> ctpFetcherSource{"ctpFetcherSource", "T0VTX", "Source for CTP rate fetching, e.g. T0VTX, T0CE, T0SC, ZNC (hadronic)"};
85+
Configurable<std::string> ccdbUrl{"ccdbUrl", "http://alice-ccdb.cern.ch", "url of the ccdb repository"};
86+
87+
// configurable axis
88+
ConfigurableAxis nClustersBinning{"nClustersBinning", {201, -0.5, 200.5}, "binning for the number of clusters"};
89+
90+
ConfigurableAxis clusterEnergy{"clusterEnergy", {100, 0., 10}, "binning for the cluster energy in GeV"};
91+
ConfigurableAxis clusterTimeBinning{"clusterTimeBinning", {1500, -600, 900}, "binning for the cluster time in ns"};
92+
ConfigurableAxis clusterM02{"clusterM02", {100, 0., 2.0}, "binning for the cluster M02"};
93+
ConfigurableAxis clusterNCellBinning{"clusterNCellBinning", {100, 0.5, 100.5}, "binning for the number of cells per cluster"};
94+
ConfigurableAxis clusterOriginRadius{"clusterOriginRadius", {225, 0., 450}, "binning for the radial original point of the main contributor of a cluster"};
95+
96+
std::vector<float> mCellTime;
97+
98+
/// \brief Create output histograms and initialize geometry
99+
void init(InitContext const&)
100+
{
101+
// load geometry just in case we need it
102+
mGeometry = o2::emcal::Geometry::GetInstanceFromRunNumber(300000);
103+
104+
// create common axes
105+
const AxisSpec numberClustersAxis{nClustersBinning, "#it{N}_{cl}/ #it{N}_{event}"};
106+
const AxisSpec axisParticle = {PoI::kNPoI, -0.5f, +PoI::kNPoI - 0.5f, ""};
107+
const AxisSpec axisEnergy{clusterEnergy, "#it{E}_{cl} (GeV)"};
108+
const AxisSpec axisTime{clusterTimeBinning, "#it{t}_{cl} (ns)"};
109+
const AxisSpec axisM02{clusterM02, "#it{M}_{02}"};
110+
const AxisSpec axisNCell{clusterNCellBinning, "#it{N}_{cells}"};
111+
const AxisSpec axisRadius{clusterOriginRadius, "#it{R}_{origin} (cm)"};
112+
113+
// create histograms
114+
115+
// event properties
116+
mHistManager.add("numberOfClustersEvents", "number of clusters per event (selected events)", HistType::kTH1D, {numberClustersAxis});
117+
118+
// cluster properties (matched clusters)
119+
mHistManager.add("hSparseClusterQA", "THn for Cluster QA", HistType::kTHnSparseF, {axisEnergy, axisTime, axisM02, axisNCell, axisRadius, axisParticle});
120+
mHistManager.add("clusterEtaPhi", "Eta and phi of cluster", HistType::kTH2F, {{140, -0.7, 0.7}, {360, 0, o2::constants::math::TwoPI}});
121+
122+
hfEvSel.addHistograms(mHistManager);
123+
124+
ccdb->setURL(ccdbUrl);
125+
ccdb->setCaching(true);
126+
ccdb->setLocalObjectValidityChecking();
127+
}
128+
129+
template <typename Coll>
130+
bool isCollSelected(const Coll& coll)
131+
{
132+
float cent{-1.f};
133+
const auto rejectionMask = hfEvSel.getHfCollisionRejectionMask<true, o2::hf_centrality::CentralityEstimator::None, aod::BCsWithTimestamps>(coll, cent, ccdb, mHistManager);
134+
/// monitor the satisfied event selections
135+
hfEvSel.fillHistograms(coll, rejectionMask, cent);
136+
return rejectionMask == 0;
137+
}
138+
139+
/// \brief returns the PoI type of a mcparticle
140+
/// \param mcparticle is the mcparticle we want to find the PoI type
141+
/// \param mcparticles table containing the mcparticles
142+
/// \return PoI type of the given mcparticle
143+
template <typename T, typename TMCs>
144+
int findPoIType(T const& mcparticle, TMCs const& mcparticles)
145+
{
146+
if (!mcparticle.has_mothers()) {
147+
return -1;
148+
}
149+
150+
int motherid = mcparticle.mothersIds()[0];
151+
auto mother = mcparticles.iteratorAt(motherid);
152+
auto it = std::find(arrPoIPDG.begin(), arrPoIPDG.end(), std::abs(mother.pdgCode()));
153+
if (it != arrPoIPDG.end()) {
154+
return *it;
155+
} else {
156+
return PoI::kHadron;
157+
}
158+
}
159+
160+
Filter clusterDefinitionSelection = (o2::aod::emcalcluster::definition == clusterDefinition);
161+
162+
/// \brief Process EMCAL clusters that are matched to a collisions
163+
void processCollisions(CollisionEvSels const& collisions, SelectedClusters const& clusters, McParticles const& mcparticles)
164+
{
165+
166+
for (const auto& collision : collisions) {
167+
if (applyEvSels && !isCollSelected(collision)) {
168+
continue;
169+
}
170+
171+
auto groupedClusters = clusters.sliceBy(psClusterPerCollision, collision.globalIndex());
172+
mHistManager.fill(HIST("numberOfClustersEvents"), groupedClusters.size());
173+
174+
for (const auto& cluster : groupedClusters) {
175+
mHistManager.fill(HIST("clusterEtaPhi"), cluster.eta(), cluster.phi());
176+
// axisEnergy, axisTime, axisM02, axisNCell, axisRadius, axisParticle
177+
if (cluster.mcParticle().size() == 0) {
178+
LOG(info) << "Somehow cluster.mcParticle().size() == 0!";
179+
continue;
180+
}
181+
auto mainMcParticle = cluster.mcParticle_as<McParticles>()[0];
182+
float radius = std::hypot(mainMcParticle.px(), mainMcParticle.py());
183+
mHistManager.fill(HIST("hSparseClusterQA"), cluster.energy(), cluster.time(), cluster.m02(), cluster.nCells(), radius, findPoIType(mainMcParticle, mcparticles));
184+
}
185+
}
186+
}
187+
PROCESS_SWITCH(TaskEmcExtensiveMcQa, processCollisions, "Process clusters from collision", true);
188+
};
189+
190+
WorkflowSpec defineDataProcessing(ConfigContext const& cfgc)
191+
{
192+
WorkflowSpec workflow{
193+
adaptAnalysisTask<TaskEmcExtensiveMcQa>(cfgc)};
194+
return workflow;
195+
}

0 commit comments

Comments
 (0)