From 3fadf9a849ec63dbe78abf3d62c33b5bf120c355 Mon Sep 17 00:00:00 2001 From: Paola Vargas Torres Date: Tue, 28 Jul 2026 13:22:22 -0600 Subject: [PATCH 1/8] Add GoodITSLayersAll event cut and adjust myTrackSelection cuts --- PWGLF/Tasks/Nuspex/dedxPidAnalysis.cxx | 24 +++++++++++++++++++----- 1 file changed, 19 insertions(+), 5 deletions(-) diff --git a/PWGLF/Tasks/Nuspex/dedxPidAnalysis.cxx b/PWGLF/Tasks/Nuspex/dedxPidAnalysis.cxx index 2186703599f..aa012ec3dd6 100644 --- a/PWGLF/Tasks/Nuspex/dedxPidAnalysis.cxx +++ b/PWGLF/Tasks/Nuspex/dedxPidAnalysis.cxx @@ -140,6 +140,7 @@ struct DedxPidAnalysis { ZVtxCut, NoSameBunchPileup, GoodZvtxFT0vsPV, + GoodITS, INELgt }; @@ -204,7 +205,7 @@ struct DedxPidAnalysis { "max z distance to IP"}; Configurable etaMin{"etaMin", -0.8f, "etaMin"}; Configurable etaMax{"etaMax", +0.8f, "etaMax"}; - Configurable minNCrossedRowsOverFindableClustersTPC{"minNCrossedRowsOverFindableClustersTPC", 0.8f, "Additional cut on the minimum value of the ratio between crossed rows and findable clusters in the TPC"}; + // Configurable minNCrossedRowsOverFindableClustersTPC{"minNCrossedRowsOverFindableClustersTPC", 0.8f, "Additional cut on the minimum value of the ratio between crossed rows and findable clusters in the TPC"}; Configurable nSigmaDCAxy{"nSigmaDCAxy", 3.0, "nSigma DCAxy selection"}; Configurable dcaXYp0{"dcaXYp0", 0.0105f, "DCAxy formula: p0 + p1/pt^p2"}; Configurable dcaXYp1{"dcaXYp1", 0.0350f, "DCAxy p1 parameter"}; @@ -250,6 +251,7 @@ struct DedxPidAnalysis { Configurable nGoodZvtx{"nGoodZvtx", true, "Rejects events with no vertex match between FT0 and PV"}; // Configurable nPileUp{"nPileUp", true, "Rejects events with pileup in the same bunch crossing"}; Configurable nINELSelectionMode{"nINELSelectionMode", 2, "INEL event selection: 1 no sel, 2 INEL>0, 3 INEL>1"}; + Configurable nGoodITS{"nGoodITS", true, "Numbers of inactive chips on all ITS layers are below maximum allowed values"}; Configurable v0SelectionMode{"v0SelectionMode", 3, "V0 Selection base on TPC: 1, TOF:2 ,Both:3"}; Configurable momentumMode{"momentumMode", 2, "1: TPC inner param, 2: Total momentum p"}; Configurable v0TypeSelection{"v0TypeSelection", 1, "select on a certain V0 type (leave negative if no selection desired)"}; @@ -281,10 +283,10 @@ struct DedxPidAnalysis { TrackSelection selectedTracks; selectedTracks.SetPtRange(0.1f, 1e10f); selectedTracks.SetEtaRange(etaMin, etaMax); - selectedTracks.SetRequireITSRefit(true); - selectedTracks.SetRequireTPCRefit(true); + // selectedTracks.SetRequireITSRefit(true); + // selectedTracks.SetRequireTPCRefit(true); selectedTracks.SetMinNCrossedRowsTPC(static_cast(minNCrossedRowsTPC.value)); - selectedTracks.SetMinNCrossedRowsOverFindableClustersTPC(minNCrossedRowsOverFindableClustersTPC); + // selectedTracks.SetMinNCrossedRowsOverFindableClustersTPC(minNCrossedRowsOverFindableClustersTPC); selectedTracks.SetMaxChi2PerClusterTPC(maxChi2TPC); selectedTracks.SetRequireHitsInITSLayers(1, {0, 1, 2}); selectedTracks.SetMaxChi2PerClusterITS(maxChi2ITS); @@ -310,6 +312,11 @@ struct DedxPidAnalysis { } else { LOGF(info, "GoodZvtxFT0vsPV cut disabled"); } + if (nGoodITS) { + LOGF(info, "Applying GoodITSLayersAll cut"); + } else { + LOGF(info, "GoodITSLayersAll cut disabled"); + } if (nINELSelectionMode == NoSelINEL) { LOGF(info, "Applying just INEL"); label = "INEL"; @@ -760,7 +767,7 @@ struct DedxPidAnalysis { HistType::kTH2F, {{ptAxis}, {dcaAxis}}); // Event Counter - registryDeDx.add("evsel", "events selected", HistType::kTH1F, {{6, 0.5, 6.5, ""}}); + registryDeDx.add("evsel", "events selected", HistType::kTH1F, {{7, 0.5, 7.5, ""}}); auto hstat = registryDeDx.get(HIST("evsel")); auto* x = hstat->GetXaxis(); x->SetBinLabel(AllEv, "AllEv"); @@ -769,6 +776,7 @@ struct DedxPidAnalysis { x->SetBinLabel(NoSameBunchPileup, "NoSameBunchPileup"); x->SetBinLabel(GoodZvtxFT0vsPV, "GoodZvtxFT0vsPV"); x->SetBinLabel(INELgt, label); + x->SetBinLabel(GoodITS, "GoodITSLayersAll"); // Track Prim Counter registryDeDx.add("trackselAll", "track selected all particles", HistType::kTH1F, {{5, 0.5, 5.5, ""}}); @@ -1438,6 +1446,12 @@ struct DedxPidAnalysis { registryDeDx.fill(HIST("evsel"), EvCutLabel::GoodZvtxFT0vsPV); } + if (nGoodITS) { + if (!collision.selection_bit(o2::aod::evsel::kIsGoodITSLayersAll)) + return; + registryDeDx.fill(HIST("evsel"), EvCutLabel::GoodITS); + } + if (nINELSelectionMode == NoSelINEL) { registryDeDx.fill(HIST("evsel"), EvCutLabel::INELgt); } else if (nINELSelectionMode == SelINELgt0) { From cdccf12064c725df66a5533483e168f621f62dfe Mon Sep 17 00:00:00 2001 From: Paola Vargas Torres Date: Mon, 3 Aug 2026 15:43:51 -0600 Subject: [PATCH 2/8] Add GoodITSLayersAll event cut and adjust myTrackSelection cuts to multiplicityPt.cxx --- PWGLF/Tasks/Nuspex/multiplicityPt.cxx | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/PWGLF/Tasks/Nuspex/multiplicityPt.cxx b/PWGLF/Tasks/Nuspex/multiplicityPt.cxx index 7f0864b61c1..09bc3ac17ba 100644 --- a/PWGLF/Tasks/Nuspex/multiplicityPt.cxx +++ b/PWGLF/Tasks/Nuspex/multiplicityPt.cxx @@ -121,6 +121,7 @@ struct MultiplicityPt { Configurable requireIsGoodZvtxFT0vsPV{"requireIsGoodZvtxFT0vsPV", false, "Require good Z vertex FT0 vs PV"}; Configurable requireIsVertexITSTPC{"requireIsVertexITSTPC", false, "Require vertex ITSTPC"}; Configurable removeNoTimeFrameBorder{"removeNoTimeFrameBorder", false, "Remove no time frame border"}; + Configurable nGoodITS{"nGoodITS", true, "Numbers of inactive chips on all ITS layers are below maximum allowed values"}; // Gen-level event selection Configurable selTVXMC{"selTVXMC", true, "Require TVX-equivalent at gen level"}; @@ -229,7 +230,8 @@ struct MultiplicityPt { kVtxZ, kINELgt0, kRecoColl, - kRecoSelected + kGoodITS, + kRecoSelected, }; // Particle species enum @@ -252,14 +254,14 @@ struct MultiplicityPt { // Setup custom track cuts if (useCustomTrackCuts.value) { customTrackCuts = getGlobalTrackSelectionRun3ITSMatch(itsPattern.value); - customTrackCuts.SetRequireITSRefit(requireITS.value); - customTrackCuts.SetRequireTPCRefit(requireTPC.value); + //customTrackCuts.SetRequireITSRefit(requireITS.value); + //customTrackCuts.SetRequireTPCRefit(requireTPC.value); customTrackCuts.SetMinNClustersITS(minITSnClusters.value); customTrackCuts.SetRequireGoldenChi2(requireGoldenChi2.value); customTrackCuts.SetMaxChi2PerClusterTPC(maxChi2PerClusterTPC.value); customTrackCuts.SetMaxChi2PerClusterITS(maxChi2PerClusterITS.value); customTrackCuts.SetMinNCrossedRowsTPC(minNCrossedRowsTPC.value); - customTrackCuts.SetMinNCrossedRowsOverFindableClustersTPC(minNCrossedRowsOverFindableClustersTPC.value); + //customTrackCuts.SetMinNCrossedRowsOverFindableClustersTPC(minNCrossedRowsOverFindableClustersTPC.value); customTrackCuts.SetMaxDcaXYPtDep([](float /*pt*/) { return 10000.f; }); // customTrackCuts.SetMaxDcaZ(maxDcaZ.value); } @@ -305,7 +307,7 @@ struct MultiplicityPt { // ======================================================================== // EVENT COUNTER AND BASIC HISTOGRAMS // ======================================================================== - registry.add("EventCounter", ";;Events", kTH1F, {{8, 0.5, 8.5}}); + registry.add("EventCounter", ";;Events", kTH1F, {{9, 0.5, 9.5}}); { auto h = registry.get(HIST("EventCounter")); h->GetXaxis()->SetBinLabel(kAllGen, "All gen."); @@ -313,6 +315,7 @@ struct MultiplicityPt { h->GetXaxis()->SetBinLabel(kVtxZ, "|Zvtx|GetXaxis()->SetBinLabel(kINELgt0, "INEL>0"); h->GetXaxis()->SetBinLabel(kRecoColl, ">=1 reco coll."); + h->GetXaxis()->SetBinLabel(kGoodITS, "GoodITSLayersAll"); h->GetXaxis()->SetBinLabel(kRecoSelected, ">=1 reco+sel."); } @@ -967,7 +970,7 @@ struct MultiplicityPt { if (isZvtxPosSelMC.value && std::abs(mcCollision.posZ()) > cfgCutVertex.value) return; registry.fill(HIST("EventCounter"), kVtxZ); - + if (cfgINELCut.value == 1 && nChINEL == 0) return; if (cfgINELCut.value == INELgt1 && nChINEL < INELgt1) @@ -1063,8 +1066,12 @@ struct MultiplicityPt { continue; if (!isEventSelectedMC(collision)) continue; - - registry.fill(HIST("EventCounter"), kRecoSelected); + + if (nGoodITS.value && !collision.selection_bit(o2::aod::evsel::kIsGoodITSLayersAll)) + continue; + registry.fill(HIST("EventCounter"), kGoodITS); + + registry.fill(HIST("EventCounter"), kRecoSelected); const float centrality = collision.centFT0M(); From 223bc85d462f8764bda6cd9601b9e936d55eb730 Mon Sep 17 00:00:00 2001 From: Paola Vargas Torres Date: Mon, 3 Aug 2026 15:44:47 -0600 Subject: [PATCH 3/8] Add GoodITSLayersAll event cut and adjust myTrackSelection cuts to multiplicityPt.cxx --- PWGLF/Tasks/Nuspex/multiplicityPt.cxx | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/PWGLF/Tasks/Nuspex/multiplicityPt.cxx b/PWGLF/Tasks/Nuspex/multiplicityPt.cxx index 09bc3ac17ba..7e90e8b89d5 100644 --- a/PWGLF/Tasks/Nuspex/multiplicityPt.cxx +++ b/PWGLF/Tasks/Nuspex/multiplicityPt.cxx @@ -121,7 +121,7 @@ struct MultiplicityPt { Configurable requireIsGoodZvtxFT0vsPV{"requireIsGoodZvtxFT0vsPV", false, "Require good Z vertex FT0 vs PV"}; Configurable requireIsVertexITSTPC{"requireIsVertexITSTPC", false, "Require vertex ITSTPC"}; Configurable removeNoTimeFrameBorder{"removeNoTimeFrameBorder", false, "Remove no time frame border"}; - Configurable nGoodITS{"nGoodITS", true, "Numbers of inactive chips on all ITS layers are below maximum allowed values"}; + Configurable nGoodITS{"nGoodITS", true, "Numbers of inactive chips on all ITS layers are below maximum allowed values"}; // Gen-level event selection Configurable selTVXMC{"selTVXMC", true, "Require TVX-equivalent at gen level"}; @@ -254,14 +254,14 @@ struct MultiplicityPt { // Setup custom track cuts if (useCustomTrackCuts.value) { customTrackCuts = getGlobalTrackSelectionRun3ITSMatch(itsPattern.value); - //customTrackCuts.SetRequireITSRefit(requireITS.value); - //customTrackCuts.SetRequireTPCRefit(requireTPC.value); + // customTrackCuts.SetRequireITSRefit(requireITS.value); + // customTrackCuts.SetRequireTPCRefit(requireTPC.value); customTrackCuts.SetMinNClustersITS(minITSnClusters.value); customTrackCuts.SetRequireGoldenChi2(requireGoldenChi2.value); customTrackCuts.SetMaxChi2PerClusterTPC(maxChi2PerClusterTPC.value); customTrackCuts.SetMaxChi2PerClusterITS(maxChi2PerClusterITS.value); customTrackCuts.SetMinNCrossedRowsTPC(minNCrossedRowsTPC.value); - //customTrackCuts.SetMinNCrossedRowsOverFindableClustersTPC(minNCrossedRowsOverFindableClustersTPC.value); + // customTrackCuts.SetMinNCrossedRowsOverFindableClustersTPC(minNCrossedRowsOverFindableClustersTPC.value); customTrackCuts.SetMaxDcaXYPtDep([](float /*pt*/) { return 10000.f; }); // customTrackCuts.SetMaxDcaZ(maxDcaZ.value); } @@ -970,7 +970,7 @@ struct MultiplicityPt { if (isZvtxPosSelMC.value && std::abs(mcCollision.posZ()) > cfgCutVertex.value) return; registry.fill(HIST("EventCounter"), kVtxZ); - + if (cfgINELCut.value == 1 && nChINEL == 0) return; if (cfgINELCut.value == INELgt1 && nChINEL < INELgt1) @@ -1066,12 +1066,12 @@ struct MultiplicityPt { continue; if (!isEventSelectedMC(collision)) continue; - - if (nGoodITS.value && !collision.selection_bit(o2::aod::evsel::kIsGoodITSLayersAll)) - continue; + + if (nGoodITS.value && !collision.selection_bit(o2::aod::evsel::kIsGoodITSLayersAll)) + continue; registry.fill(HIST("EventCounter"), kGoodITS); - - registry.fill(HIST("EventCounter"), kRecoSelected); + + registry.fill(HIST("EventCounter"), kRecoSelected); const float centrality = collision.centFT0M(); From eaeec4a6896b7f96a00eb1011d3d57af6c0ce6a7 Mon Sep 17 00:00:00 2001 From: Paola Vargas Torres Date: Wed, 5 Aug 2026 14:50:33 -0600 Subject: [PATCH 4/8] add generator-level vs reco-level flattenicity task --- PWGMM/UE/Tasks/CMakeLists.txt | 40 ++-- PWGMM/UE/Tasks/flattenicityTask.cxx | 325 ++++++++++++++++++++++++++++ 2 files changed, 346 insertions(+), 19 deletions(-) create mode 100644 PWGMM/UE/Tasks/flattenicityTask.cxx diff --git a/PWGMM/UE/Tasks/CMakeLists.txt b/PWGMM/UE/Tasks/CMakeLists.txt index f9ee32c6e10..cd9dddec276 100644 --- a/PWGMM/UE/Tasks/CMakeLists.txt +++ b/PWGMM/UE/Tasks/CMakeLists.txt @@ -1,25 +1,27 @@ -# 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. +#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". +#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 +#In applying this license CERN does not waive the privileges and immunities +#granted to it by virtue of its status as an Intergovernmental Organization # or submit itself to any jurisdiction. -o2physics_add_dpl_workflow(ue-charged - SOURCES uecharged.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore - COMPONENT_NAME Analysis) +o2physics_add_dpl_workflow(ue - charged + SOURCES uecharged.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore + COMPONENT_NAME Analysis) -o2physics_add_dpl_workflow(ue-zdc-analysis - SOURCES ue-zdc-analysys.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore - COMPONENT_NAME Analysis) + o2physics_add_dpl_workflow(ue - zdc - analysis SOURCES ue - zdc - analysys.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore COMPONENT_NAME Analysis) -o2physics_add_dpl_workflow(dedx-analysis - SOURCES dedxAnalysis.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore - COMPONENT_NAME Analysis) \ No newline at end of file + o2physics_add_dpl_workflow(ue - lambdak0sflattenicity + SOURCES lambdak0sflattenicity.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore + COMPONENT_NAME Analysis) + + o2physics_add_dpl_workflow(flattenicity + SOURCES flattenicityTask.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore + COMPONENT_NAME Analysis) diff --git a/PWGMM/UE/Tasks/flattenicityTask.cxx b/PWGMM/UE/Tasks/flattenicityTask.cxx new file mode 100644 index 00000000000..0800433520d --- /dev/null +++ b/PWGMM/UE/Tasks/flattenicityTask.cxx @@ -0,0 +1,325 @@ +//============================================================================= +// 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. +/// +/// \author Eishah Rani +/// \since August 5, 2026 +/// \file flattenicityTask.cxx +/// \brief Generator-Level vs Reconstruction-Level Flattenicity +// Based on: +// PWGMM/UE/Tasks/uecharged.cxx +//============================================================================= + +#include "Common/Core/TrackSelection.h" +#include "Common/Core/TrackSelectionDefaults.h" +#include "Common/DataModel/EventSelection.h" +#include "Common/DataModel/Multiplicity.h" +#include "Common/DataModel/TrackSelectionTables.h" + +#include "Framework/ASoAHelpers.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/AnalysisTask.h" +#include "Framework/Configurable.h" +#include "Framework/Constants.h" +#include "Framework/HistogramRegistry.h" +#include "Framework/InitContext.h" +#include "Framework/O2DatabasePDGPlugin.h" +#include "Framework/runDataProcessing.h" +#include "ReconstructionDataFormats/Track.h" + +#include +#include + +using namespace o2; +using namespace o2::framework; +using namespace o2::framework::expressions; + +struct FlattenicityTask { + + // --- Flattenicity constants --- + static constexpr int NCH_A = 96; + static constexpr int NCH_C = 112; + static constexpr int NCELL = NCH_A + NCH_C; + static constexpr int NPHISECTORS = 8; + static constexpr int NETA_A = NCH_A / NPHISECTORS; + static constexpr int NETA_C = NCH_C / NPHISECTORS; + + // FT0 acceptance + static constexpr float FT0A_ETA_MIN = 3.5f; + static constexpr float FT0A_ETA_MAX = 4.9f; + static constexpr float FT0C_ETA_MIN = -3.3f; + static constexpr float FT0C_ETA_MAX = -2.1f; + + // --- Event selection constants --- + static constexpr float VERTEX_CUT = 10.0f; + static constexpr float FLAT_MIN = 0.0f; + static constexpr float INEL_ETA_CUT = 1.0f; + static constexpr float MIDRAP_ETA_CUT = 0.8f; + + // --- Configurables --- + Configurable cfgTrkEtaCut{"cfgTrkEtaCut", 0.8f, "Eta range for tracks"}; + Configurable cfgTrkLowPtCut{"cfgTrkLowPtCut", 0.15f, "Minimum pT"}; + + Configurable isRun3{"isRun3", true, "is Run3 dataset"}; + Configurable timeEvsel{"timeEvsel", true, "TPC Time frame boundary cut"}; + Configurable piluprejection{"piluprejection", true, "Pileup rejection"}; + Configurable goodzvertex{"goodzvertex", true, "Good Z vertex"}; + + // --- Track selection --- + TrackSelection mySelectionPrim; + + // --- Histograms --- + HistogramRegistry registry; + + // --- Init --- + void init(InitContext const&) override + { + // Initialize track selection + mySelectionPrim = myTrackSelectionPrim(); + + // Define histograms + AxisSpec flatBins = {40, 0.0, 1.0, "#rho"}; + AxisSpec nchBins = {100, -0.5, 99.5, "N_{ch}"}; + + registry.add("hFlattenicityTruth", "Truth flattenicity; 1-#rho; Events", + HistType::kTH1D, {flatBins}); + registry.add("hFlattenicityReco", "Reco flattenicity; 1-#rho; Events", + HistType::kTH1D, {flatBins}); + registry.add("hFlattenicityCorrelation", "Truth vs Reco; 1-#rho_{truth}; 1-#rho_{reco}", + HistType::kTH2D, {flatBins, flatBins}); + registry.add("hNch", "Reco Nch distribution; N_{ch}; Events", + HistType::kTH1D, {nchBins}); + registry.add("hNchTruth", "Truth Nch distribution; N_{ch}; Events", + HistType::kTH1D, {nchBins}); + } + + // --- Track selection function --- + TrackSelection myTrackSelectionPrim() + { + TrackSelection selectedTracks; + selectedTracks.SetPtRange(0.1f, 1e10f); + selectedTracks.SetEtaRange(-0.8f, 0.8f); + selectedTracks.SetRequireITSRefit(true); + selectedTracks.SetRequireTPCRefit(true); + selectedTracks.SetMinNCrossedRowsTPC(70); + selectedTracks.SetMinNCrossedRowsOverFindableClustersTPC(0.4f); + selectedTracks.SetMaxChi2PerClusterTPC(4.0f); + selectedTracks.SetRequireHitsInITSLayers(1, {0, 1}); + selectedTracks.SetMaxChi2PerClusterITS(36.0f); + selectedTracks.SetMaxDcaXYPtDep([](float pt) { return 0.0105f + 0.0350f / std::pow(pt, 1.1f); }); + selectedTracks.SetMaxDcaZ(2.0f); + return selectedTracks; + } + + // --- Helper: Get cell ID for a particle in FT0 acceptance --- + int getCellId(float eta, float phi) + { + // Check if in FT0-A acceptance + if (eta > FT0A_ETA_MIN && eta < FT0A_ETA_MAX) { + int phiBin = static_cast(std::floor(phi / (2.0f * o2::constants::math::PI / static_cast(NPHISECTORS)))); + phiBin = std::clamp(phiBin, 0, NPHISECTORS - 1); + int etaBin = static_cast(std::floor((eta - FT0A_ETA_MIN) / ((FT0A_ETA_MAX - FT0A_ETA_MIN) / static_cast(NETA_A)))); + etaBin = std::clamp(etaBin, 0, NETA_A - 1); + return etaBin * NPHISECTORS + phiBin; + } + + // Check if in FT0-C acceptance + if (eta > FT0C_ETA_MIN && eta < FT0C_ETA_MAX) { + int phiBin = static_cast(std::floor(phi / (2.0f * o2::constants::math::PI / static_cast(NPHISECTORS)))); + phiBin = std::clamp(phiBin, 0, NPHISECTORS - 1); + int etaBin = static_cast(std::floor((eta - FT0C_ETA_MIN) / ((FT0C_ETA_MAX - FT0C_ETA_MIN) / static_cast(NETA_C)))); + etaBin = std::clamp(etaBin, 0, NETA_C - 1); + return NCH_A + etaBin * NPHISECTORS + phiBin; + } + + return -1; // Not in FT0 acceptance + } + + // --- Flattenicity calculation --- + float calculateFlattenicity(const std::vector& counts) + { + if (counts.size() != static_cast(NCELL)) { + return -1.0f; + } + + float total = 0.0f; + for (const auto& c : counts) { + total += c; + } + if (total <= 0.0f) { + return -1.0f; + } + + float mean = total / static_cast(NCELL); + if (mean <= 0.0f) { + return -1.0f; + } + + float sumSq = 0.0f; + for (const auto& c : counts) { + sumSq += (c - mean) * (c - mean); + } + + float rho = std::sqrt(sumSq / (static_cast(NCELL) * static_cast(NCELL))) / mean; + return 1.0f - rho; + } + + // --- Process Data --- + void processData(aod::Collision const& collision, + soa::Filtered const& tracks, + aod::FT0s const& ft0s) + { + // Event selection (Paola/Jesus) + if (!collision.sel8()) { + return; + } + if (std::abs(collision.posZ()) >= VERTEX_CUT) { + return; + } + + // Track loop for Nch + int nch = 0; + for (const auto& track : tracks) { + if (!mySelectionPrim.IsSelected(track)) { + continue; + } + nch++; + } + registry.fill(HIST("hNch"), nch); + + // FT0 flattenicity + auto ft0 = collision.ft0(); + if (ft0.hasAmplitudeA() && ft0.hasAmplitudeC()) { + auto ampA = ft0.amplitudeA(); + auto ampC = ft0.amplitudeC(); + + std::vector counts(NCELL, 0.0f); + for (int i = 0; i < static_cast(ampA.size()) && i < NCH_A; ++i) { + counts[i] = ampA[i]; + } + for (int i = 0; i < static_cast(ampC.size()) && i < NCH_C; ++i) { + counts[NCH_A + i] = ampC[i]; + } + + float flat = calculateFlattenicity(counts); + if (flat >= FLAT_MIN) { + registry.fill(HIST("hFlattenicityReco"), flat); + } + } + } + PROCESS_SWITCH(FlattenicityTask, processData, "Process data", true); + + // --- Process MC --- + void processMC(aod::McCollision const& mcCollision, + aod::McParticles const& particles, + soa::SmallGroups> const& collisions, + aod::FT0s const& ft0s, + aod::BCs const& /*bcs*/) + { + // ---- Truth-level processing ---- + bool inel = false; + int nchTruth = 0; + std::vector truthCounts(NCELL, 0.0f); + + for (const auto& particle : particles) { + // Check if physical primary + if (!particle.isPhysicalPrimary()) { + continue; + } + + // Check if charged + if (std::abs(particle.pdgCode()) == 0) { + continue; + } + + // Check pT > 0 + if (particle.pt() <= 0.0f) { + continue; + } + + // INEL>0 check: primary charged with |eta| < INEL_ETA_CUT + if (std::abs(particle.eta()) < INEL_ETA_CUT) { + inel = true; + } + + // Nch at midrapidity: |eta| < MIDRAP_ETA_CUT, pT > cfgTrkLowPtCut + if (std::abs(particle.eta()) < MIDRAP_ETA_CUT && particle.pt() > cfgTrkLowPtCut) { + nchTruth++; + } + + // Flattenicity: particles in FT0 acceptance + int cellId = getCellId(particle.eta(), particle.phi()); + if (cellId >= 0 && cellId < NCELL) { + truthCounts[cellId] += 1.0f; + } + } + + // Apply truth-level event selection (Paola/Jesus) + if (!inel) { + return; + } + if (std::abs(mcCollision.posZ()) >= VERTEX_CUT) { + return; + } + + // Fill truth multiplicity + registry.fill(HIST("hNchTruth"), nchTruth); + registry.fill(HIST("hNch"), nchTruth); + + // Calculate truth flattenicity + float truthFlat = calculateFlattenicity(truthCounts); + if (truthFlat >= FLAT_MIN) { + registry.fill(HIST("hFlattenicityTruth"), truthFlat); + } + + // ---- Reconstructed-level processing for matched collisions ---- + for (const auto& collision : collisions) { + // Apply reconstruction-level event selection + if (!collision.sel8()) { + continue; + } + if (std::abs(collision.posZ()) >= VERTEX_CUT) { + continue; + } + + // Get FT0 flattenicity for this collision + auto ft0 = collision.ft0(); + if (!ft0.hasAmplitudeA() || !ft0.hasAmplitudeC()) { + continue; + } + + auto ampA = ft0.amplitudeA(); + auto ampC = ft0.amplitudeC(); + + std::vector recoCounts(NCELL, 0.0f); + for (int i = 0; i < static_cast(ampA.size()) && i < NCH_A; ++i) { + recoCounts[i] = ampA[i]; + } + for (int i = 0; i < static_cast(ampC.size()) && i < NCH_C; ++i) { + recoCounts[NCH_A + i] = ampC[i]; + } + + float recoFlat = calculateFlattenicity(recoCounts); + if (recoFlat >= FLAT_MIN && truthFlat >= FLAT_MIN) { + registry.fill(HIST("hFlattenicityReco"), recoFlat); + registry.fill(HIST("hFlattenicityCorrelation"), truthFlat, recoFlat); + } + } + } + PROCESS_SWITCH(FlattenicityTask, processMC, "Process MC", true); +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + WorkflowSpec workflow{}; + workflow.push_back(adaptAnalysisTask(cfgc)); + return workflow; +} From 1bd47517e021f754b570039faa8db4dbc61051d5 Mon Sep 17 00:00:00 2001 From: Paola Vargas Torres Date: Wed, 5 Aug 2026 15:07:51 -0600 Subject: [PATCH 5/8] Add Flattenicity task --- PWGMM/UE/Tasks/CMakeLists.txt | 8 ++++---- PWGMM/UE/Tasks/flattenicityTask.cxx | 12 ++++-------- 2 files changed, 8 insertions(+), 12 deletions(-) diff --git a/PWGMM/UE/Tasks/CMakeLists.txt b/PWGMM/UE/Tasks/CMakeLists.txt index cd9dddec276..edc7c4a1fcb 100644 --- a/PWGMM/UE/Tasks/CMakeLists.txt +++ b/PWGMM/UE/Tasks/CMakeLists.txt @@ -21,7 +21,7 @@ o2physics_add_dpl_workflow(ue - charged PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore COMPONENT_NAME Analysis) - o2physics_add_dpl_workflow(flattenicity - SOURCES flattenicityTask.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore - COMPONENT_NAME Analysis) + o2physics_add_dpl_workflow(flattenicity - task + SOURCES flattenicityTask.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore + COMPONENT_NAME Analysis) diff --git a/PWGMM/UE/Tasks/flattenicityTask.cxx b/PWGMM/UE/Tasks/flattenicityTask.cxx index 0800433520d..fae4d7946de 100644 --- a/PWGMM/UE/Tasks/flattenicityTask.cxx +++ b/PWGMM/UE/Tasks/flattenicityTask.cxx @@ -1,4 +1,3 @@ -//============================================================================= // 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. @@ -9,14 +8,11 @@ // 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. -/// -/// \author Eishah Rani -/// \since August 5, 2026 + /// \file flattenicityTask.cxx -/// \brief Generator-Level vs Reconstruction-Level Flattenicity -// Based on: -// PWGMM/UE/Tasks/uecharged.cxx -//============================================================================= +/// \brief Flattenicity analysis task for UE studies +/// \author Eisha Rani +/// \since August 2026 #include "Common/Core/TrackSelection.h" #include "Common/Core/TrackSelectionDefaults.h" From 817ad765d95c78279df63b0e259cd3d4cb90f0bb Mon Sep 17 00:00:00 2001 From: Paola Vargas Torres Date: Wed, 5 Aug 2026 17:45:18 -0600 Subject: [PATCH 6/8] Fix CMakeLists file to add Flattenicity task workflow --- PWGMM/UE/Tasks/CMakeLists.txt | 43 +++++++++++++++++++---------------- 1 file changed, 23 insertions(+), 20 deletions(-) diff --git a/PWGMM/UE/Tasks/CMakeLists.txt b/PWGMM/UE/Tasks/CMakeLists.txt index edc7c4a1fcb..29a7bcb2486 100644 --- a/PWGMM/UE/Tasks/CMakeLists.txt +++ b/PWGMM/UE/Tasks/CMakeLists.txt @@ -1,27 +1,30 @@ -#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. +# 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". +# 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 +# In applying this license CERN does not waive the privileges and immunities +# granted to it by virtue of its status as an Intergovernmental Organization # or submit itself to any jurisdiction. -o2physics_add_dpl_workflow(ue - charged - SOURCES uecharged.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore - COMPONENT_NAME Analysis) +o2physics_add_dpl_workflow(ue-charged + SOURCES uecharged.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore + COMPONENT_NAME Analysis) - o2physics_add_dpl_workflow(ue - zdc - analysis SOURCES ue - zdc - analysys.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore COMPONENT_NAME Analysis) +o2physics_add_dpl_workflow(ue-zdc-analysis + SOURCES ue-zdc-analysys.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore + COMPONENT_NAME Analysis) - o2physics_add_dpl_workflow(ue - lambdak0sflattenicity - SOURCES lambdak0sflattenicity.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore - COMPONENT_NAME Analysis) +o2physics_add_dpl_workflow(dedx-analysis + SOURCES dedxAnalysis.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore + COMPONENT_NAME Analysis) - o2physics_add_dpl_workflow(flattenicity - task - SOURCES flattenicityTask.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore - COMPONENT_NAME Analysis) +o2physics_add_dpl_workflow(flattenicity-task + SOURCES flattenicityTask.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore + COMPONENT_NAME Analysis) \ No newline at end of file From 4c0bee3b1fbbc6fc86897ff87ba522f7bc9cdaa1 Mon Sep 17 00:00:00 2001 From: Paola Vargas Torres Date: Wed, 5 Aug 2026 21:52:08 -0600 Subject: [PATCH 7/8] Fix clang for fattenicity task --- PWGMM/UE/Tasks/flattenicityTask.cxx | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/PWGMM/UE/Tasks/flattenicityTask.cxx b/PWGMM/UE/Tasks/flattenicityTask.cxx index fae4d7946de..24bc226b74c 100644 --- a/PWGMM/UE/Tasks/flattenicityTask.cxx +++ b/PWGMM/UE/Tasks/flattenicityTask.cxx @@ -20,16 +20,16 @@ #include "Common/DataModel/Multiplicity.h" #include "Common/DataModel/TrackSelectionTables.h" -#include "Framework/ASoAHelpers.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/AnalysisTask.h" -#include "Framework/Configurable.h" -#include "Framework/Constants.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/InitContext.h" -#include "Framework/O2DatabasePDGPlugin.h" -#include "Framework/runDataProcessing.h" -#include "ReconstructionDataFormats/Track.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include #include #include From 8dd36d46a2bbd93578e533f8e9919ce3e64dcc51 Mon Sep 17 00:00:00 2001 From: ALICE Action Bot Date: Thu, 6 Aug 2026 03:56:18 +0000 Subject: [PATCH 8/8] Please consider the following formatting changes --- PWGMM/UE/Tasks/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/PWGMM/UE/Tasks/CMakeLists.txt b/PWGMM/UE/Tasks/CMakeLists.txt index 29a7bcb2486..27d74e095c1 100644 --- a/PWGMM/UE/Tasks/CMakeLists.txt +++ b/PWGMM/UE/Tasks/CMakeLists.txt @@ -27,4 +27,4 @@ o2physics_add_dpl_workflow(dedx-analysis o2physics_add_dpl_workflow(flattenicity-task SOURCES flattenicityTask.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore - COMPONENT_NAME Analysis) \ No newline at end of file + COMPONENT_NAME Analysis)