From 8e53928780ec88a8d79afe4ce57870693da5dad9 Mon Sep 17 00:00:00 2001 From: David Dobrigkeit Chinellato Date: Sat, 1 Nov 2025 09:12:49 -0300 Subject: [PATCH] [Common] ZDC task for exploring light ions --- Common/DataModel/CMakeLists.txt | 1 + Common/DataModel/ZDCLightIons.h | 97 +++++++ Common/TableProducer/CMakeLists.txt | 5 + Common/TableProducer/zdcTaskLightIons.cxx | 337 ++++++++++++++++++++++ 4 files changed, 440 insertions(+) create mode 100644 Common/DataModel/ZDCLightIons.h create mode 100644 Common/TableProducer/zdcTaskLightIons.cxx diff --git a/Common/DataModel/CMakeLists.txt b/Common/DataModel/CMakeLists.txt index f3a9d1d2259..dc9001e61ff 100644 --- a/Common/DataModel/CMakeLists.txt +++ b/Common/DataModel/CMakeLists.txt @@ -27,5 +27,6 @@ o2physics_add_header_only_library(DataModel MatchMFTFT0.h MftmchMatchingML.h ZDCExtra.h + ZDCLightIons.h EseTable.h FwdTrackReAlignTables.h) diff --git a/Common/DataModel/ZDCLightIons.h b/Common/DataModel/ZDCLightIons.h new file mode 100644 index 00000000000..b2faa13ba9d --- /dev/null +++ b/Common/DataModel/ZDCLightIons.h @@ -0,0 +1,97 @@ +// 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 ZDCLightIons.h +/// \brief ZDC data model for O-O Ne-Ne and p-O collisions +/// \author Chiara Oppedisano + +#ifndef PWGMM_DATAMODEL_ZDCLIGHTIONS_H_ +#define PWGMM_DATAMODEL_ZDCLIGHTIONS_H_ + +#include "Common/DataModel/Centrality.h" + +#include "Framework/ASoAHelpers.h" +#include "Framework/AnalysisDataModel.h" + +namespace o2::aod +{ +namespace zdclightions +{ +DECLARE_SOA_COLUMN(ZnaTdc, znaTdc, float); //! TDC ZNA +DECLARE_SOA_COLUMN(ZnaAmpl, znaAmpl, float); //! amplitude ZNA +DECLARE_SOA_COLUMN(ZnaPmc, znaPmc, float); //! ADC PmC ZNA +DECLARE_SOA_COLUMN(ZnaPm1, znaPm1, float); //! ADC PmQ1 ZNA +DECLARE_SOA_COLUMN(ZnaPm2, znaPm2, float); //! ADC PmQ2 ZNA +DECLARE_SOA_COLUMN(ZnaPm3, znaPm3, float); //! ADC PmQ3 ZNA +DECLARE_SOA_COLUMN(ZnaPm4, znaPm4, float); //! ADC PmQ4 ZNA +DECLARE_SOA_COLUMN(ZncTdc, zncTdc, float); //! TDC ZNC +DECLARE_SOA_COLUMN(ZncAmpl, zncAmpl, float); //! amplitude ZNC +DECLARE_SOA_COLUMN(ZncPmc, zncPmc, float); //! ADC PmC ZNC +DECLARE_SOA_COLUMN(ZncPm1, zncPm1, float); //! ADC PmQ1 ZNC +DECLARE_SOA_COLUMN(ZncPm2, zncPm2, float); //! ADC PmQ2 ZNC +DECLARE_SOA_COLUMN(ZncPm3, zncPm3, float); //! ADC PmQ3 ZNC +DECLARE_SOA_COLUMN(ZncPm4, zncPm4, float); //! ADC PmQ4 ZNC +DECLARE_SOA_COLUMN(ZpaTdc, zpaTdc, float); //! TDC ZPA +DECLARE_SOA_COLUMN(ZpaAmpl, zpaAmpl, float); //! amplitude ZPA +DECLARE_SOA_COLUMN(ZpaPmc, zpaPmc, float); //! ADC PmC ZPA +DECLARE_SOA_COLUMN(ZpcTdc, zpcTdc, float); //! TDC ZPC +DECLARE_SOA_COLUMN(ZpcAmpl, zpcAmpl, float); //! amplitude ZPA +DECLARE_SOA_COLUMN(ZpcPmc, zpcPmc, float); //! ADC PmC ZPA +DECLARE_SOA_COLUMN(Zem1Tdc, zem1Tdc, float); //! TDC ZEM1 +DECLARE_SOA_COLUMN(Zem1Ampl, zem1Ampl, float); //! amplitude ZEM1 +DECLARE_SOA_COLUMN(Zem2Tdc, zem2Tdc, float); //! TDC ZEM2 +DECLARE_SOA_COLUMN(Zem2Ampl, zem2Ampl, float); //! amplitude ZEM2 +DECLARE_SOA_COLUMN(MultFt0a, multFt0a, float); //! mult. FIT-A +DECLARE_SOA_COLUMN(MultFt0c, multFt0c, float); //! mult. FIT-C +DECLARE_SOA_COLUMN(MultV0a, multV0a, float); //! mult. V0-A +DECLARE_SOA_COLUMN(VertexZ, vertexZ, float); //! Z vertex +DECLARE_SOA_COLUMN(CentralityFt0c, centralityFt0c, float); //! Centrality +DECLARE_SOA_COLUMN(CentralityFt0a, centralityFt0a, float); //! Centrality +DECLARE_SOA_COLUMN(CentralityFt0m, centralityFt0m, float); //! Centrality +DECLARE_SOA_COLUMN(Timestamp, timestamp, uint64_t); //! Timestamp +DECLARE_SOA_COLUMN(SelectionBits, selectionBits, uint8_t); //! Selection Flags +} // namespace zdclightions + +DECLARE_SOA_TABLE(ZDCLightIons, "AOD", "ZDCTABLELIGHTIONS", + zdclightions::ZnaTdc, + zdclightions::ZnaAmpl, + zdclightions::ZnaPmc, + zdclightions::ZnaPm1, + zdclightions::ZnaPm2, + zdclightions::ZnaPm3, + zdclightions::ZnaPm4, + zdclightions::ZncTdc, + zdclightions::ZncAmpl, + zdclightions::ZncPmc, + zdclightions::ZncPm1, + zdclightions::ZncPm2, + zdclightions::ZncPm3, + zdclightions::ZncPm4, + zdclightions::ZpaTdc, + zdclightions::ZpaAmpl, + zdclightions::ZpcTdc, + zdclightions::ZpcAmpl, + zdclightions::Zem1Tdc, + zdclightions::Zem1Ampl, + zdclightions::Zem2Tdc, + zdclightions::Zem2Ampl, + zdclightions::MultFt0a, + zdclightions::MultFt0c, + zdclightions::MultV0a, + zdclightions::VertexZ, + zdclightions::CentralityFt0c, + zdclightions::CentralityFt0a, + zdclightions::CentralityFt0m, + zdclightions::Timestamp, + zdclightions::SelectionBits); +} // namespace o2::aod + +#endif // COMMON_DATAMODEL_ZDCLIGHTIONS_H_ diff --git a/Common/TableProducer/CMakeLists.txt b/Common/TableProducer/CMakeLists.txt index 5f0d91132a0..2282a06b5e7 100644 --- a/Common/TableProducer/CMakeLists.txt +++ b/Common/TableProducer/CMakeLists.txt @@ -182,3 +182,8 @@ o2physics_add_dpl_workflow(selectionstudytable SOURCES selectionStudyTable.cxx PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore COMPONENT_NAME Analysis) + +o2physics_add_dpl_workflow(zdc-task-light-ions + SOURCES zdcTaskLightIons.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore + COMPONENT_NAME Analysis) diff --git a/Common/TableProducer/zdcTaskLightIons.cxx b/Common/TableProducer/zdcTaskLightIons.cxx new file mode 100644 index 00000000000..1cd6cccf3c2 --- /dev/null +++ b/Common/TableProducer/zdcTaskLightIons.cxx @@ -0,0 +1,337 @@ +// 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 zdcTaskLightIons.cxx +/// \brief Task for ZDC in light ions +/// \author chiara.oppedisano@cern.ch + +#include "Common/CCDB/EventSelectionParams.h" +#include "Common/CCDB/TriggerAliases.h" +#include "Common/Core/TrackSelection.h" +#include "Common/Core/trackUtilities.h" +#include "Common/DataModel/Centrality.h" +#include "Common/DataModel/EventSelection.h" +#include "Common/DataModel/Multiplicity.h" +#include "Common/DataModel/ZDCLightIons.h" + +#include +#include +#include +#include + +#include + +using namespace o2; +using namespace o2::aod; +using namespace o2::framework; +using namespace o2::framework::expressions; +using namespace o2::aod::evsel; + +using BCsRun3 = soa::Join; +using ColEvSels = soa::Join; + +struct ZdcTaskLightIons { + + Produces zdcTableLI; + + // Configurable parameters + Configurable nBinsTiming{"nBinsTiming", 200, "n bins for debunching histo"}; + Configurable tdcCut{"tdcCut", true, "Flag for TDC cut"}; + Configurable tdcZNmincut{"tdcZNmincut", -2.5, "Min. ZN TDC cut value"}; + Configurable tdcZNmaxcut{"tdcZNmaxcut", 2.5, "Max. ZN TDC cut value"}; + // + // Event selections + Configurable cfgEvSelVtxZ{"cfgEvSelVtxZ", 10, "Event selection: zVtx"}; + Configurable cfgEvSelSel8{"cfgEvSelSel8", true, "Event selection: sel8"}; + Configurable cfgEvSelsDoOccupancySel{"cfgEvSelsDoOccupancySel", true, "Event selection: do occupancy selection"}; + Configurable cfgEvSelsMaxOccupancy{"cfgEvSelsMaxOccupancy", 10000, "Event selection: set max occupancy"}; + Configurable cfgEvSelsNoSameBunchPileupCut{"cfgEvSelsNoSameBunchPileupCut", true, "Event selection: no same bunch pileup cut"}; + Configurable cfgEvSelsIsGoodZvtxFT0vsPV{"cfgEvSelsIsGoodZvtxFT0vsPV", true, "Event selection: is good ZVTX FT0 vs PV"}; + Configurable cfgEvSelsNoCollInTimeRangeStandard{"cfgEvSelsNoCollInTimeRangeStandard", true, "Event selection: no collision in time range standard"}; + Configurable cfgEvSelsIsVertexITSTPC{"cfgEvSelsIsVertexITSTPC", true, "Event selection: is vertex ITSTPC"}; + Configurable cfgEvSelsIsGoodITSLayersAll{"cfgEvSelsIsGoodITSLayersAll", true, "Event selection: is good ITS layers all"}; + // + HistogramRegistry registry{"Histos", {}, OutputObjHandlingPolicy::AnalysisObject}; + + enum SelectionCriteria { + evSel_zvtx, + evSel_sel8, + evSel_occupancy, + evSel_kNoSameBunchPileup, + evSel_kIsGoodZvtxFT0vsPV, + evSel_kNoCollInTimeRangeStandard, + evSel_kNoITSROFrameBorder, + evSel_kIsGoodITSLayersAll, + evSel_allEvents, + nEventSelections + }; + + void init(InitContext const&) + { + registry.add("zdcDebunchHist", "ZN sum vs. diff; ZNA-ZNC (ns); ZNA+ZNC (ns)", {HistType::kTH2D, {{nBinsTiming, -20., 20.}, {nBinsTiming, -20., 20.}}}); + + if (doprocessALICEcoll) { + registry.add("hEventCount", "Number of Event; Cut; #Events Passed Cut", {HistType::kTH1D, {{nEventSelections, 0, nEventSelections}}}); + registry.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(evSel_allEvents + 1, "All events"); + registry.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(evSel_zvtx + 1, "vtxZ"); + registry.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(evSel_sel8 + 1, "Sel8"); + registry.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(evSel_occupancy + 1, "kOccupancy"); + registry.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(evSel_kNoSameBunchPileup + 1, "kNoSameBunchPileup"); + registry.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(evSel_kIsGoodZvtxFT0vsPV + 1, "kIsGoodZvtxFT0vsPV"); + registry.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(evSel_kNoCollInTimeRangeStandard + 1, "kNoCollInTimeRangeStandard"); + registry.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(evSel_kNoITSROFrameBorder + 1, "kNoITSROFrameBorder"); + registry.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(evSel_kIsGoodITSLayersAll + 1, "kkIsGoodITSLayersAll"); + } + } + + template + uint8_t eventSelected(TCollision collision) + { + uint8_t selectionBits = 0; + bool selected; + + registry.fill(HIST("hEventCount"), evSel_allEvents); + + selected = std::fabs(collision.posZ()) < cfgEvSelVtxZ; + if (selected) { + selectionBits |= (uint8_t)(0x1u << evSel_zvtx); + registry.fill(HIST("hEventCount"), evSel_zvtx); + } + + selected = collision.sel8(); + if (selected) { + selectionBits |= (uint8_t)(0x1u << evSel_sel8); + registry.fill(HIST("hEventCount"), evSel_sel8); + } + + auto occupancy = collision.trackOccupancyInTimeRange(); + selected = occupancy <= cfgEvSelsMaxOccupancy; + if (selected) { + selectionBits |= (uint8_t)(0x1u << evSel_occupancy); + registry.fill(HIST("hEventCount"), evSel_occupancy); + } + + selected = collision.selection_bit(o2::aod::evsel::kNoSameBunchPileup); + if (selected) { + selectionBits |= (uint8_t)(0x1u << evSel_kNoSameBunchPileup); + registry.fill(HIST("hEventCount"), evSel_kNoSameBunchPileup); + } + + selected = collision.selection_bit(o2::aod::evsel::kIsGoodZvtxFT0vsPV); + if (selected) { + selectionBits |= (uint8_t)(0x1u << evSel_kIsGoodZvtxFT0vsPV); + registry.fill(HIST("hEventCount"), evSel_kIsGoodZvtxFT0vsPV); + } + + selected = collision.selection_bit(o2::aod::evsel::kNoCollInTimeRangeStandard); + if (selected) { + selectionBits |= (uint8_t)(0x1u << evSel_kNoCollInTimeRangeStandard); + registry.fill(HIST("hEventCount"), evSel_kNoCollInTimeRangeStandard); + } + + selected = collision.selection_bit(o2::aod::evsel::kNoITSROFrameBorder); + if (selected) { + selectionBits |= (uint8_t)(0x1u << evSel_kNoITSROFrameBorder); + registry.fill(HIST("hEventCount"), evSel_kNoITSROFrameBorder); + } + + selected = collision.selection_bit(o2::aod::evsel::kIsGoodITSLayersAll); + if (selected) { + selectionBits |= (uint8_t)(0x1u << evSel_kIsGoodITSLayersAll); + registry.fill(HIST("hEventCount"), evSel_kIsGoodITSLayersAll); + } + + return selectionBits; + } + + void processZDCBC(BCsRun3 const& bcs, aod::Zdcs const& /*zdcs*/) + { + for (const auto& bc : bcs) { + if (bc.has_zdc()) { + + auto tdcZNA = bc.zdc().timeZNA(); + auto tdcZNC = bc.zdc().timeZNC(); + auto tdcZPA = bc.zdc().timeZPA(); + auto tdcZPC = bc.zdc().timeZPC(); + auto tdcZEM1 = bc.zdc().timeZEM1(); + auto tdcZEM2 = bc.zdc().timeZEM2(); + // + double zna = bc.zdc().amplitudeZNA(); + double znc = bc.zdc().amplitudeZNC(); + double zpa = bc.zdc().amplitudeZPA(); + double zpc = bc.zdc().amplitudeZPC(); + double zem1 = bc.zdc().amplitudeZEM1(); + double zem2 = bc.zdc().amplitudeZEM2(); + // + double pmcZNA = bc.zdc().energyCommonZNA(); + double pmcZNC = bc.zdc().energyCommonZNC(); + double pmqZNC[4] = { + 0, + 0, + 0, + 0, + }; + double pmqZNA[4] = { + 0, + 0, + 0, + 0, + }; + const int noofZNsectors = 4; + for (int itow = 0; itow < noofZNsectors; itow++) { + pmqZNA[itow] = (bc.zdc().energySectorZNA())[itow]; + pmqZNC[itow] = (bc.zdc().energySectorZNC())[itow]; + } + + bool isZNChit = false, isZNAhit = false; + if (tdcCut) { // a narrow TDC window is set + if ((tdcZNC >= tdcZNmincut) && (tdcZNC <= tdcZNmaxcut)) { + isZNChit = true; + } + if ((tdcZNA >= tdcZNmincut) && (tdcZNA <= tdcZNmaxcut)) { + isZNAhit = true; + } + } else { // if no window on TDC is set + if (pmcZNC > 0.) { + isZNChit = true; + } + if (pmcZNA > 0.) { + isZNAhit = true; + } + } + if (isZNChit && isZNAhit) { + registry.get(HIST("debunchHist"))->Fill(zna - znc, zna + znc); + } + + zdcTableLI(tdcZNA, zna, pmcZNA, pmqZNA[0], pmqZNA[1], pmqZNA[2], pmqZNA[3], + tdcZNC, znc, pmcZNC, pmqZNC[0], pmqZNC[1], pmqZNC[2], pmqZNC[3], + tdcZPA, zpa, tdcZPC, zpc, tdcZEM1, zem1, tdcZEM2, zem2, + -1, -1, -1, + -1., + -1, -1, -1, + bc.timestamp(), + -1); + } + } + } + /// name, description, function pointer, default value + /// note that it has to be declared after the function, so that the pointer is known + PROCESS_SWITCH(ZdcTaskLightIons, processZDCBC, "Processing ZDC 4 auto-triggered events", true); + + void processALICEcoll(ColEvSels const& cols, BCsRun3 const& /*bcs*/, aod::Zdcs const& /*zdcs*/) + { + // collision-based event selection + for (auto const& collision : cols) { + + const auto& foundBC = collision.foundBC_as(); + uint8_t evSelection = eventSelected(collision); + auto zv = collision.posZ(); + auto centralityFT0C = collision.centFT0C(); + auto centralityFT0A = collision.centFT0A(); + auto centralityFT0M = collision.centFT0M(); + + // FT0 + float multFT0A = 0.; + float multFT0C = 0.; + if (foundBC.has_ft0()) { + for (auto const& amplitude : foundBC.ft0().amplitudeA()) { + multFT0A += amplitude; + } + for (auto const& amplitude : foundBC.ft0().amplitudeC()) { + multFT0C += amplitude; + } + } + // FV0 + float multV0A = 0; + if (foundBC.has_fv0a()) { + for (auto const& amplitude : foundBC.fv0a().amplitude()) { + multV0A += amplitude; + } + } + + if (foundBC.has_zdc()) { + const auto& zdc = foundBC.zdc(); + + auto tdcZNA = zdc.timeZNA(); + auto tdcZNC = zdc.timeZNC(); + auto tdcZPA = zdc.timeZPA(); + auto tdcZPC = zdc.timeZPC(); + auto tdcZEM1 = zdc.timeZEM1(); + auto tdcZEM2 = zdc.timeZEM2(); + // + double zna = zdc.amplitudeZNA(); + double znc = zdc.amplitudeZNC(); + double zpa = zdc.amplitudeZPA(); + double zpc = zdc.amplitudeZPC(); + double zem1 = zdc.amplitudeZEM1(); + double zem2 = zdc.amplitudeZEM2(); + // + double pmcZNA = zdc.energyCommonZNA(); + double pmcZNC = zdc.energyCommonZNC(); + double pmqZNC[4] = { + 0, + 0, + 0, + 0, + }; + double pmqZNA[4] = { + 0, + 0, + 0, + 0, + }; + const int noofZNsectors = 4; + for (int itow = 0; itow < noofZNsectors; itow++) { + pmqZNA[itow] = (zdc.energySectorZNA())[itow]; + pmqZNC[itow] = (zdc.energySectorZNC())[itow]; + } + + bool isZNChit = false, isZNAhit = false; + if (tdcCut) { // a narrow TDC window is set + if ((tdcZNC >= tdcZNmincut) && (tdcZNC <= tdcZNmaxcut)) { + isZNChit = true; + } + if ((tdcZNA >= tdcZNmincut) && (tdcZNA <= tdcZNmaxcut)) { + isZNAhit = true; + } + } else { // if no window on TDC is set + if (pmcZNC > 0.) { + isZNChit = true; + } + if (pmcZNA > 0.) { + isZNAhit = true; + } + } + if (isZNChit && isZNAhit) { + registry.get(HIST("debunchHist"))->Fill(zna - znc, zna + znc); + } + + zdcTableLI(tdcZNA, zna, pmcZNA, pmqZNA[0], pmqZNA[1], pmqZNA[2], pmqZNA[3], + tdcZNC, znc, pmcZNC, pmqZNC[0], pmqZNC[1], pmqZNC[2], pmqZNC[3], + tdcZPA, zpa, tdcZPC, zpc, tdcZEM1, zem1, tdcZEM2, zem2, + multFT0A, multFT0C, multV0A, + zv, + centralityFT0C, centralityFT0A, centralityFT0M, + foundBC.timestamp(), + evSelection); + } + } + } + /// name, description, function pointer, default value + /// note that it has to be declared after the function, so that the pointer is known + PROCESS_SWITCH(ZdcTaskLightIons, processALICEcoll, "Processing ZDC for ALICE collisions", true); +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) // o2-linter: disable=name/file-cpp +{ + return WorkflowSpec{ + adaptAnalysisTask(cfgc)}; +}