From ba45bb1a5cf7c0a408a9e07c51c97cd0bdce5cf6 Mon Sep 17 00:00:00 2001 From: Marvin Hemmer Date: Sat, 12 Sep 2026 10:26:34 +0200 Subject: [PATCH 1/3] [PWGJE,EMCAL] Add new clusterizer definitions, add new table and QA plots for cluster dispersion and update M02 and M20 QA plots to 2D plots - Add new clusterizer definitions - Add new tables for the clusters and the ambigous clusters to store the cluster dispersion - Add new QA plot for dispersion as function of energy and add energy as new dimension to the M02 and M20 plots --- PWGJE/DataModel/EMCALClusters.h | 19 +++++++ PWGJE/TableProducer/emcalCorrectionTask.cxx | 57 +++++++++++++++++--- PWGJE/Tasks/emcClusterMonitor.cxx | 59 ++++++++++++--------- 3 files changed, 101 insertions(+), 34 deletions(-) diff --git a/PWGJE/DataModel/EMCALClusters.h b/PWGJE/DataModel/EMCALClusters.h index 915eecaca51..6e7dd16d676 100644 --- a/PWGJE/DataModel/EMCALClusters.h +++ b/PWGJE/DataModel/EMCALClusters.h @@ -50,6 +50,9 @@ inline const EMCALClusterDefinition kV3SmallestTimeDiff(ClusterAlgorithm::kV3, 4 inline const EMCALClusterDefinition kV3MostSplitSmallTimeDiff(ClusterAlgorithm::kV3, 43, 1, "kV3MostSplitSmallTimeDiff", 0.5, 0.1, -10000, 10000, 500, true, 0., false); inline const EMCALClusterDefinition kV3MostSplitSmallerTimeDiff(ClusterAlgorithm::kV3, 44, 1, "kV3MostSplitSmallerTimeDiff", 0.5, 0.1, -10000, 10000, 100, true, 0., false); inline const EMCALClusterDefinition kV3MostSplitSmallestTimeDiff(ClusterAlgorithm::kV3, 45, 1, "kV3MostSplitSmallestTimeDiff", 0.5, 0.1, -10000, 10000, 50, true, 0., false); +inline const EMCALClusterDefinition kV3SmallTimeDiffLowestSeed(ClusterAlgorithm::kV3, 46, 1, "kV3SmallTimeDiffLowestSeed", 0.1, 0.1, -10000, 10000, 500, true, 0.03, false); +inline const EMCALClusterDefinition kV3SmallerTimeDiffLowSeed(ClusterAlgorithm::kV3, 47, 1, "kV3SmallerTimeDiffLowSeed", 0.3, 0.1, -10000, 10000, 100, true, 0.03, false); +inline const EMCALClusterDefinition kV3SmallestTimeDiffLowerSeed(ClusterAlgorithm::kV3, 48, 1, "kV3SmallestTimeDiffLowerSeed", 0.2, 0.1, -10000, 10000, 50, true, 0.03, false); inline const EMCALClusterDefinition kV3MostSplitSmallestTimeDiffLowestSeed(ClusterAlgorithm::kV3, 50, 1, "kV3MostSplitSmallestTimeDiffLowestSeed", 0.1, 0.1, -10000, 10000, 50, true, 0., false); inline const EMCALClusterDefinition kV3MostSplitSmallestTimeDiffLowSeed(ClusterAlgorithm::kV3, 51, 1, "kV3MostSplitSmallestTimeDiffLowSeed", 0.3, 0.1, -10000, 10000, 50, true, 0., false); inline const EMCALClusterDefinition kV3MostSplitSmallestTimeDiffLowerSeed(ClusterAlgorithm::kV3, 52, 1, "kV3MostSplitSmallestTimeDiffLowerSeed", 0.2, 0.1, -10000, 10000, 50, true, 0., false); @@ -94,6 +97,12 @@ inline const EMCALClusterDefinition& getClusterDefinitionFromID(int storageID) return kV3MostSplitSmallerTimeDiff; case 45: return kV3MostSplitSmallestTimeDiff; + case 46: + return kV3SmallTimeDiffLowestSeed; + case 47: + return kV3SmallerTimeDiffLowSeed; + case 48: + return kV3SmallestTimeDiffLowerSeed; case 50: return kV3MostSplitSmallestTimeDiffLowestSeed; case 51: @@ -128,6 +137,9 @@ inline const EMCALClusterDefinition& getClusterDefinitionFromString(const std::s {"kV3MostSplitSmallTimeDiff", 43}, {"kV3MostSplitSmallerTimeDiff", 44}, {"kV3MostSplitSmallestTimeDiff", 45}, + {"kV3SmallTimeDiffLowestSeed", 46}, + {"kV3SmallerTimeDiffLowSeed", 47}, + {"kV3SmallestTimeDiffLowerSeed", 48}, {"kV3MostSplitSmallestTimeDiffLowestSeed", 50}, {"kV3MostSplitSmallestTimeDiffLowSeed", 51}, {"kV3MostSplitSmallestTimeDiffLowerSeed", 52}, @@ -156,6 +168,7 @@ DECLARE_SOA_COLUMN(IsExotic, isExotic, bool); //! flag DECLARE_SOA_COLUMN(DistanceToBadChannel, distanceToBadChannel, float); //! distance to bad channel DECLARE_SOA_COLUMN(NLM, nlm, int); //! number of local maxima DECLARE_SOA_COLUMN(Definition, definition, int); //! cluster definition, see EMCALClusterDefinition.h +DECLARE_SOA_COLUMN(Dispersion, dispersion, float); //! cluster energy dispersion (cells) } // namespace emcalcluster // table of clusters that could be matched to a collision @@ -174,6 +187,12 @@ DECLARE_SOA_TABLE(EMCALAmbiguousClusters, "AOD", "EMCALAMBCLUS", //! using EMCALCluster = EMCALClusters::iterator; using EMCALAmbiguousCluster = EMCALAmbiguousClusters::iterator; +DECLARE_SOA_TABLE(Dispersions, "AOD", "DISPERSIONS", //! + o2::soa::Index<>, emcalcluster::Dispersion); + +DECLARE_SOA_TABLE(AmbigousDispersions, "AOD", "AMBDISPERSIONS", //! + o2::soa::Index<>, emcalcluster::Dispersion); + namespace emcalclustermc { DECLARE_SOA_ARRAY_INDEX_COLUMN(McParticle, mcParticle); //! Array of MC particles that deposited energy in this calo cell diff --git a/PWGJE/TableProducer/emcalCorrectionTask.cxx b/PWGJE/TableProducer/emcalCorrectionTask.cxx index 258cbe8e80c..0aa66a9931a 100644 --- a/PWGJE/TableProducer/emcalCorrectionTask.cxx +++ b/PWGJE/TableProducer/emcalCorrectionTask.cxx @@ -45,6 +45,7 @@ #include #include #include +#include #include #include #include @@ -96,8 +97,10 @@ enum CellScaleMode { struct EmcalCorrectionTask { Produces clusters; Produces mcclusters; + Produces dispersions; Produces clustersAmbiguous; Produces mcclustersAmbiguous; + Produces ambigousDispersions; Produces clustercells; // cells belonging to given cluster Produces clustercellsambiguous; Produces matchedTracks; @@ -387,6 +390,10 @@ struct EmcalCorrectionTask { } } + auto hClusters = mHistManager.add("hClusters", "hClusters", O2HistType::kTH1D, {{2, -0.5, 1.5}}); + hClusters->GetXaxis()->SetBinLabel(1, "all clusters"); + hClusters->GetXaxis()->SetBinLabel(2, "cross boundary cluster"); + // For some runs, LG cells require an extra time shift of 2 * 8.8ns due to problems in the time calibration // Affected run ranges (inclusive) are initialised here (min,max) mExtraTimeShiftRunRanges.emplace_back(535365, 535645); // LHC23g-LHC23h @@ -422,7 +429,9 @@ struct EmcalCorrectionTask { { LOG(debug) << "Starting process full."; clusters.reserve(MaxClusterPerDFPerClusterizer * mClusterizers.size()); + dispersions.reserve(MaxClusterPerDFPerClusterizer * mClusterizers.size()); clustersAmbiguous.reserve(MaxAmbClusterPerDFPerClusterizer * mClusterizers.size()); + ambigousDispersions.reserve(MaxAmbClusterPerDFPerClusterizer * mClusterizers.size()); clustercells.reserve(MaxCellsPerClusterPerDFPerClusterizer * mClusterizers.size()); clustercellsambiguous.reserve(MaxCellsPerAmbClusterPerDFPerClusterizer * mClusterizers.size()); @@ -529,7 +538,7 @@ struct EmcalCorrectionTask { // Store the clusters in the table where a matching collision could // be identified. - fillClusterTable(col, vertexPos, iClusterizer, cellIndicesBC, &indexMapPair, &trackGlobalIndex); + fillClusterTable(col, vertexPos, iClusterizer, cellIndicesBC, cells, &indexMapPair, &trackGlobalIndex, nullptr, nullptr); } else { mHistManager.fill(HIST("hBCMatchErrors"), 2); } @@ -582,7 +591,9 @@ struct EmcalCorrectionTask { LOG(debug) << "Starting process full."; clusters.reserve(MaxClusterPerDFPerClusterizer * mClusterizers.size()); + dispersions.reserve(MaxClusterPerDFPerClusterizer * mClusterizers.size()); clustersAmbiguous.reserve(MaxAmbClusterPerDFPerClusterizer * mClusterizers.size()); + ambigousDispersions.reserve(MaxAmbClusterPerDFPerClusterizer * mClusterizers.size()); clustercells.reserve(MaxCellsPerClusterPerDFPerClusterizer * mClusterizers.size()); clustercellsambiguous.reserve(MaxCellsPerAmbClusterPerDFPerClusterizer * mClusterizers.size()); @@ -694,7 +705,7 @@ struct EmcalCorrectionTask { // Store the clusters in the table where a matching collision could // be identified. - fillClusterTable(col, vertexPos, iClusterizer, cellIndicesBC, &indexMapPair, &trackGlobalIndex, &indexMapPairSecondary, &secondaryGlobalIndex); + fillClusterTable(col, vertexPos, iClusterizer, cellIndicesBC, cells, &indexMapPair, &trackGlobalIndex, &indexMapPairSecondary, &secondaryGlobalIndex); } else { mHistManager.fill(HIST("hBCMatchErrors"), 2); } @@ -748,8 +759,10 @@ struct EmcalCorrectionTask { clusters.reserve(MaxClusterPerDFPerClusterizer * mClusterizers.size()); mcclusters.reserve(MaxClusterPerDFPerClusterizer * mClusterizers.size()); + dispersions.reserve(MaxClusterPerDFPerClusterizer * mClusterizers.size()); clustersAmbiguous.reserve(MaxAmbClusterPerDFPerClusterizer * mClusterizers.size()); mcclustersAmbiguous.reserve(MaxAmbClusterPerDFPerClusterizer * mClusterizers.size()); + ambigousDispersions.reserve(MaxAmbClusterPerDFPerClusterizer * mClusterizers.size()); clustercells.reserve(MaxCellsPerClusterPerDFPerClusterizer * mClusterizers.size()); clustercellsambiguous.reserve(MaxCellsPerAmbClusterPerDFPerClusterizer * mClusterizers.size()); @@ -891,7 +904,7 @@ struct EmcalCorrectionTask { // Store the clusters in the table where a matching collision could // be identified. - fillClusterTable(col, vertexPos, iClusterizer, cellIndicesBC, &indexMapPair, &trackGlobalIndex); + fillClusterTable(col, vertexPos, iClusterizer, cellIndicesBC, cells, &indexMapPair, &trackGlobalIndex); } else { mHistManager.fill(HIST("hBCMatchErrors"), 2); } @@ -943,8 +956,10 @@ struct EmcalCorrectionTask { clusters.reserve(MaxClusterPerDFPerClusterizer * mClusterizers.size()); mcclusters.reserve(MaxClusterPerDFPerClusterizer * mClusterizers.size()); + dispersions.reserve(MaxClusterPerDFPerClusterizer * mClusterizers.size()); clustersAmbiguous.reserve(MaxAmbClusterPerDFPerClusterizer * mClusterizers.size()); mcclustersAmbiguous.reserve(MaxAmbClusterPerDFPerClusterizer * mClusterizers.size()); + ambigousDispersions.reserve(MaxAmbClusterPerDFPerClusterizer * mClusterizers.size()); clustercells.reserve(MaxCellsPerClusterPerDFPerClusterizer * mClusterizers.size()); clustercellsambiguous.reserve(MaxCellsPerAmbClusterPerDFPerClusterizer * mClusterizers.size()); @@ -1088,7 +1103,7 @@ struct EmcalCorrectionTask { // Store the clusters in the table where a matching collision could // be identified. - fillClusterTable(col, vertexPos, iClusterizer, cellIndicesBC, &indexMapPair, &trackGlobalIndex, &indexMapPairSecondary, &secondaryGlobalIndex); + fillClusterTable(col, vertexPos, iClusterizer, cellIndicesBC, cells, &indexMapPair, &trackGlobalIndex, &indexMapPairSecondary, &secondaryGlobalIndex); } else { mHistManager.fill(HIST("hBCMatchErrors"), 2); } @@ -1139,7 +1154,9 @@ struct EmcalCorrectionTask { LOG(debug) << "Starting process standalone."; clusters.reserve(MaxClusterPerDFPerClusterizer * mClusterizers.size()); + dispersions.reserve(MaxClusterPerDFPerClusterizer * mClusterizers.size()); clustersAmbiguous.reserve(MaxAmbClusterPerDFPerClusterizer * mClusterizers.size()); + ambigousDispersions.reserve(MaxAmbClusterPerDFPerClusterizer * mClusterizers.size()); clustercells.reserve(MaxCellsPerClusterPerDFPerClusterizer * mClusterizers.size()); clustercellsambiguous.reserve(MaxCellsPerAmbClusterPerDFPerClusterizer * mClusterizers.size()); @@ -1234,7 +1251,7 @@ struct EmcalCorrectionTask { // Store the clusters in the table where a matching collision could // be identified. - fillClusterTable(col, vertexPos, iClusterizer, cellIndicesBC); + fillClusterTable(col, vertexPos, iClusterizer, cellIndicesBC, cells); } } else { // ambiguous // LOG(warning) << "No vertex found for event. Assuming (0,0,0)."; @@ -1303,12 +1320,11 @@ struct EmcalCorrectionTask { LOG(debug) << "Converted to analysis clusters."; } - template - 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, MatchResult* indexMapPairSecondaries = nullptr, const std::vector* secondariesGlobalIndex = nullptr) + template + void fillClusterTable(Collision const& col, math_utils::Point3D const& vertexPos, size_t iClusterizer, const gsl::span cellIndicesBC, Cells const& cells, MatchResult* indexMapPair = nullptr, const std::vector* trackGlobalIndex = nullptr, MatchResult* indexMapPairSecondaries = nullptr, const std::vector* secondariesGlobalIndex = nullptr) { // get the clusterType once const auto clusterType = static_cast(mClusterDefinitions[iClusterizer]); - int cellindex = -1; unsigned int iCluster = 0; float energy = 0.f; @@ -1341,16 +1357,40 @@ struct EmcalCorrectionTask { cluster.getClusterTime(), cluster.getIsExotic(), cluster.getDistanceToBadChannel(), cluster.getNExMax(), clusterType); + dispersions(cluster.getDispersion()); ++nCluster; + mHistManager.fill(HIST("hClusters"), 0); if (!mClusterLabels.empty()) { mcclusters(mClusterLabels[iCluster].getLabels(), mClusterLabels[iCluster].getEnergyFractions()); } // loop over cells in cluster and save to table + bool hasLargeDispersion = cluster.getDispersion() > 8; + if (hasLargeDispersion) { + mHistManager.fill(HIST("hClusters"), 1); + LOG(info) << "Found cluster with large dispersion = " << cluster.getDispersion() << "\t M02 = " << cluster.getM02() << "\t NCells = " << cluster.getNCells(); + } for (int ncell = 0; ncell < cluster.getNCells(); ncell++) { cellindex = cluster.getCellIndex(ncell); LOG(debug) << "trying to find cell index " << cellindex << " in map"; if (cellIndicesBC[cellindex] >= 0) { clustercells(clusters.lastIndex(), cellIndicesBC[cellindex]); + auto cellGlobalIndex = cellIndicesBC[cellindex]; + + if (hasLargeDispersion) { + auto theCell = cells.rawIteratorAt(cellGlobalIndex); + auto towerId = theCell.cellNumber(); + + auto [nSupMod, nModule, nIphi, nIeta] = geometry->GetCellIndex(towerId); + auto [iphiLocal, ietaLocal] = geometry->GetCellPhiEtaIndexInSModule(nSupMod, nModule, nIphi, nIeta); + auto [rowGlobal, colGlobal] = geometry->GlobalRowColFromIndex(towerId); + + LOG(info) << " Cell globalIndex = " << cellGlobalIndex + << " towerId = " << towerId + << " SM = " << nSupMod + << " local(eta, phi) = (" << ietaLocal << ", " << iphiLocal << ")" + << " global(eta, phi) = (" << colGlobal << ", " << rowGlobal << ")" + << " E = " << theCell.amplitude(); + } ++nCells; } } // end of cells of cluser loop @@ -1426,6 +1466,7 @@ struct EmcalCorrectionTask { cluster.getM20(), cluster.getNCells(), cluster.getClusterTime(), cluster.getIsExotic(), cluster.getDistanceToBadChannel(), cluster.getNExMax(), static_cast(mClusterDefinitions.at(iClusterizer))); + ambigousDispersions(cluster.getDispersion()); ++nClusterAmb; if (!mClusterLabels.empty()) { mcclustersAmbiguous(mClusterLabels[iCluster].getLabels(), mClusterLabels[iCluster].getEnergyFractions()); diff --git a/PWGJE/Tasks/emcClusterMonitor.cxx b/PWGJE/Tasks/emcClusterMonitor.cxx index b014ffae8fb..8820d975d6f 100644 --- a/PWGJE/Tasks/emcClusterMonitor.cxx +++ b/PWGJE/Tasks/emcClusterMonitor.cxx @@ -62,8 +62,8 @@ 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 selectedClusters = o2::soa::Filtered>; +using selectedAmbiguousClusters = o2::soa::Filtered>; struct ClusterMonitor { HistogramRegistry mHistManager{"ClusterMonitorHistograms"}; o2::emcal::Geometry* mGeometry = nullptr; @@ -104,6 +104,7 @@ struct ClusterMonitor { o2Axis numberClustersAxis{mNumberClusterBinning, "Number of clusters / event"}; const AxisSpec thAxisCellTimeDiff{3000, -1500, 1500, "#Delta#it{t}_{cell} (ns)"}; const AxisSpec thAxisCellTimeMean{1500, -600, 900, "#LT#it{t}_{cell}#GT (ns)"}; + const AxisSpec thAxisDispersion{100, 0, 10, "dispersion (cells)"}; // event properties mHistManager.add("eventsAll", "Number of events", o2HistType::kTH1D, {{1, 0.5, 1.5}}); @@ -124,8 +125,8 @@ struct ClusterMonitor { mHistManager.add("clusterESupermodule", "Energy of the cluster vs. supermoduleID", o2HistType::kTH2F, {energyAxis, supermoduleAxis}); mHistManager.add("clusterE_SimpleBinning", "Energy of cluster", o2HistType::kTH1D, {{2000, 0, 200}}); mHistManager.add("clusterEtaPhi", "Eta and phi of cluster", o2HistType::kTH2F, {{100, -1, 1}, {100, 0, 2 * TMath::Pi()}}); - mHistManager.add("clusterM02", "M02 of cluster", o2HistType::kTH1D, {{400, 0, 5}}); - mHistManager.add("clusterM20", "M20 of cluster", o2HistType::kTH1D, {{400, 0, 2.5}}); + mHistManager.add("clusterM02", "M02 of cluster;M_{02} (cells);#it{E} (GeV)", o2HistType::kTH2D, {{400, 0, 5}, {100, 0, 10}}); + mHistManager.add("clusterM20", "M20 of cluster", o2HistType::kTH2D, {{400, 0, 2.5}, {100, 0, 10}}); mHistManager.add("clusterNLM", "Number of local maxima of cluster", o2HistType::kTH1D, {{10, 0, 10}}); mHistManager.add("clusterNCells", "Number of cells in cluster", o2HistType::kTH1D, {{50, 0, 50}}); mHistManager.add("clusterDistanceToBadChannel", "Distance to bad channel", o2HistType::kTH1D, {{100, 0, 100}}); @@ -133,6 +134,7 @@ struct ClusterMonitor { mHistManager.add("clusterAmpFractionLeadingCell", "Fraction of energy in leading cell", o2HistType::kTH1D, {{100, 0, 1}}); mHistManager.add("clusterCellTimeDiff", "Cell time difference in clusters", o2HistType::kTH1D, {thAxisCellTimeDiff}); mHistManager.add("clusterCellTimeMean", "Mean cell time per cluster", o2HistType::kTH1D, {thAxisCellTimeMean}); + mHistManager.add("clusterDispersion", "Cluster dispersion vs energy", o2HistType::kTH2D, {thAxisDispersion, energyAxis}); // add histograms per supermodule for (int ism = 0; ism < 20; ++ism) { @@ -142,10 +144,10 @@ struct ClusterMonitor { mHistManager.add(Form("clusterM20VsESM/clusterM20VsESM%d", ism), Form("Cluster M20 vs energy in Supermodule %d", ism), o2HistType::kTH2F, {{400, 0, 2.5}, amplitudeAxisLarge}); } - if (mVetoBCID->length()) { + if (!mVetoBCID->empty()) { std::stringstream parser(mVetoBCID.value); std::string token; - int bcid; + int bcid = -1; while (std::getline(parser, token, ',')) { bcid = std::stoi(token); LOG(info) << "Veto BCID " << bcid; @@ -155,7 +157,7 @@ struct ClusterMonitor { if (mSelectBCID.value != "all") { std::stringstream parser(mSelectBCID.value); std::string token; - int bcid; + int bcid = -1; while (std::getline(parser, token, ',')) { bcid = std::stoi(token); LOG(info) << "Select BCID " << bcid; @@ -204,7 +206,7 @@ struct ClusterMonitor { mHistManager.fill(HIST("numberOfClustersEvents"), clusters.size()); LOG(debug) << "bunch crossing ID" << theCollision.bcId(); - std::array numberOfClustersSM; + std::array numberOfClustersSM{0}; std::fill(numberOfClustersSM.begin(), numberOfClustersSM.end(), 0); // loop over all clusters from accepted collision // auto eventClusters = clusters.select(o2::aod::emcalcluster::bcId == theCollision.bc().globalBC()); @@ -220,12 +222,13 @@ struct ClusterMonitor { mHistManager.fill(HIST("clusterE"), cluster.energy()); mHistManager.fill(HIST("clusterE_SimpleBinning"), cluster.energy()); mHistManager.fill(HIST("clusterEtaPhi"), cluster.eta(), cluster.phi()); - mHistManager.fill(HIST("clusterM02"), cluster.m02()); - mHistManager.fill(HIST("clusterM20"), cluster.m20()); + mHistManager.fill(HIST("clusterM02"), cluster.m02(), cluster.energy()); + mHistManager.fill(HIST("clusterM20"), cluster.m20(), cluster.energy()); mHistManager.fill(HIST("clusterTimeVsE"), cluster.time(), cluster.energy()); mHistManager.fill(HIST("clusterNLM"), cluster.nlm()); mHistManager.fill(HIST("clusterNCells"), cluster.nCells()); mHistManager.fill(HIST("clusterDistanceToBadChannel"), cluster.distanceToBadChannel()); + mHistManager.fill(HIST("clusterDispersion"), cluster.dispersion(), cluster.energy()); // loop over cells in cluster LOG(debug) << "Cluster energy: " << cluster.energy(); LOG(debug) << "Cluster index: " << cluster.index(); @@ -241,6 +244,7 @@ struct ClusterMonitor { } catch (o2::emcal::InvalidPositionException& e) { // Imprecision of the position at the sector boundaries, mostly due to // vertex imprecision. Skip these clusters for the now. + LOG(debug) << "Skipping cluster at sector boundary: " << e.what(); } // example of loop over all cells of current cluster @@ -290,7 +294,7 @@ struct ClusterMonitor { LOG(info) << "Event rejected because of veto BCID " << eventIR.bc; return; } - if (mSelectBCIDs.size() && (std::find(mSelectBCIDs.begin(), mSelectBCIDs.end(), eventIR.bc) == mSelectBCIDs.end())) { + if (!mSelectBCIDs.empty() && (std::find(mSelectBCIDs.begin(), mSelectBCIDs.end(), eventIR.bc) == mSelectBCIDs.end())) { return; } bool isSelected = true; @@ -311,19 +315,20 @@ struct ClusterMonitor { mHistManager.fill(HIST("eventBCSelected"), eventIR.bc); mHistManager.fill(HIST("numberOfClustersBC"), clusters.size()); - std::array numberOfClustersSM; + std::array numberOfClustersSM{0}; std::fill(numberOfClustersSM.begin(), numberOfClustersSM.end(), 0); // loop over ambiguous clusters for (const auto& cluster : clusters) { mHistManager.fill(HIST("clusterE"), cluster.energy()); mHistManager.fill(HIST("clusterE_SimpleBinning"), cluster.energy()); mHistManager.fill(HIST("clusterEtaPhi"), cluster.eta(), cluster.phi()); - mHistManager.fill(HIST("clusterM02"), cluster.m02()); - mHistManager.fill(HIST("clusterM20"), cluster.m20()); + mHistManager.fill(HIST("clusterM02"), cluster.m02(), cluster.energy()); + mHistManager.fill(HIST("clusterM20"), cluster.m20(), cluster.energy()); mHistManager.fill(HIST("clusterTimeVsE"), cluster.time(), cluster.energy()); mHistManager.fill(HIST("clusterNLM"), cluster.nlm()); mHistManager.fill(HIST("clusterNCells"), cluster.nCells()); mHistManager.fill(HIST("clusterDistanceToBadChannel"), cluster.distanceToBadChannel()); + mHistManager.fill(HIST("clusterDispersion"), cluster.dispersion(), cluster.energy()); try { auto supermoduleID = mGeometry->SuperModuleNumberFromEtaPhi(cluster.eta(), cluster.phi()); @@ -333,6 +338,7 @@ struct ClusterMonitor { } catch (o2::emcal::InvalidPositionException& e) { // Imprecision of the position at the sector boundaries, mostly due to // vertex imprecision. Skip these clusters for the now. + LOG(debug) << "Skipping cluster at sector boundary: " << e.what(); } } for (int supermoduleID = 0; supermoduleID < 20; supermoduleID++) { @@ -456,33 +462,34 @@ struct ClusterMonitor { std::vector result; Int_t nBinsClusterE = 235; for (Int_t i = 0; i < nBinsClusterE + 1; i++) { - if (i < 1) + if (i < 1) { result.emplace_back(0.3 * i); - else if (i < 55) + } else if (i < 55) { result.emplace_back(0.3 + 0.05 * (i - 1)); - else if (i < 105) + } else if (i < 105) { result.emplace_back(3. + 0.1 * (i - 55)); - else if (i < 140) + } else if (i < 140) { result.emplace_back(8. + 0.2 * (i - 105)); - else if (i < 170) + } else if (i < 170) { result.emplace_back(15. + 0.5 * (i - 140)); - else if (i < 190) + } else if (i < 190) { result.emplace_back(30. + 1.0 * (i - 170)); - else if (i < 215) + } else if (i < 215) { result.emplace_back(50. + 2.0 * (i - 190)); - else if (i < 235) + } else if (i < 235) { result.emplace_back(100. + 5.0 * (i - 215)); - else if (i < 245) + } else if (i < 245) { result.emplace_back(200. + 10.0 * (i - 235)); + } } return result; } }; -WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +WorkflowSpec defineDataProcessing(ConfigContext const& context) { WorkflowSpec workflow{ - adaptAnalysisTask(cfgc, TaskName{"EMCClusterMonitorTask"}, SetDefaultProcesses{{{"processCollisions", true}, {"processAmbiguous", false}}}), - adaptAnalysisTask(cfgc, TaskName{"EMCClusterMonitorTaskAmbiguous"}, SetDefaultProcesses{{{"processCollisions", false}, {"processAmbiguous", true}}})}; + adaptAnalysisTask(context, TaskName{"EMCClusterMonitorTask"}, SetDefaultProcesses{{{"processCollisions", true}, {"processAmbiguous", false}}}), + adaptAnalysisTask(context, TaskName{"EMCClusterMonitorTaskAmbiguous"}, SetDefaultProcesses{{{"processCollisions", false}, {"processAmbiguous", true}}})}; return workflow; } From 9a1e78c228761cd0322e90a02e2893e41a0b7a55 Mon Sep 17 00:00:00 2001 From: Marvin Hemmer Date: Thu, 17 Sep 2026 15:29:26 +0200 Subject: [PATCH 2/3] Remove local debug output --- PWGJE/TableProducer/emcalCorrectionTask.cxx | 42 ++++----------------- 1 file changed, 7 insertions(+), 35 deletions(-) diff --git a/PWGJE/TableProducer/emcalCorrectionTask.cxx b/PWGJE/TableProducer/emcalCorrectionTask.cxx index 0aa66a9931a..025bb78c868 100644 --- a/PWGJE/TableProducer/emcalCorrectionTask.cxx +++ b/PWGJE/TableProducer/emcalCorrectionTask.cxx @@ -390,10 +390,6 @@ struct EmcalCorrectionTask { } } - auto hClusters = mHistManager.add("hClusters", "hClusters", O2HistType::kTH1D, {{2, -0.5, 1.5}}); - hClusters->GetXaxis()->SetBinLabel(1, "all clusters"); - hClusters->GetXaxis()->SetBinLabel(2, "cross boundary cluster"); - // For some runs, LG cells require an extra time shift of 2 * 8.8ns due to problems in the time calibration // Affected run ranges (inclusive) are initialised here (min,max) mExtraTimeShiftRunRanges.emplace_back(535365, 535645); // LHC23g-LHC23h @@ -538,7 +534,7 @@ struct EmcalCorrectionTask { // Store the clusters in the table where a matching collision could // be identified. - fillClusterTable(col, vertexPos, iClusterizer, cellIndicesBC, cells, &indexMapPair, &trackGlobalIndex, nullptr, nullptr); + fillClusterTable(col, vertexPos, iClusterizer, cellIndicesBC, &indexMapPair, &trackGlobalIndex, nullptr, nullptr); } else { mHistManager.fill(HIST("hBCMatchErrors"), 2); } @@ -705,7 +701,7 @@ struct EmcalCorrectionTask { // Store the clusters in the table where a matching collision could // be identified. - fillClusterTable(col, vertexPos, iClusterizer, cellIndicesBC, cells, &indexMapPair, &trackGlobalIndex, &indexMapPairSecondary, &secondaryGlobalIndex); + fillClusterTable(col, vertexPos, iClusterizer, cellIndicesBC, &indexMapPair, &trackGlobalIndex, &indexMapPairSecondary, &secondaryGlobalIndex); } else { mHistManager.fill(HIST("hBCMatchErrors"), 2); } @@ -904,7 +900,7 @@ struct EmcalCorrectionTask { // Store the clusters in the table where a matching collision could // be identified. - fillClusterTable(col, vertexPos, iClusterizer, cellIndicesBC, cells, &indexMapPair, &trackGlobalIndex); + fillClusterTable(col, vertexPos, iClusterizer, cellIndicesBC, &indexMapPair, &trackGlobalIndex); } else { mHistManager.fill(HIST("hBCMatchErrors"), 2); } @@ -1103,7 +1099,7 @@ struct EmcalCorrectionTask { // Store the clusters in the table where a matching collision could // be identified. - fillClusterTable(col, vertexPos, iClusterizer, cellIndicesBC, cells, &indexMapPair, &trackGlobalIndex, &indexMapPairSecondary, &secondaryGlobalIndex); + fillClusterTable(col, vertexPos, iClusterizer, cellIndicesBC, &indexMapPair, &trackGlobalIndex, &indexMapPairSecondary, &secondaryGlobalIndex); } else { mHistManager.fill(HIST("hBCMatchErrors"), 2); } @@ -1251,7 +1247,7 @@ struct EmcalCorrectionTask { // Store the clusters in the table where a matching collision could // be identified. - fillClusterTable(col, vertexPos, iClusterizer, cellIndicesBC, cells); + fillClusterTable(col, vertexPos, iClusterizer, cellIndicesBC); } } else { // ambiguous // LOG(warning) << "No vertex found for event. Assuming (0,0,0)."; @@ -1320,8 +1316,8 @@ struct EmcalCorrectionTask { LOG(debug) << "Converted to analysis clusters."; } - template - void fillClusterTable(Collision const& col, math_utils::Point3D const& vertexPos, size_t iClusterizer, const gsl::span cellIndicesBC, Cells const& cells, MatchResult* indexMapPair = nullptr, const std::vector* trackGlobalIndex = nullptr, MatchResult* indexMapPairSecondaries = nullptr, const std::vector* secondariesGlobalIndex = nullptr) + template + 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, MatchResult* indexMapPairSecondaries = nullptr, const std::vector* secondariesGlobalIndex = nullptr) { // get the clusterType once const auto clusterType = static_cast(mClusterDefinitions[iClusterizer]); @@ -1359,38 +1355,14 @@ struct EmcalCorrectionTask { clusterType); dispersions(cluster.getDispersion()); ++nCluster; - mHistManager.fill(HIST("hClusters"), 0); if (!mClusterLabels.empty()) { mcclusters(mClusterLabels[iCluster].getLabels(), mClusterLabels[iCluster].getEnergyFractions()); } - // loop over cells in cluster and save to table - bool hasLargeDispersion = cluster.getDispersion() > 8; - if (hasLargeDispersion) { - mHistManager.fill(HIST("hClusters"), 1); - LOG(info) << "Found cluster with large dispersion = " << cluster.getDispersion() << "\t M02 = " << cluster.getM02() << "\t NCells = " << cluster.getNCells(); - } for (int ncell = 0; ncell < cluster.getNCells(); ncell++) { cellindex = cluster.getCellIndex(ncell); LOG(debug) << "trying to find cell index " << cellindex << " in map"; if (cellIndicesBC[cellindex] >= 0) { clustercells(clusters.lastIndex(), cellIndicesBC[cellindex]); - auto cellGlobalIndex = cellIndicesBC[cellindex]; - - if (hasLargeDispersion) { - auto theCell = cells.rawIteratorAt(cellGlobalIndex); - auto towerId = theCell.cellNumber(); - - auto [nSupMod, nModule, nIphi, nIeta] = geometry->GetCellIndex(towerId); - auto [iphiLocal, ietaLocal] = geometry->GetCellPhiEtaIndexInSModule(nSupMod, nModule, nIphi, nIeta); - auto [rowGlobal, colGlobal] = geometry->GlobalRowColFromIndex(towerId); - - LOG(info) << " Cell globalIndex = " << cellGlobalIndex - << " towerId = " << towerId - << " SM = " << nSupMod - << " local(eta, phi) = (" << ietaLocal << ", " << iphiLocal << ")" - << " global(eta, phi) = (" << colGlobal << ", " << rowGlobal << ")" - << " E = " << theCell.amplitude(); - } ++nCells; } } // end of cells of cluser loop From da7656dd7adfee2841bc087313aeb7a7422fc14b Mon Sep 17 00:00:00 2001 From: Marvin Hemmer Date: Thu, 17 Sep 2026 15:42:57 +0200 Subject: [PATCH 3/3] Use table and iterator concepts where applicable in templates --- PWGJE/TableProducer/emcalCorrectionTask.cxx | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/PWGJE/TableProducer/emcalCorrectionTask.cxx b/PWGJE/TableProducer/emcalCorrectionTask.cxx index 025bb78c868..985e622f7fa 100644 --- a/PWGJE/TableProducer/emcalCorrectionTask.cxx +++ b/PWGJE/TableProducer/emcalCorrectionTask.cxx @@ -407,7 +407,7 @@ struct EmcalCorrectionTask { } } - template + template void initZorroCCDB(const BCType& bc) { if (applySoftwareTriggerSelection) { @@ -1403,7 +1403,7 @@ struct EmcalCorrectionTask { } // end of cluster loop } - template + template void fillAmbigousClusterTable(BC const& bc, size_t iClusterizer, const gsl::span cellIndicesBC, bool hasCollision) { int cellindex = -1; @@ -1452,7 +1452,7 @@ struct EmcalCorrectionTask { } // end of cluster loop } - template + template void doTrackMatching(Collision const& col, MyGlobTracks const& tracks, MatchResult& indexMapPair, std::vector& trackGlobalIndex) { auto groupedTracks = tracks.sliceBy(perCollision, col.globalIndex()); @@ -1468,7 +1468,7 @@ struct EmcalCorrectionTask { indexMapPair = matchTracksToCluster(mClusterPhi, mClusterEta, trackPhi, trackEta, maxMatchingDistance, MaxMatchesPerCluster); } - template + template void doSecondaryTrackMatching(Collision const& col, EMV0Legs const& v0legs, MatchResult& indexMapPair, std::vector& trackGlobalIndex, MyGlobTracks const& tracks) { auto groupedV0Legs = v0legs.sliceBy(perCollisionEMV0Legs, col.globalIndex()); @@ -1504,7 +1504,7 @@ struct EmcalCorrectionTask { indexMapPair = matchTracksToCluster(mClusterPhi, mClusterEta, trackPhi, trackEta, maxMatchingDistance, MaxMatchesPerCluster); } - template + template void fillTrackInfo(Tracks const& tracks, std::vector& trackPhi, std::vector& trackEta, std::vector& trackGlobalIndex) { for (const auto& track : tracks) {