From 3e4ca7898b78476a1b17d5015b3daa47d54bdfff Mon Sep 17 00:00:00 2001 From: Bong-Hwi Lim Date: Tue, 30 Dec 2025 11:43:33 +0900 Subject: [PATCH 1/8] Update the collision cut class --- PWGLF/Utils/CMakeLists.txt | 10 +- PWGLF/Utils/EventSelectionFlagsMapping.def | 78 +++++ PWGLF/Utils/collisionCuts.h | 316 ++++++++++++++++----- PWGLF/Utils/collisionCutsGroup.cxx | 86 ++++++ PWGLF/Utils/collisionCutsGroup.h | 109 +++++++ PWGLF/Utils/collisionCutsGroupLinkDef.h | 34 +++ Tutorials/PWGLF/CMakeLists.txt | 1 + Tutorials/PWGLF/Utils/CMakeLists.txt | 16 ++ Tutorials/PWGLF/Utils/README.md | 65 +++++ Tutorials/PWGLF/Utils/collisionCuts.cxx | 90 ++++++ 10 files changed, 733 insertions(+), 72 deletions(-) create mode 100644 PWGLF/Utils/EventSelectionFlagsMapping.def create mode 100644 PWGLF/Utils/collisionCutsGroup.cxx create mode 100644 PWGLF/Utils/collisionCutsGroup.h create mode 100644 PWGLF/Utils/collisionCutsGroupLinkDef.h create mode 100644 Tutorials/PWGLF/Utils/CMakeLists.txt create mode 100644 Tutorials/PWGLF/Utils/README.md create mode 100644 Tutorials/PWGLF/Utils/collisionCuts.cxx diff --git a/PWGLF/Utils/CMakeLists.txt b/PWGLF/Utils/CMakeLists.txt index 51048b896a5..fad54f18617 100644 --- a/PWGLF/Utils/CMakeLists.txt +++ b/PWGLF/Utils/CMakeLists.txt @@ -15,4 +15,12 @@ o2physics_add_library(v0SelectionGroup o2physics_target_root_dictionary(v0SelectionGroup HEADERS v0SelectionGroup.h - LINKDEF v0SelectionGroupLinkDef.h) \ No newline at end of file + LINKDEF v0SelectionGroupLinkDef.h) + +o2physics_add_library(collisionCutsGroup + SOURCES collisionCutsGroup.cxx + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore) + +o2physics_target_root_dictionary(collisionCutsGroup + HEADERS collisionCutsGroup.h + LINKDEF collisionCutsGroupLinkDef.h) \ No newline at end of file diff --git a/PWGLF/Utils/EventSelectionFlagsMapping.def b/PWGLF/Utils/EventSelectionFlagsMapping.def new file mode 100644 index 00000000000..3e23ba89cdd --- /dev/null +++ b/PWGLF/Utils/EventSelectionFlagsMapping.def @@ -0,0 +1,78 @@ +// 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 EventSelectionFlagsMapping.def +/// \brief X-macro mapping between EventSelectionFlags and collisionCutsGroup +/// +/// This file defines the canonical mapping between o2::aod::evsel::EventSelectionFlags +/// enum values and collisionCutsGroup boolean member variables. It is used via X-macros +/// to auto-generate member declarations, getters, setters, initialization, and metadata. +/// +/// IMPORTANT: This file should NOT have include guards as it is included multiple times +/// with different EVSEL_FLAG macro definitions. +/// +/// Format: EVSEL_FLAG(enumValue, memberName, defaultValue, evtSelEnum, setterName, getterName, label, description) +/// +/// Parameters: +/// enumValue - EventSelectionFlags enum (e.g., kIsTriggerTVX) +/// memberName - collisionCutsGroup bool member variable name +/// defaultValue - Default value (true/false) in constructor +/// evtSelEnum - CollisonCuts::EvtSel enum value for histogram binning +/// setterName - CollisonCuts setter method name +/// getterName - collisionCutsGroup getter method name suffix (without 'get') +/// label - Histogram axis label (short, no spaces) +/// description - Human-readable description +/// +/// To add a new event selection flag: +/// 1. Add a new EVSEL_FLAG line below following the format +/// 2. Ensure the EvtSel enum in collisionCuts.h has corresponding entry +/// 3. Ensure the setter method exists in CollisonCuts class +/// 4. Rebuild - all getters, members, logging, and metadata are auto-generated +/// +/// \author Bong-Hwi Lim + +// Trigger selection +EVSEL_FLAG(kIsTriggerTVX, triggerTVXSel, false, kFlagTrigerTVX, setTriggerTVX, TriggerTVXSel, "IsTriggerTVX", "Trigger TVX selection") + +// Time frame and readout frame borders +EVSEL_FLAG(kNoTimeFrameBorder, applyTFBorderCut, false, kFlagTimeFrameBorder, setApplyTFBorderCut, ApplyTFBorderCut, "NoTimeFrameBorder", "Apply TF border cut") +EVSEL_FLAG(kNoITSROFrameBorder, applyNoITSROBorderCut, false, kFlagITSROFrameBorder, setApplyNoITSROBorderCut, ApplyNoITSROBorderCut, "NoITSROFrameBorder", "Apply NoITSRO frame border cut") + +// Vertex quality +EVSEL_FLAG(kIsVertexITSTPC, applyITSTPCvertex, false, kFlagVertexITSTPC, setApplyITSTPCvertex, ApplyITSTPCvertex, "IsVertexITSTPC", "Apply ITS-TPC vertex") +EVSEL_FLAG(kIsGoodZvtxFT0vsPV, applyZvertexTimedifference, false, kFlagZvtxFT0vsPV, setApplyZvertexTimedifference, ApplyZvertexTimedifference, "IsGoodZvtxFT0vsPV", "Apply Z-vertex time difference") +EVSEL_FLAG(kIsVertexTRDmatched, applyVertexTRDmatched, false, kFlagVertexTRDmatched, setApplyVertexTRDmatched, ApplyVertexTRDmatched, "IsVertexTRDmatched", "Vertex has TRD-matched track") + +// Pileup rejection +EVSEL_FLAG(kNoSameBunchPileup, applyPileupRejection, false, kFlagBunchPileup, setApplyPileupRejection, ApplyPileupRejection, "NoSameBunchPileup", "Apply Pileup rejection") + +// Collision-in-time-range cuts +EVSEL_FLAG(kNoCollInTimeRangeStandard, applyCollInTimeRangeStandard, false, kNoCollInTimeRangeStandard, setApplyCollInTimeRangeStandard, ApplyCollInTimeRangeStandard, "NoCollInTimeRangeStandard", "Apply NoCollInTimeRangeStandard") +EVSEL_FLAG(kNoCollInTimeRangeNarrow, applyCollInTimeRangeNarrow, false, kNoCollInTimeRangeNarrow, setApplyCollInTimeRangeNarrow, ApplyCollInTimeRangeNarrow, "NoCollInTimeRangeNarrow", "Apply NoCollInTimeRangeNarrow") +EVSEL_FLAG(kNoCollInTimeRangeStrict, applyCollInTimeRangeStrict, false, kNoCollInTimeRangeStrict, setApplyCollInTimeRangeStrict, ApplyCollInTimeRangeStrict, "NoCollInTimeRangeStrict", "No collisions in time range (strict)") + +// Collision-in-ROF cuts +EVSEL_FLAG(kNoCollInRofStandard, applyCollInRofStandard, false, kNoCollInRofStandard, setApplyCollInRofStandard, ApplyCollInRofStandard, "NoCollInRofStandard", "No high-mult collisions in this ROF") +EVSEL_FLAG(kNoCollInRofStrict, applyCollInRofStrict, false, kNoCollInRofStrict, setApplyCollInRofStrict, ApplyCollInRofStrict, "NoCollInRofStrict", "No collisions in this ROF (strict)") +EVSEL_FLAG(kNoHighMultCollInPrevRof, applyHighMultCollInPrevRof, false, kNoHighMultCollInPrevRof, setApplyHighMultCollInPrevRof, ApplyHighMultCollInPrevRof, "NoHighMultCollInPrevRof", "No high-mult collision in previous ROF") + +// ITS layer quality +EVSEL_FLAG(kIsGoodITSLayersAll, applyGoodITSLayersAll, false, kIsGoodITSLayersAll, setApplyGoodITSLayersAll, ApplyGoodITSLayersAll, "IsGoodITSLayersAll", "Apply GoodITSLayersAll") +EVSEL_FLAG(kIsGoodITSLayer3, applyGoodITSLayer3, false, kIsGoodITSLayer3, setApplyGoodITSLayer3, ApplyGoodITSLayer3, "IsGoodITSLayer3", "Apply GoodITSLayer3") +EVSEL_FLAG(kIsGoodITSLayer0123, applyGoodITSLayer0123, false, kIsGoodITSLayer0123, setApplyGoodITSLayer0123, ApplyGoodITSLayer0123, "IsGoodITSLayer0123", "Apply GoodITSLayer0123") + +// Beam-beam timing +EVSEL_FLAG(kIsBBT0A, applyBBT0A, false, kFlagBBT0A, setApplyBBT0A, ApplyBBT0A, "IsBBT0A", "T0A in beam-beam window") +EVSEL_FLAG(kIsBBT0C, applyBBT0C, false, kFlagBBT0C, setApplyBBT0C, ApplyBBT0C, "IsBBT0C", "T0C in beam-beam window") + +// Future flags can be easily added here, for example: +// EVSEL_FLAG(kIsVertexTOFmatched, applyVertexTOFmatched, false, kFlagVertexTOFmatched, setApplyVertexTOFmatched, ApplyVertexTOFmatched, "IsVertexTOFmatched", "Apply vertex TOF matched") +// EVSEL_FLAG(kNoCollInTimeRangeStrict, applyCollInTimeRangeStrict, false, kNoCollInTimeRangeStrict, setApplyCollInTimeRangeStrict, ApplyCollInTimeRangeStrict, "NoCollInTimeRangeStrict", "Apply NoCollInTimeRangeStrict") diff --git a/PWGLF/Utils/collisionCuts.h b/PWGLF/Utils/collisionCuts.h index b1a80cfe075..10497b75d12 100644 --- a/PWGLF/Utils/collisionCuts.h +++ b/PWGLF/Utils/collisionCuts.h @@ -25,7 +25,10 @@ #include "Framework/HistogramRegistry.h" #include "Framework/Logger.h" +#include "PWGLF/Utils/collisionCutsGroup.h" +#include +#include #include namespace o2::analysis @@ -49,6 +52,16 @@ class CollisonCuts kFlagOccupancy, kNoCollInTimeRangeStandard, kNoCollInTimeRangeNarrow, + kNoCollInTimeRangeStrict, + kNoCollInRofStandard, + kNoCollInRofStrict, + kNoHighMultCollInPrevRof, + kIsGoodITSLayersAll, + kIsGoodITSLayer3, + kIsGoodITSLayer0123, + kFlagVertexTRDmatched, + kFlagBBT0A, + kFlagBBT0C, kAllpassed }; @@ -76,6 +89,7 @@ class CollisonCuts mApplyNoITSROBorderCut = false; mApplyCollInTimeRangeNarrow = false; mApplyCollInTimeRangeStandard = false; + mApplyGoodITSLayersAll = false; mtrackOccupancyInTimeRangeMax = trackOccupancyInTimeRangeMax; mtrackOccupancyInTimeRangeMin = trackOccupancyInTimeRangeMin; mApplyRun2AliEventCuts = true; @@ -108,16 +122,14 @@ class CollisonCuts mHistogramRegistry->add("CollCutCounts", "; ; Entries", o2::framework::kTH1F, {{kAllpassed + 1, 0, kAllpassed + 1}}); mHistogramRegistry->get(HIST("CollCutCounts"))->GetXaxis()->SetBinLabel(binLabel(EvtSel::kAllEvent), "all"); mHistogramRegistry->get(HIST("CollCutCounts"))->GetXaxis()->SetBinLabel(binLabel(EvtSel::kFlagZvertex), "Zvtx"); - mHistogramRegistry->get(HIST("CollCutCounts"))->GetXaxis()->SetBinLabel(binLabel(EvtSel::kFlagTrigerTVX), "IsTriggerTVX"); - mHistogramRegistry->get(HIST("CollCutCounts"))->GetXaxis()->SetBinLabel(binLabel(EvtSel::kFlagTimeFrameBorder), "NoTimeFrameBorder"); - mHistogramRegistry->get(HIST("CollCutCounts"))->GetXaxis()->SetBinLabel(binLabel(EvtSel::kFlagITSROFrameBorder), "NoITSROFrameBorder"); + + // Automatically set labels from metadata registry + for (const auto& [evtSelFlag, metadata] : sSelectionRegistry) { + mHistogramRegistry->get(HIST("CollCutCounts"))->GetXaxis()->SetBinLabel(binLabel(metadata.histogramBin), metadata.label); + } + mHistogramRegistry->get(HIST("CollCutCounts"))->GetXaxis()->SetBinLabel(binLabel(EvtSel::kFlagSel8), "sel8"); - mHistogramRegistry->get(HIST("CollCutCounts"))->GetXaxis()->SetBinLabel(binLabel(EvtSel::kFlagVertexITSTPC), "IsVertexITSTPC"); - mHistogramRegistry->get(HIST("CollCutCounts"))->GetXaxis()->SetBinLabel(binLabel(EvtSel::kFlagBunchPileup), "NoSameBunchPileup"); - mHistogramRegistry->get(HIST("CollCutCounts"))->GetXaxis()->SetBinLabel(binLabel(EvtSel::kFlagZvtxFT0vsPV), "IsGoodZvtxFT0vsPV"); mHistogramRegistry->get(HIST("CollCutCounts"))->GetXaxis()->SetBinLabel(binLabel(EvtSel::kFlagOccupancy), "LowOccupancy"); - mHistogramRegistry->get(HIST("CollCutCounts"))->GetXaxis()->SetBinLabel(binLabel(EvtSel::kNoCollInTimeRangeStandard), "NoCollInTimeRangeStandard"); - mHistogramRegistry->get(HIST("CollCutCounts"))->GetXaxis()->SetBinLabel(binLabel(EvtSel::kNoCollInTimeRangeNarrow), "NoCollInTimeRangeNarrow"); mHistogramRegistry->get(HIST("CollCutCounts"))->GetXaxis()->SetBinLabel(binLabel(EvtSel::kAllpassed), "Allpassed"); } @@ -147,25 +159,53 @@ class CollisonCuts } /// Set MB selection - void setTriggerTVX(bool triggerTVXsel) { mTriggerTVXselection = triggerTVXsel; } + void setTriggerTVX(bool triggerTVXsel) + { + mTriggerTVXselection = triggerTVXsel; + setSelection(EvtSel::kFlagTrigerTVX, triggerTVXsel); + } /// Set the time frame border cut - void setApplyTFBorderCut(bool applyTFBorderCut) { mApplyTFBorderCut = applyTFBorderCut; } + void setApplyTFBorderCut(bool applyTFBorderCut) + { + mApplyTFBorderCut = applyTFBorderCut; + setSelection(EvtSel::kFlagTimeFrameBorder, applyTFBorderCut); + } /// Set the ITS-TPC matching cut - void setApplyITSTPCvertex(bool applyITSTPCvertex) { mApplyITSTPCvertex = applyITSTPCvertex; } + void setApplyITSTPCvertex(bool applyITSTPCvertex) + { + mApplyITSTPCvertex = applyITSTPCvertex; + setSelection(EvtSel::kFlagVertexITSTPC, applyITSTPCvertex); + } /// Set the NoCollInTimeRangeNarrow cut - void setApplyCollInTimeRangeNarrow(bool applyCollInTimeRangeNarrow) { mApplyCollInTimeRangeNarrow = applyCollInTimeRangeNarrow; } + void setApplyCollInTimeRangeNarrow(bool applyCollInTimeRangeNarrow) + { + mApplyCollInTimeRangeNarrow = applyCollInTimeRangeNarrow; + setSelection(EvtSel::kNoCollInTimeRangeNarrow, applyCollInTimeRangeNarrow); + } /// Set the Z-vertex time difference cut - void setApplyZvertexTimedifference(bool applyZvertexTimedifference) { mApplyZvertexTimedifference = applyZvertexTimedifference; } + void setApplyZvertexTimedifference(bool applyZvertexTimedifference) + { + mApplyZvertexTimedifference = applyZvertexTimedifference; + setSelection(EvtSel::kFlagZvtxFT0vsPV, applyZvertexTimedifference); + } /// Set the Pileup rejection - void setApplyPileupRejection(bool applyPileupRejection) { mApplyPileupRejection = applyPileupRejection; } + void setApplyPileupRejection(bool applyPileupRejection) + { + mApplyPileupRejection = applyPileupRejection; + setSelection(EvtSel::kFlagBunchPileup, applyPileupRejection); + } /// Set the NoITSRO frame border cut - void setApplyNoITSROBorderCut(bool applyNoITSROBorderCut) { mApplyNoITSROBorderCut = applyNoITSROBorderCut; } + void setApplyNoITSROBorderCut(bool applyNoITSROBorderCut) + { + mApplyNoITSROBorderCut = applyNoITSROBorderCut; + setSelection(EvtSel::kFlagITSROFrameBorder, applyNoITSROBorderCut); + } /// Set the track occupancy in time range cut void setTrackOccupancyInTimeRange(int trackOccupancyInTimeRangeMax, int trackOccupancyInTimeRangeMin) @@ -174,7 +214,79 @@ class CollisonCuts mtrackOccupancyInTimeRangeMin = trackOccupancyInTimeRangeMin; } /// Set the NoCollInTimeRangeStandard cut - void setApplyCollInTimeRangeStandard(bool applyCollInTimeRangeStandard) { mApplyCollInTimeRangeStandard = applyCollInTimeRangeStandard; } + void setApplyCollInTimeRangeStandard(bool applyCollInTimeRangeStandard) + { + mApplyCollInTimeRangeStandard = applyCollInTimeRangeStandard; + setSelection(EvtSel::kNoCollInTimeRangeStandard, applyCollInTimeRangeStandard); + } + + /// Set the GoodITSLayersAll cut + void setApplyGoodITSLayersAll(bool applyGoodITSLayersAll) + { + mApplyGoodITSLayersAll = applyGoodITSLayersAll; + setSelection(EvtSel::kIsGoodITSLayersAll, applyGoodITSLayersAll); + } + + /// Set the GoodITSLayer3 cut + void setApplyGoodITSLayer3(bool applyGoodITSLayer3) + { + setSelection(EvtSel::kIsGoodITSLayer3, applyGoodITSLayer3); + } + + /// Set the GoodITSLayer0123 cut + void setApplyGoodITSLayer0123(bool applyGoodITSLayer0123) + { + setSelection(EvtSel::kIsGoodITSLayer0123, applyGoodITSLayer0123); + } + + /// Set the NoCollInTimeRangeStrict cut + void setApplyCollInTimeRangeStrict(bool apply) + { + mApplyCollInTimeRangeStrict = apply; + setSelection(EvtSel::kNoCollInTimeRangeStrict, apply); + } + + /// Set the NoCollInRofStandard cut + void setApplyCollInRofStandard(bool apply) + { + mApplyCollInRofStandard = apply; + setSelection(EvtSel::kNoCollInRofStandard, apply); + } + + /// Set the NoCollInRofStrict cut + void setApplyCollInRofStrict(bool apply) + { + mApplyCollInRofStrict = apply; + setSelection(EvtSel::kNoCollInRofStrict, apply); + } + + /// Set the NoHighMultCollInPrevRof cut + void setApplyHighMultCollInPrevRof(bool apply) + { + mApplyHighMultCollInPrevRof = apply; + setSelection(EvtSel::kNoHighMultCollInPrevRof, apply); + } + + /// Set the VertexTRDmatched cut + void setApplyVertexTRDmatched(bool apply) + { + mApplyVertexTRDmatched = apply; + setSelection(EvtSel::kFlagVertexTRDmatched, apply); + } + + /// Set the BBT0A cut + void setApplyBBT0A(bool apply) + { + mApplyBBT0A = apply; + setSelection(EvtSel::kFlagBBT0A, apply); + } + + /// Set the BBT0C cut + void setApplyBBT0C(bool apply) + { + mApplyBBT0C = apply; + setSelection(EvtSel::kFlagBBT0C, apply); + } /// Set the Run2 AliEventCuts cut void setApplyRun2AliEventCuts(bool applyRun2AliEventCuts) { mApplyRun2AliEventCuts = applyRun2AliEventCuts; } @@ -182,6 +294,67 @@ class CollisonCuts /// Set the Run2 INELgtZERO cut void setApplyRun2INELgtZERO(bool applyRun2INELgtZERO) { mApplyRun2INELgtZERO = applyRun2INELgtZERO; } + /// Overload that accepts a CollisionCutsGroup and isRun3 flag + /// \param settings The CollisionCutsGroup containing all selection parameters + /// \param checkRun3 Whether this is Run3 data (true) or Run2 (false) + void setCuts(const CollisionCutsGroup& settings, bool checkRun3) + { + mCutsSet = true; + mZvtxMax = settings.getZvtxMax(); + mCheckTrigger = settings.getCheckTrigger(); + mCheckOffline = settings.getCheckOffline(); + mCheckIsRun3 = checkRun3; + mApplyTFBorderCut = false; + mApplyITSTPCvertex = false; + mApplyZvertexTimedifference = false; + mApplyPileupRejection = false; + mApplyNoITSROBorderCut = false; + mApplyCollInTimeRangeNarrow = false; + mApplyCollInTimeRangeStandard = false; + mApplyGoodITSLayersAll = false; + mtrackOccupancyInTimeRangeMax = settings.getOccupancyInTimeRangeMax(); + mtrackOccupancyInTimeRangeMin = settings.getOccupancyInTimeRangeMin(); + mApplyRun2AliEventCuts = settings.getApplyRun2AliEventCuts(); + mApplyRun2INELgtZERO = settings.getApplyRun2INELgtZERO(); + mTriggerTVXselection = false; + + // Apply all other settings via delegation + settings.applyToCollisonCuts(*this); + } + + /// Apply settings from a CollisionCutsGroup object (alternative to setCuts) + /// \param settings The CollisionCutsGroup containing all selection parameters + void applySettings(const CollisionCutsGroup& settings) + { + settings.applyToCollisonCuts(*this); + } + + /// Generic selection control (NEW API) + /// \param evtSelFlag Event selection flag from EvtSel enum + /// \param enable Whether to enable (true) or disable (false) this selection + void setSelection(int evtSelFlag, bool enable) + { + mEnabledSelections[evtSelFlag] = enable; + } + + /// Get current state of a selection + /// \param evtSelFlag Event selection flag from EvtSel enum + /// \return Whether the selection is enabled + bool getSelection(int evtSelFlag) const + { + auto it = mEnabledSelections.find(evtSelFlag); + return it != mEnabledSelections.end() ? it->second : false; + } + + /// Enable multiple selections at once + /// \param selections Vector of pairs (evtSelFlag, enabled) + void setSelections(const std::vector>& selections) + { + for (const auto& [flag, enabled] : selections) { + setSelection(flag, enabled); + } + } + /// Check whether the collisions fulfills the specified selections /// \tparam T type of the collision /// \param col Collision @@ -212,27 +385,33 @@ class CollisonCuts mHistogramRegistry->fill(HIST("CollCutCounts"), EvtSel::kFlagZvertex); } if (mCheckIsRun3) { // Run3 case - if (!col.selection_bit(aod::evsel::kIsTriggerTVX) && mTriggerTVXselection) { - LOGF(debug, "Offline selection TVX failed (Run3)"); - return false; - } - if (QA) { - mHistogramRegistry->fill(HIST("CollCutCounts"), EvtSel::kFlagTrigerTVX); - } - if (!col.selection_bit(aod::evsel::kNoTimeFrameBorder) && mApplyTFBorderCut) { - LOGF(debug, "Time frame border cut failed"); - return false; - } - if (QA) { - mHistogramRegistry->fill(HIST("CollCutCounts"), EvtSel::kFlagTimeFrameBorder); - } - if (!col.selection_bit(aod::evsel::kNoITSROFrameBorder) && mApplyNoITSROBorderCut) { - LOGF(debug, "NoITSRO frame border cut failed"); - return false; - } - if (QA) { - mHistogramRegistry->fill(HIST("CollCutCounts"), EvtSel::kFlagITSROFrameBorder); + // Metadata-driven selection loop for registry-based cuts + for (const auto& [evtSelFlag, enabled] : mEnabledSelections) { + if (!enabled) { + continue; // Skip disabled selections + } + + auto it = sSelectionRegistry.find(evtSelFlag); + if (it == sSelectionRegistry.end()) { + LOGF(warning, "Unknown selection flag %d in mEnabledSelections", evtSelFlag); + continue; + } + + const auto& metadata = it->second; + + // Check the selection_bit + if (!col.selection_bit(metadata.evselFlag)) { + LOGF(debug, "%s", metadata.debugMessage); + return false; + } + + // Fill QA histogram + if (QA) { + mHistogramRegistry->fill(HIST("CollCutCounts"), metadata.histogramBin); + } } + + // Special case: sel8 (not using selection_bit) if (!col.sel8() && mCheckOffline) { LOGF(debug, "Offline selection failed (Run3)"); return false; @@ -240,34 +419,8 @@ class CollisonCuts if (QA) { mHistogramRegistry->fill(HIST("CollCutCounts"), EvtSel::kFlagSel8); } - if (!col.selection_bit(o2::aod::evsel::kIsVertexITSTPC) && mApplyITSTPCvertex) { - LOGF(debug, "ITS-TPC matching cut failed"); - return false; - } - if (QA) { - mHistogramRegistry->fill(HIST("CollCutCounts"), EvtSel::kFlagVertexITSTPC); - } - if (!col.selection_bit(o2::aod::evsel::kNoSameBunchPileup) && mApplyPileupRejection) { - LOGF(debug, "Pileup rejection failed"); - return false; - } - if (QA) { - mHistogramRegistry->fill(HIST("CollCutCounts"), EvtSel::kFlagBunchPileup); - } - if (!col.selection_bit(o2::aod::evsel::kNoCollInTimeRangeNarrow) && mApplyCollInTimeRangeNarrow) { - LOGF(debug, "NoCollInTimeRangeNarrow selection failed"); - return false; - } - if (QA) { - mHistogramRegistry->fill(HIST("CollCutCounts"), EvtSel::kNoCollInTimeRangeNarrow); - } - if (!col.selection_bit(o2::aod::evsel::kIsGoodZvtxFT0vsPV) && mApplyZvertexTimedifference) { - LOGF(debug, "Z-vertex time difference cut failed"); - return false; - } - if (QA) { - mHistogramRegistry->fill(HIST("CollCutCounts"), EvtSel::kFlagZvtxFT0vsPV); - } + + // Special case: Occupancy cuts (custom logic) if (mtrackOccupancyInTimeRangeMax > 0 && col.trackOccupancyInTimeRange() > mtrackOccupancyInTimeRangeMax) { LOGF(debug, "trackOccupancyInTimeRange selection failed"); return false; @@ -279,13 +432,6 @@ class CollisonCuts if (QA) { mHistogramRegistry->fill(HIST("CollCutCounts"), EvtSel::kFlagOccupancy); } - if ((!col.selection_bit(o2::aod::evsel::kNoCollInTimeRangeStandard)) && mApplyCollInTimeRangeStandard) { - LOGF(debug, "NoCollInTimeRangeStandard selection failed"); - return false; - } - if (QA) { - mHistogramRegistry->fill(HIST("CollCutCounts"), EvtSel::kNoCollInTimeRangeStandard); - } } else { // Run2 case if (mCheckOffline && !col.sel7()) { LOGF(debug, "Offline selection failed (sel7)"); @@ -343,6 +489,26 @@ class CollisonCuts } private: + /// Metadata structure for event selections + struct SelectionMetadata { + int evselFlag; ///< o2::aod::evsel::EventSelectionFlags value + const char* label; ///< Histogram label + const char* debugMessage; ///< Debug message for LOGF + int histogramBin; ///< Position in EvtSel enum (for histogram bin) + }; + + /// Central registry mapping EvtSel enum to metadata (auto-generated from EventSelectionFlagsMapping.def) + inline static const std::map sSelectionRegistry = { + // AUTO-GENERATED from EventSelectionFlagsMapping.def +#define EVSEL_FLAG(enumVal, member, defaultVal, evtSelEnum, setter, getter, label, desc) \ + {EvtSel::evtSelEnum, {aod::evsel::enumVal, label, desc " selection failed", EvtSel::evtSelEnum}}, +#include "PWGLF/Utils/EventSelectionFlagsMapping.def" +#undef EVSEL_FLAG + }; + + /// Dynamic selection state: which selections are enabled + std::map mEnabledSelections; + using BCsWithRun2Info = soa::Join; o2::framework::HistogramRegistry* mHistogramRegistry = nullptr; ///< For QA output std::vector bitList; @@ -359,6 +525,14 @@ class CollisonCuts bool mApplyPileupRejection = false; ///< Pileup rejection bool mApplyNoITSROBorderCut = false; ///< Apply NoITSRO frame border cut bool mApplyCollInTimeRangeStandard = false; ///< Apply NoCollInTimeRangeStandard selection + bool mApplyGoodITSLayersAll = false; ///< Apply GoodITSLayersAll selection (cuts time intervals with dead ITS staves) + bool mApplyCollInTimeRangeStrict = false; ///< Apply NoCollInTimeRangeStrict selection + bool mApplyCollInRofStandard = false; ///< Apply NoCollInRofStandard selection + bool mApplyCollInRofStrict = false; ///< Apply NoCollInRofStrict selection + bool mApplyHighMultCollInPrevRof = false; ///< Apply NoHighMultCollInPrevRof selection + bool mApplyVertexTRDmatched = false; ///< Apply vertex TRD matched selection + bool mApplyBBT0A = false; ///< Apply T0A beam-beam timing selection + bool mApplyBBT0C = false; ///< Apply T0C beam-beam timing selection bool mApplyRun2AliEventCuts = true; ///< Apply Run2 AliEventCuts bool mApplyRun2INELgtZERO = false; ///< Apply Run2 INELgtZERO selection float mZvtxMax = 999.f; ///< Maximal deviation from nominal z-vertex (cm) diff --git a/PWGLF/Utils/collisionCutsGroup.cxx b/PWGLF/Utils/collisionCutsGroup.cxx new file mode 100644 index 00000000000..1fd5e44767d --- /dev/null +++ b/PWGLF/Utils/collisionCutsGroup.cxx @@ -0,0 +1,86 @@ +// 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 collisionCutsGroup.cxx +/// \brief Implementation of CollisionCutsGroup class +/// +/// Event selection flags are auto-generated from EventSelectionFlagsMapping.def +/// using X-macros for member initialization, setter calls, and logging. +/// +/// \author Bong-Hwi Lim +/// o2-linter: disable=name/workflow-file (Library implementation file, not a workflow) + +#include "PWGLF/Utils/collisionCutsGroup.h" +#include "PWGLF/Utils/collisionCuts.h" +#include "Framework/Logger.h" + +CollisionCutsGroup::CollisionCutsGroup() + : zvtxMax{10.0f}, + occupancyInTimeRangeMax{-1}, + occupancyInTimeRangeMin{-1}, + checkTrigger{false}, + checkOffline{true}, + // AUTO-GENERATED member initialization from EventSelectionFlagsMapping.def +#define EVSEL_FLAG(enumVal, member, defaultVal, evtSelEnum, setter, getter, label, desc) \ + member{defaultVal}, +#include "EventSelectionFlagsMapping.def" +#undef EVSEL_FLAG + // Manual Run2 flag initialization + applyRun2AliEventCuts{true}, + applyRun2INELgtZERO{false} +{ + // Constructor - member initialization done in initializer list +} + +void CollisionCutsGroup::applyToCollisonCuts(o2::analysis::CollisonCuts& cuts) const +{ + // AUTO-GENERATED setter method calls from EventSelectionFlagsMapping.def +#define EVSEL_FLAG(enumVal, member, defaultVal, evtSelEnum, setter, getter, label, desc) \ + cuts.setter(member); +#include "EventSelectionFlagsMapping.def" +#undef EVSEL_FLAG + + // Manual setter calls for non-flag members + cuts.setTrackOccupancyInTimeRange(occupancyInTimeRangeMax, occupancyInTimeRangeMin); + cuts.setApplyRun2AliEventCuts(applyRun2AliEventCuts); + cuts.setApplyRun2INELgtZERO(applyRun2INELgtZERO); +} + +void CollisionCutsGroup::printSelections() const +{ + LOGF(info, ""); + LOGF(info, "+++ Collision Selection Settings ++++++++++++++++++++++++"); + LOGF(info, ""); + LOGF(info, "Basic Parameters:"); + LOGF(info, " Max z-vertex (cm) ......................: %.2f", zvtxMax); + LOGF(info, " Occupancy max ..........................: %d", occupancyInTimeRangeMax); + LOGF(info, " Occupancy min ..........................: %d", occupancyInTimeRangeMin); + LOGF(info, ""); + LOGF(info, "General Flags:"); + LOGF(info, " Check trigger ..........................: %s", checkTrigger ? "true" : "false"); + LOGF(info, " Check offline ..........................: %s", checkOffline ? "true" : "false"); + LOGF(info, ""); + LOGF(info, "Run 3 Selections (from EventSelectionFlags):"); + + // AUTO-GENERATED logging from EventSelectionFlagsMapping.def +#define EVSEL_FLAG(enumVal, member, defaultVal, evtSelEnum, setter, getter, label, desc) \ + LOGF(info, " %-40s: %s", desc, member ? "true" : "false"); +#include "EventSelectionFlagsMapping.def" +#undef EVSEL_FLAG + + LOGF(info, ""); + LOGF(info, "Run 2 Selections:"); + LOGF(info, " Apply Run2 AliEventCuts ................: %s", applyRun2AliEventCuts ? "true" : "false"); + LOGF(info, " Apply Run2 INEL>0 ......................: %s", applyRun2INELgtZERO ? "true" : "false"); + LOGF(info, ""); + LOGF(info, "+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++"); + LOGF(info, ""); +} diff --git a/PWGLF/Utils/collisionCutsGroup.h b/PWGLF/Utils/collisionCutsGroup.h new file mode 100644 index 00000000000..a741046b967 --- /dev/null +++ b/PWGLF/Utils/collisionCutsGroup.h @@ -0,0 +1,109 @@ +// 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 collisionCutsGroup.h +/// \brief Configurable group for collision event selection cuts +/// +/// This class follows the v0SelectionGroup pattern to enable automatic +/// configurable registration in O2 analysis tasks via ROOT serialization. +/// +/// Usage in analysis tasks: +/// Configurable collCuts{"collCuts", {}, "Collision event selection"}; +/// o2::analysis::CollisonCuts colCutsChecker; +/// +/// void init(InitContext const&) { +/// colCutsChecker.init(®istry); +/// colCutsChecker.setCuts(collCuts, /*isRun3*/ true); +/// } +/// +/// \author Bong-Hwi Lim + +#ifndef PWGLF_UTILS_COLLISIONCUTSGROUP_H_ +#define PWGLF_UTILS_COLLISIONCUTSGROUP_H_ + +#include +#include +#include "Common/CCDB/EventSelectionParams.h" + +// Forward declaration to avoid circular dependency +namespace o2::analysis +{ +class CollisonCuts; +} + +/// \class collisionCutsGroup +/// \brief ROOT-serializable container for collision event selection parameters +/// +/// This class encapsulates all collision selection parameters as member variables, +/// enabling automatic configurable registration via the DPL framework's ROOT +/// dictionary introspection. This eliminates the need for manual configurable +/// declarations in each analysis task. +/// +/// Event selection flags are synchronized with o2::aod::evsel::EventSelectionFlags +/// via X-macros defined in EventSelectionFlagsMapping.def. To add new flags, simply +/// add an entry to that file - all getters, members, setters, and metadata are +/// auto-generated. +class CollisionCutsGroup +{ + public: + /// Default constructor with standard default values + CollisionCutsGroup(); + + /// Apply all settings to a CollisonCuts object + /// \param cuts The CollisonCuts object to configure + void applyToCollisonCuts(o2::analysis::CollisonCuts& cuts) const; + + /// Print all selection settings for debugging + void printSelections() const; + + // ===== Getters for non-flag members ===== + float getZvtxMax() const { return zvtxMax; } + int getOccupancyInTimeRangeMax() const { return occupancyInTimeRangeMax; } + int getOccupancyInTimeRangeMin() const { return occupancyInTimeRangeMin; } + bool getCheckTrigger() const { return checkTrigger; } + bool getCheckOffline() const { return checkOffline; } + + // ===== AUTO-GENERATED GETTERS for event selection flags ===== + // Generated from EventSelectionFlagsMapping.def +#define EVSEL_FLAG(enumVal, member, defaultVal, evtSelEnum, setter, getter, label, desc) \ + bool get##getter() const { return member; } +#include "EventSelectionFlagsMapping.def" +#undef EVSEL_FLAG + + // ===== Getters for Run2-specific flags (not in EventSelectionFlags) ===== + bool getApplyRun2AliEventCuts() const { return applyRun2AliEventCuts; } + bool getApplyRun2INELgtZERO() const { return applyRun2INELgtZERO; } + + private: + // ===== Basic collision parameters ===== + float zvtxMax; ///< Maximum z-vertex position (cm) + int occupancyInTimeRangeMax; ///< Maximum track occupancy (-1 = no cut) + int occupancyInTimeRangeMin; ///< Minimum track occupancy (-1 = no cut) + + // ===== General event selection flags ===== + bool checkTrigger; ///< Check for trigger + bool checkOffline; ///< Check for offline selection + + // ===== AUTO-GENERATED event selection flag members ===== + // Generated from EventSelectionFlagsMapping.def +#define EVSEL_FLAG(enumVal, member, defaultVal, evtSelEnum, setter, getter, label, desc) \ + bool member; ///< desc +#include "EventSelectionFlagsMapping.def" +#undef EVSEL_FLAG + + // ===== Run2-specific selections (not in EventSelectionFlags) ===== + bool applyRun2AliEventCuts; ///< Run2 AliEventCuts + bool applyRun2INELgtZERO; ///< Run2 INEL>0 selection + + ClassDefNV(CollisionCutsGroup, 2); +}; + +#endif // PWGLF_UTILS_COLLISIONCUTSGROUP_H_ diff --git a/PWGLF/Utils/collisionCutsGroupLinkDef.h b/PWGLF/Utils/collisionCutsGroupLinkDef.h new file mode 100644 index 00000000000..e327556fbd2 --- /dev/null +++ b/PWGLF/Utils/collisionCutsGroupLinkDef.h @@ -0,0 +1,34 @@ +// 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 collisionCutsGroupLinkDef.h +/// \brief ROOT dictionary LinkDef for CollisionCutsGroup +/// +/// This file instructs rootcling to generate the ROOT dictionary +/// for CollisionCutsGroup, enabling DPL auto-discovery of configurables. +/// +/// \author Bong-Hwi Lim + +#ifndef PWGLF_UTILS_COLLISIONCUTSGROUPLINKDEF_H_ +#define PWGLF_UTILS_COLLISIONCUTSGROUPLINKDEF_H_ + +#pragma link off all globals; +#pragma link off all classes; +#pragma link off all functions; + +#pragma link C++ nestedclasses; + +#pragma link C++ class CollisionCutsGroup + ; +#pragma link C++ class std::vector < int> + ; +#pragma link C++ class std::vector < float> + ; +#pragma link C++ class std::vector < bool> + ; + +#endif // PWGLF_UTILS_COLLISIONCUTSGROUPLINKDEF_H_ diff --git a/Tutorials/PWGLF/CMakeLists.txt b/Tutorials/PWGLF/CMakeLists.txt index ae8ac8ad1f4..1ce6633a0af 100644 --- a/Tutorials/PWGLF/CMakeLists.txt +++ b/Tutorials/PWGLF/CMakeLists.txt @@ -11,4 +11,5 @@ add_subdirectory(Resonance) add_subdirectory(Strangeness) +add_subdirectory(Utils) diff --git a/Tutorials/PWGLF/Utils/CMakeLists.txt b/Tutorials/PWGLF/Utils/CMakeLists.txt new file mode 100644 index 00000000000..25f636c2a51 --- /dev/null +++ b/Tutorials/PWGLF/Utils/CMakeLists.txt @@ -0,0 +1,16 @@ +# Copyright 2019-2020 CERN and copyright holders of ALICE O2. +# See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +# All rights not expressly granted are reserved. +# +# This software is distributed under the terms of the GNU General Public +# License v3 (GPL Version 3), copied verbatim in the file "COPYING". +# +# In applying this license CERN does not waive the privileges and immunities +# granted to it by virtue of its status as an Intergovernmental Organization +# or submit itself to any jurisdiction. + +# PWGLF Utils tutorial +o2physics_add_dpl_workflow(collision-cuts-tutorial + SOURCES collisionCuts.cxx + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore O2Physics::collisionCutsGroup + COMPONENT_NAME AnalysisTutorial) diff --git a/Tutorials/PWGLF/Utils/README.md b/Tutorials/PWGLF/Utils/README.md new file mode 100644 index 00000000000..74dd7c7ea65 --- /dev/null +++ b/Tutorials/PWGLF/Utils/README.md @@ -0,0 +1,65 @@ +# PWGLF Utils Tutorial + +This directory contains tutorials for common PWGLF utilities and helper classes. + +## Collision Cuts Tutorial + +**File:** `collisionCuts.cxx` + +**Workflow:** `o2-analysis-collision-cuts-tutorial` + +This tutorial demonstrates how to use the `collisionCutsGroup` pattern for automatic configurable registration of collision event selection parameters. + +### Key Features: + +- **Automatic Configurable Registration**: All collision selection parameters are automatically registered by the DPL framework with a single line of code +- **Reduced Boilerplate**: Traditional approach requires ~30 lines of manual configurable declarations, the new pattern reduces this to ~5 lines +- **Comprehensive Event Selection**: Includes z-vertex cuts, centrality cuts, time frame cuts, occupancy cuts, and various Run 3 event selection flags + +### What You'll Learn: + +1. How to declare a `collisionCutsGroup` configurable +2. How to apply settings from the group to a `CollisonCuts` object +3. How to use the collision cuts checker to filter events +4. How to fill QA histograms for selected events + +### Running the Tutorial: + +```bash +# Load O2Physics environment +alienv enter O2Physics/latest + +# Run the tutorial +o2-analysis-collision-cuts-tutorial --aod-file +``` + +### Customizing Cuts: + +The collision cuts can be customized via JSON configuration file: + +```json +{ + "collision-cuts-tutorial": { + "collCuts": { + "VtxRange": 10.0, + "CentMin": 0.0, + "CentMax": 90.0, + "CentEstimator": 1, + "IsRun3": true, + "DoOccupancySel": true, + "OccupancyMax": 1000 + } + } +} +``` + +For a complete list of available parameters, run: +```bash +o2-analysis-collision-cuts-tutorial --help full +``` + +### Related Documentation: + +- Main collision cuts implementation: `PWGLF/Utils/collisionCuts.h` +- Configurable group implementation: `PWGLF/Utils/collisionCutsGroup.h` +- Event selection parameters: `Common/CCDB/EventSelectionParams.h` diff --git a/Tutorials/PWGLF/Utils/collisionCuts.cxx b/Tutorials/PWGLF/Utils/collisionCuts.cxx new file mode 100644 index 00000000000..b027b76507a --- /dev/null +++ b/Tutorials/PWGLF/Utils/collisionCuts.cxx @@ -0,0 +1,90 @@ +// 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 collisionCuts.cxx +/// \brief Tutorial: Using CollisionCutsGroup for automatic configurable registration +/// \author Bong-Hwi Lim +/// \since 30/12/2024 + +#include "Framework/runDataProcessing.h" +#include "Framework/AnalysisTask.h" +#include "Common/DataModel/Centrality.h" +#include "Common/DataModel/EventSelection.h" +#include "PWGLF/Utils/collisionCuts.h" +#include "PWGLF/Utils/collisionCutsGroup.h" + +using namespace o2; +using namespace o2::framework; +using namespace o2::framework::expressions; + +// Tutorial: Collision Cuts with Automatic Configurable Registration +// This tutorial demonstrates the new CollisionCutsGroup pattern that enables +// automatic configurable registration, reducing boilerplate from ~30 lines to ~5 lines. +struct CollisionCutsTutorial { // o2-linter: disable=name/workflow-file (Tutorial file naming convention) + // NEW PATTERN: Single line configurable declaration! + // All collision selection parameters are automatically registered by DPL framework + Configurable collCuts{"collCuts", {}, "Collision event selection cuts"}; + + // Collision cuts checker object + o2::analysis::CollisonCuts colCutsChecker; + + // Histogram registry + HistogramRegistry histos{"histos", {}, OutputObjHandlingPolicy::AnalysisObject}; + + void init(InitContext const&) + { + LOGF(info, "=========================================================="); + LOGF(info, "Tutorial: collisionCutsGroup Automatic Configurable Registration"); + LOGF(info, "=========================================================="); + LOGF(info, ""); + + // Print all settings from CollisionCutsGroup + LOGF(info, "Step 1: Printing CollisionCutsGroup settings..."); + collCuts->printSelections(); + + // Apply settings from CollisionCutsGroup to CollisonCuts FIRST + LOGF(info, "Step 2: Applying CollisionCutsGroup settings to CollisonCuts..."); + colCutsChecker.setCuts(collCuts, /*isRun3*/ true); + + // Then initialize collision cuts checker (creates histograms based on settings) + LOGF(info, "Step 3: Initializing CollisonCuts object..."); + colCutsChecker.init(&histos); + + // Print CollisonCuts settings for verification + LOGF(info, "Step 4: Printing CollisonCuts settings after application..."); + colCutsChecker.printCuts(); + + LOGF(info, ""); + LOGF(info, "=========================================================="); + LOGF(info, "Tutorial: Initialization Complete!"); + LOGF(info, "=========================================================="); + LOGF(info, ""); + } + + void process(soa::Join::iterator const& collision) + { + // Test collision selection + bool isSelected = colCutsChecker.isSelected(collision); + + if (isSelected) { + LOGF(debug, "Collision passed selection: z-vertex = %.2f cm", collision.posZ()); + colCutsChecker.fillQA(collision); + } else { + LOGF(debug, "Collision rejected by selection"); + } + } +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{ + adaptAnalysisTask(cfgc)}; +} From 066bb3851c9ef84419a4c897fac9da7b6ba065b8 Mon Sep 17 00:00:00 2001 From: Bong-Hwi Lim Date: Tue, 30 Dec 2025 11:43:53 +0900 Subject: [PATCH 2/8] modift readme --- Tutorials/PWGLF/Utils/README.md | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/Tutorials/PWGLF/Utils/README.md b/Tutorials/PWGLF/Utils/README.md index 74dd7c7ea65..5e167f2156b 100644 --- a/Tutorials/PWGLF/Utils/README.md +++ b/Tutorials/PWGLF/Utils/README.md @@ -23,16 +23,6 @@ This tutorial demonstrates how to use the `collisionCutsGroup` pattern for autom 3. How to use the collision cuts checker to filter events 4. How to fill QA histograms for selected events -### Running the Tutorial: - -```bash -# Load O2Physics environment -alienv enter O2Physics/latest - -# Run the tutorial -o2-analysis-collision-cuts-tutorial --aod-file -``` - ### Customizing Cuts: The collision cuts can be customized via JSON configuration file: From 0291b4826ee517d2bad00471c3466b3a10499a1e Mon Sep 17 00:00:00 2001 From: ALICE Action Bot Date: Tue, 30 Dec 2025 02:51:12 +0000 Subject: [PATCH 3/8] Please consider the following formatting changes --- PWGLF/Utils/collisionCuts.h | 15 ++++++++------- PWGLF/Utils/collisionCutsGroup.cxx | 6 ++++-- PWGLF/Utils/collisionCutsGroup.h | 22 ++++++++++++---------- Tutorials/PWGLF/Utils/collisionCuts.cxx | 11 +++++++---- 4 files changed, 31 insertions(+), 23 deletions(-) diff --git a/PWGLF/Utils/collisionCuts.h b/PWGLF/Utils/collisionCuts.h index 10497b75d12..7b23620ee64 100644 --- a/PWGLF/Utils/collisionCuts.h +++ b/PWGLF/Utils/collisionCuts.h @@ -21,11 +21,12 @@ #ifndef PWGLF_UTILS_COLLISIONCUTS_H_ #define PWGLF_UTILS_COLLISIONCUTS_H_ +#include "PWGLF/Utils/collisionCutsGroup.h" + #include "Common/DataModel/EventSelection.h" #include "Framework/HistogramRegistry.h" #include "Framework/Logger.h" -#include "PWGLF/Utils/collisionCutsGroup.h" #include #include @@ -491,17 +492,17 @@ class CollisonCuts private: /// Metadata structure for event selections struct SelectionMetadata { - int evselFlag; ///< o2::aod::evsel::EventSelectionFlags value - const char* label; ///< Histogram label - const char* debugMessage; ///< Debug message for LOGF - int histogramBin; ///< Position in EvtSel enum (for histogram bin) + int evselFlag; ///< o2::aod::evsel::EventSelectionFlags value + const char* label; ///< Histogram label + const char* debugMessage; ///< Debug message for LOGF + int histogramBin; ///< Position in EvtSel enum (for histogram bin) }; /// Central registry mapping EvtSel enum to metadata (auto-generated from EventSelectionFlagsMapping.def) inline static const std::map sSelectionRegistry = { - // AUTO-GENERATED from EventSelectionFlagsMapping.def + // AUTO-GENERATED from EventSelectionFlagsMapping.def #define EVSEL_FLAG(enumVal, member, defaultVal, evtSelEnum, setter, getter, label, desc) \ - {EvtSel::evtSelEnum, {aod::evsel::enumVal, label, desc " selection failed", EvtSel::evtSelEnum}}, + {EvtSel::evtSelEnum, {aod::evsel::enumVal, label, desc " selection failed", EvtSel::evtSelEnum}}, #include "PWGLF/Utils/EventSelectionFlagsMapping.def" #undef EVSEL_FLAG }; diff --git a/PWGLF/Utils/collisionCutsGroup.cxx b/PWGLF/Utils/collisionCutsGroup.cxx index 1fd5e44767d..60fedce5277 100644 --- a/PWGLF/Utils/collisionCutsGroup.cxx +++ b/PWGLF/Utils/collisionCutsGroup.cxx @@ -19,7 +19,9 @@ /// o2-linter: disable=name/workflow-file (Library implementation file, not a workflow) #include "PWGLF/Utils/collisionCutsGroup.h" + #include "PWGLF/Utils/collisionCuts.h" + #include "Framework/Logger.h" CollisionCutsGroup::CollisionCutsGroup() @@ -28,9 +30,9 @@ CollisionCutsGroup::CollisionCutsGroup() occupancyInTimeRangeMin{-1}, checkTrigger{false}, checkOffline{true}, - // AUTO-GENERATED member initialization from EventSelectionFlagsMapping.def +// AUTO-GENERATED member initialization from EventSelectionFlagsMapping.def #define EVSEL_FLAG(enumVal, member, defaultVal, evtSelEnum, setter, getter, label, desc) \ - member{defaultVal}, + member{defaultVal}, #include "EventSelectionFlagsMapping.def" #undef EVSEL_FLAG // Manual Run2 flag initialization diff --git a/PWGLF/Utils/collisionCutsGroup.h b/PWGLF/Utils/collisionCutsGroup.h index a741046b967..3497e507695 100644 --- a/PWGLF/Utils/collisionCutsGroup.h +++ b/PWGLF/Utils/collisionCutsGroup.h @@ -29,10 +29,12 @@ #ifndef PWGLF_UTILS_COLLISIONCUTSGROUP_H_ #define PWGLF_UTILS_COLLISIONCUTSGROUP_H_ -#include -#include #include "Common/CCDB/EventSelectionParams.h" +#include + +#include + // Forward declaration to avoid circular dependency namespace o2::analysis { @@ -84,24 +86,24 @@ class CollisionCutsGroup private: // ===== Basic collision parameters ===== - float zvtxMax; ///< Maximum z-vertex position (cm) - int occupancyInTimeRangeMax; ///< Maximum track occupancy (-1 = no cut) - int occupancyInTimeRangeMin; ///< Minimum track occupancy (-1 = no cut) + float zvtxMax; ///< Maximum z-vertex position (cm) + int occupancyInTimeRangeMax; ///< Maximum track occupancy (-1 = no cut) + int occupancyInTimeRangeMin; ///< Minimum track occupancy (-1 = no cut) // ===== General event selection flags ===== - bool checkTrigger; ///< Check for trigger - bool checkOffline; ///< Check for offline selection + bool checkTrigger; ///< Check for trigger + bool checkOffline; ///< Check for offline selection // ===== AUTO-GENERATED event selection flag members ===== // Generated from EventSelectionFlagsMapping.def #define EVSEL_FLAG(enumVal, member, defaultVal, evtSelEnum, setter, getter, label, desc) \ - bool member; ///< desc + bool member; ///< desc #include "EventSelectionFlagsMapping.def" #undef EVSEL_FLAG // ===== Run2-specific selections (not in EventSelectionFlags) ===== - bool applyRun2AliEventCuts; ///< Run2 AliEventCuts - bool applyRun2INELgtZERO; ///< Run2 INEL>0 selection + bool applyRun2AliEventCuts; ///< Run2 AliEventCuts + bool applyRun2INELgtZERO; ///< Run2 INEL>0 selection ClassDefNV(CollisionCutsGroup, 2); }; diff --git a/Tutorials/PWGLF/Utils/collisionCuts.cxx b/Tutorials/PWGLF/Utils/collisionCuts.cxx index b027b76507a..964cedaf2c4 100644 --- a/Tutorials/PWGLF/Utils/collisionCuts.cxx +++ b/Tutorials/PWGLF/Utils/collisionCuts.cxx @@ -14,13 +14,16 @@ /// \author Bong-Hwi Lim /// \since 30/12/2024 -#include "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" -#include "Common/DataModel/Centrality.h" -#include "Common/DataModel/EventSelection.h" #include "PWGLF/Utils/collisionCuts.h" + #include "PWGLF/Utils/collisionCutsGroup.h" +#include "Common/DataModel/Centrality.h" +#include "Common/DataModel/EventSelection.h" + +#include "Framework/AnalysisTask.h" +#include "Framework/runDataProcessing.h" + using namespace o2; using namespace o2::framework; using namespace o2::framework::expressions; From 88a53dee379ca51ea3c25e7231b8f6fa6ff7e695 Mon Sep 17 00:00:00 2001 From: Bong-Hwi Lim Date: Tue, 30 Dec 2025 11:54:35 +0900 Subject: [PATCH 4/8] update file name --- Tutorials/PWGLF/Utils/CMakeLists.txt | 2 +- .../Utils/{collisionCuts.cxx => collisionCutsTutorial.cxx} | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) rename Tutorials/PWGLF/Utils/{collisionCuts.cxx => collisionCutsTutorial.cxx} (99%) diff --git a/Tutorials/PWGLF/Utils/CMakeLists.txt b/Tutorials/PWGLF/Utils/CMakeLists.txt index 25f636c2a51..904eaec1c69 100644 --- a/Tutorials/PWGLF/Utils/CMakeLists.txt +++ b/Tutorials/PWGLF/Utils/CMakeLists.txt @@ -11,6 +11,6 @@ # PWGLF Utils tutorial o2physics_add_dpl_workflow(collision-cuts-tutorial - SOURCES collisionCuts.cxx + SOURCES collisionCutsTutorial.cxx PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore O2Physics::collisionCutsGroup COMPONENT_NAME AnalysisTutorial) diff --git a/Tutorials/PWGLF/Utils/collisionCuts.cxx b/Tutorials/PWGLF/Utils/collisionCutsTutorial.cxx similarity index 99% rename from Tutorials/PWGLF/Utils/collisionCuts.cxx rename to Tutorials/PWGLF/Utils/collisionCutsTutorial.cxx index 964cedaf2c4..3a83f925f43 100644 --- a/Tutorials/PWGLF/Utils/collisionCuts.cxx +++ b/Tutorials/PWGLF/Utils/collisionCutsTutorial.cxx @@ -9,7 +9,7 @@ // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. /// -/// \file collisionCuts.cxx +/// \file collisionCutsTutorial.cxx /// \brief Tutorial: Using CollisionCutsGroup for automatic configurable registration /// \author Bong-Hwi Lim /// \since 30/12/2024 From c3a56096a6dc2ae0d0b01f651daef8c8827446ad Mon Sep 17 00:00:00 2001 From: ALICE Action Bot Date: Tue, 30 Dec 2025 02:59:05 +0000 Subject: [PATCH 5/8] Please consider the following formatting changes --- Tutorials/PWGLF/Utils/collisionCutsTutorial.cxx | 1 - 1 file changed, 1 deletion(-) diff --git a/Tutorials/PWGLF/Utils/collisionCutsTutorial.cxx b/Tutorials/PWGLF/Utils/collisionCutsTutorial.cxx index 3a83f925f43..47747c6e4b2 100644 --- a/Tutorials/PWGLF/Utils/collisionCutsTutorial.cxx +++ b/Tutorials/PWGLF/Utils/collisionCutsTutorial.cxx @@ -15,7 +15,6 @@ /// \since 30/12/2024 #include "PWGLF/Utils/collisionCuts.h" - #include "PWGLF/Utils/collisionCutsGroup.h" #include "Common/DataModel/Centrality.h" From 258a24288fa783374cd98146f538be1fa1aa43f6 Mon Sep 17 00:00:00 2001 From: Bong-Hwi Lim Date: Tue, 30 Dec 2025 12:08:31 +0900 Subject: [PATCH 6/8] update linter avoid for inteded include --- PWGLF/Utils/collisionCutsGroup.cxx | 4 ++-- PWGLF/Utils/collisionCutsGroup.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/PWGLF/Utils/collisionCutsGroup.cxx b/PWGLF/Utils/collisionCutsGroup.cxx index 60fedce5277..e873763849f 100644 --- a/PWGLF/Utils/collisionCutsGroup.cxx +++ b/PWGLF/Utils/collisionCutsGroup.cxx @@ -47,7 +47,7 @@ void CollisionCutsGroup::applyToCollisonCuts(o2::analysis::CollisonCuts& cuts) c // AUTO-GENERATED setter method calls from EventSelectionFlagsMapping.def #define EVSEL_FLAG(enumVal, member, defaultVal, evtSelEnum, setter, getter, label, desc) \ cuts.setter(member); -#include "EventSelectionFlagsMapping.def" +#include "EventSelectionFlagsMapping.def" // NOLINT(build/include) #undef EVSEL_FLAG // Manual setter calls for non-flag members @@ -75,7 +75,7 @@ void CollisionCutsGroup::printSelections() const // AUTO-GENERATED logging from EventSelectionFlagsMapping.def #define EVSEL_FLAG(enumVal, member, defaultVal, evtSelEnum, setter, getter, label, desc) \ LOGF(info, " %-40s: %s", desc, member ? "true" : "false"); -#include "EventSelectionFlagsMapping.def" +#include "EventSelectionFlagsMapping.def" // NOLINT(build/include) #undef EVSEL_FLAG LOGF(info, ""); diff --git a/PWGLF/Utils/collisionCutsGroup.h b/PWGLF/Utils/collisionCutsGroup.h index 3497e507695..f7c1d4a09d7 100644 --- a/PWGLF/Utils/collisionCutsGroup.h +++ b/PWGLF/Utils/collisionCutsGroup.h @@ -98,7 +98,7 @@ class CollisionCutsGroup // Generated from EventSelectionFlagsMapping.def #define EVSEL_FLAG(enumVal, member, defaultVal, evtSelEnum, setter, getter, label, desc) \ bool member; ///< desc -#include "EventSelectionFlagsMapping.def" +#include "EventSelectionFlagsMapping.def" // NOLINT(build/include) #undef EVSEL_FLAG // ===== Run2-specific selections (not in EventSelectionFlags) ===== From 8a6fbbccb15af79776f1e3c307e854389c764548 Mon Sep 17 00:00:00 2001 From: ALICE Action Bot Date: Tue, 30 Dec 2025 03:09:11 +0000 Subject: [PATCH 7/8] Please consider the following formatting changes --- PWGLF/Utils/collisionCutsGroup.cxx | 4 ++-- PWGLF/Utils/collisionCutsGroup.h | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/PWGLF/Utils/collisionCutsGroup.cxx b/PWGLF/Utils/collisionCutsGroup.cxx index e873763849f..daed385f673 100644 --- a/PWGLF/Utils/collisionCutsGroup.cxx +++ b/PWGLF/Utils/collisionCutsGroup.cxx @@ -47,7 +47,7 @@ void CollisionCutsGroup::applyToCollisonCuts(o2::analysis::CollisonCuts& cuts) c // AUTO-GENERATED setter method calls from EventSelectionFlagsMapping.def #define EVSEL_FLAG(enumVal, member, defaultVal, evtSelEnum, setter, getter, label, desc) \ cuts.setter(member); -#include "EventSelectionFlagsMapping.def" // NOLINT(build/include) +#include "EventSelectionFlagsMapping.def" // NOLINT(build/include) #undef EVSEL_FLAG // Manual setter calls for non-flag members @@ -75,7 +75,7 @@ void CollisionCutsGroup::printSelections() const // AUTO-GENERATED logging from EventSelectionFlagsMapping.def #define EVSEL_FLAG(enumVal, member, defaultVal, evtSelEnum, setter, getter, label, desc) \ LOGF(info, " %-40s: %s", desc, member ? "true" : "false"); -#include "EventSelectionFlagsMapping.def" // NOLINT(build/include) +#include "EventSelectionFlagsMapping.def" // NOLINT(build/include) #undef EVSEL_FLAG LOGF(info, ""); diff --git a/PWGLF/Utils/collisionCutsGroup.h b/PWGLF/Utils/collisionCutsGroup.h index f7c1d4a09d7..f891ee9813d 100644 --- a/PWGLF/Utils/collisionCutsGroup.h +++ b/PWGLF/Utils/collisionCutsGroup.h @@ -97,8 +97,8 @@ class CollisionCutsGroup // ===== AUTO-GENERATED event selection flag members ===== // Generated from EventSelectionFlagsMapping.def #define EVSEL_FLAG(enumVal, member, defaultVal, evtSelEnum, setter, getter, label, desc) \ - bool member; ///< desc -#include "EventSelectionFlagsMapping.def" // NOLINT(build/include) + bool member; ///< desc +#include "EventSelectionFlagsMapping.def" // NOLINT(build/include) #undef EVSEL_FLAG // ===== Run2-specific selections (not in EventSelectionFlags) ===== From f5041cfaba26a04f17a6d31f580f6d2fceba01c9 Mon Sep 17 00:00:00 2001 From: ALICE Action Bot Date: Tue, 30 Dec 2025 03:16:58 +0000 Subject: [PATCH 8/8] MegaLinter fixes --- Tutorials/PWGLF/Utils/README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Tutorials/PWGLF/Utils/README.md b/Tutorials/PWGLF/Utils/README.md index 5e167f2156b..461ccfdd222 100644 --- a/Tutorials/PWGLF/Utils/README.md +++ b/Tutorials/PWGLF/Utils/README.md @@ -10,20 +10,20 @@ This directory contains tutorials for common PWGLF utilities and helper classes. This tutorial demonstrates how to use the `collisionCutsGroup` pattern for automatic configurable registration of collision event selection parameters. -### Key Features: +### Key Features - **Automatic Configurable Registration**: All collision selection parameters are automatically registered by the DPL framework with a single line of code - **Reduced Boilerplate**: Traditional approach requires ~30 lines of manual configurable declarations, the new pattern reduces this to ~5 lines - **Comprehensive Event Selection**: Includes z-vertex cuts, centrality cuts, time frame cuts, occupancy cuts, and various Run 3 event selection flags -### What You'll Learn: +### What You'll Learn 1. How to declare a `collisionCutsGroup` configurable 2. How to apply settings from the group to a `CollisonCuts` object 3. How to use the collision cuts checker to filter events 4. How to fill QA histograms for selected events -### Customizing Cuts: +### Customizing Cuts The collision cuts can be customized via JSON configuration file: @@ -48,7 +48,7 @@ For a complete list of available parameters, run: o2-analysis-collision-cuts-tutorial --help full ``` -### Related Documentation: +### Related Documentation - Main collision cuts implementation: `PWGLF/Utils/collisionCuts.h` - Configurable group implementation: `PWGLF/Utils/collisionCutsGroup.h`