diff --git a/PWGUD/Core/CMakeLists.txt b/PWGUD/Core/CMakeLists.txt index 7686edd8eea..02767ee2e78 100644 --- a/PWGUD/Core/CMakeLists.txt +++ b/PWGUD/Core/CMakeLists.txt @@ -1,66 +1,74 @@ -# 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_library(UDGoodRunSelector - SOURCES UDGoodRunSelector.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore ROOT::EG RapidJSON::RapidJSON) + SOURCES UDGoodRunSelector.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore ROOT::EG RapidJSON::RapidJSON) -o2physics_target_root_dictionary(UDGoodRunSelector - HEADERS UDGoodRunSelector.h - LINKDEF UDGoodRunSelectorLinkDef.h) + o2physics_target_root_dictionary(UDGoodRunSelector + HEADERS UDGoodRunSelector.h + LINKDEF UDGoodRunSelectorLinkDef.h) -o2physics_add_library(UDFSParser - SOURCES UDFSParser.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore) + o2physics_add_library(UDFSParser + SOURCES UDFSParser.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore) -o2physics_target_root_dictionary(UDFSParser - HEADERS UDFSParser.h - LINKDEF UDFSParserLinkDef.h) + o2physics_target_root_dictionary(UDFSParser + HEADERS UDFSParser.h + LINKDEF UDFSParserLinkDef.h) -o2physics_add_library(DGCutparHolder - SOURCES DGCutparHolder.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore) + o2physics_add_library(DGCutparHolder + SOURCES DGCutparHolder.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore) -o2physics_target_root_dictionary(DGCutparHolder - HEADERS DGCutparHolder.h - LINKDEF DGCutparHolderLinkDef.h) + o2physics_target_root_dictionary(DGCutparHolder + HEADERS DGCutparHolder.h + LINKDEF DGCutparHolderLinkDef.h) -o2physics_add_library(SGCutParHolder - SOURCES SGCutParHolder.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore) + o2physics_add_library(SGCutParHolder + SOURCES SGCutParHolder.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore) -o2physics_target_root_dictionary(SGCutParHolder - HEADERS SGCutParHolder.h - LINKDEF SGCutParHolderLinkDef.h) + o2physics_target_root_dictionary(SGCutParHolder + HEADERS SGCutParHolder.h + LINKDEF SGCutParHolderLinkDef.h) -o2physics_add_library(DGPIDSelector - SOURCES DGPIDSelector.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore ROOT::EG) + o2physics_add_library(DGPIDSelector + SOURCES DGPIDSelector.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore ROOT::EG) -o2physics_target_root_dictionary(DGPIDSelector - HEADERS DGPIDSelector.h - LINKDEF DGPIDSelectorLinkDef.h) + o2physics_target_root_dictionary(DGPIDSelector + HEADERS DGPIDSelector.h + LINKDEF DGPIDSelectorLinkDef.h) -o2physics_add_library(UPCCutparHolder - SOURCES UPCCutparHolder.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore) + o2physics_add_library(UPCCutparHolder + SOURCES UPCCutparHolder.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore) -o2physics_target_root_dictionary(UPCCutparHolder - HEADERS UPCCutparHolder.h - LINKDEF UPCCutparHolderLinkDef.h) + o2physics_target_root_dictionary(UPCCutparHolder + HEADERS UPCCutparHolder.h + LINKDEF UPCCutparHolderLinkDef.h) -o2physics_add_library(decayTree - SOURCES decayTree.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore ROOT::EG RapidJSON::RapidJSON) + o2physics_add_library(decayTree + SOURCES decayTree.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore ROOT::EG RapidJSON::RapidJSON) -o2physics_target_root_dictionary(decayTree - HEADERS decayTree.h - LINKDEF decayTreeLinkDef.h) + o2physics_target_root_dictionary(decayTree + HEADERS decayTree.h + LINKDEF decayTreeLinkDef.h) + + o2physics_add_library(FITCutParHolder + SOURCES FITCutParHolder.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore) + + o2physics_target_root_dictionary(FITCutParHolder + HEADERS FITCutParHolder.h + LINKDEF FITCutParHolderLinkDef.h) diff --git a/PWGUD/Core/FITCutParHolder.cxx b/PWGUD/Core/FITCutParHolder.cxx new file mode 100644 index 00000000000..d57e2c8e12f --- /dev/null +++ b/PWGUD/Core/FITCutParHolder.cxx @@ -0,0 +1,55 @@ +// 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. +// +// \FIT bit thresholds +// \author Sandor Lokos, sandor.lokos@cern.ch +// \since March 2026 + +#include "FITCutParHolder.h" + +// setter +void FITCutParHolder::SetSaveFITbitsets(bool saveFITbitsets) +{ + mSaveFITbitsets = saveFITbitsets; +} +void FITCutParHolder::SetThr1FV0A(float thr1_FV0A) +{ + mThr1FV0A = thr1_FV0A; +} +void FITCutParHolder::SetThr1FT0A(float thr1_FT0A) +{ + mThr1FT0A = thr1_FT0A; +} +void FITCutParHolder::SetThr1FT0C(float thr1_FT0C) +{ + mThr1FT0C = thr1_FT0C; +} +void FITCutParHolder::SetThr2FV0A(float thr2_FV0A) +{ + mThr2FV0A = thr2_FV0A; +} +void FITCutParHolder::SetThr2FT0A(float thr2_FT0A) +{ + mThr2FT0A = thr2_FT0A; +} +void FITCutParHolder::SetThr2FT0C(float thr2_FT0C) +{ + mThr2FT0C = thr2_FT0C; +} + +// getter +bool FITCutParHolder::saveFITbitsets() const { return mSaveFITbitsets; } +float FITCutParHolder::thr1_FV0A() const { return mThr1FV0A; } +float FITCutParHolder::thr1_FT0A() const { return mThr1FT0A; } +float FITCutParHolder::thr1_FT0C() const { return mThr1FT0C; } +float FITCutParHolder::thr2_FV0A() const { return mThr2FV0A; } +float FITCutParHolder::thr2_FT0A() const { return mThr2FT0A; } +float FITCutParHolder::thr2_FT0C() const { return mThr2FT0C; } diff --git a/PWGUD/Core/FITCutParHolder.h b/PWGUD/Core/FITCutParHolder.h new file mode 100644 index 00000000000..e03c4161c27 --- /dev/null +++ b/PWGUD/Core/FITCutParHolder.h @@ -0,0 +1,75 @@ +// 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. +// +// \FIT bit thresholds +// \author Sandor Lokos, sandor.lokos@cern.ch +// \since March 2026 + +#ifndef PWGUD_CORE_FITCUTPARHOLDER_H_ +#define PWGUD_CORE_FITCUTPARHOLDER_H_ + +#include + +// object to hold customizable FIT bit thresholds +class FITCutParHolder +{ + public: + // constructor + FITCutParHolder(bool saveFITbitsets = true, + float thr1_FV0A = 8., + float thr1_FT0A = 8., + float thr1_FT0C = 8., + float thr2_FV0A = 20., + float thr2_FT0A = 20., + float thr2_FT0C = 20.) + : mSaveFITbitsets{saveFITbitsets}, + mThr1FV0A{thr1_FV0A}, + mThr1FT0A{thr1_FT0A}, + mThr1FT0C{thr1_FT0C}, + mThr2FV0A{thr2_FV0A}, + mThr2FT0A{thr2_FT0A}, + mThr2FT0C{thr2_FT0C} + { + } + + // setters + void SetSaveFITbitsets(bool); + void SetThr1FV0A(float); + void SetThr1FT0A(float); + void SetThr1FT0C(float); + void SetThr2FV0A(float); + void SetThr2FT0A(float); + void SetThr2FT0C(float); + + // getters + bool saveFITbitsets() const; + float thr1_FV0A() const; + float thr1_FT0A() const; + float thr1_FT0C() const; + float thr2_FV0A() const; + float thr2_FT0A() const; + float thr2_FT0C() const; + + private: + bool mSaveFITbitsets; + + float mThr1FV0A; + float mThr1FT0A; + float mThr1FT0C; + + float mThr2FV0A; + float mThr2FT0A; + float mThr2FT0C; + + ClassDefNV(FITCutParHolder, 1); +}; + +#endif // PWGUD_CORE_FITCUTPARHOLDER_H_ diff --git a/PWGUD/Core/FITCutParHolderLinkDef.h b/PWGUD/Core/FITCutParHolderLinkDef.h new file mode 100644 index 00000000000..3194a6754b2 --- /dev/null +++ b/PWGUD/Core/FITCutParHolderLinkDef.h @@ -0,0 +1,24 @@ +// 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. +// +// \FIT bit thresholds +// \author Sandor Lokos, sandor.lokos@cern.ch +// \since March 2026 + +#ifndef PWGUD_CORE_FITCUTPARHOLDERLINKDEF_H_ +#define PWGUD_CORE_FITCUTPARHOLDERLINKDEF_H_ + +#pragma link off all globals; +#pragma link off all classes; +#pragma link off all functions; +#pragma link C++ class FITCutParHolder + ; + +#endif // PWGUD_CORE_FITCUTPARHOLDERLINKDEF_H_ diff --git a/PWGUD/Core/SGCutParHolderLinkDef.h b/PWGUD/Core/SGCutParHolderLinkDef.h index f9216fa0c37..5dcadadc69e 100644 --- a/PWGUD/Core/SGCutParHolderLinkDef.h +++ b/PWGUD/Core/SGCutParHolderLinkDef.h @@ -8,6 +8,7 @@ // 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. + #ifndef PWGUD_CORE_SGCUTPARHOLDERLINKDEF_H_ #define PWGUD_CORE_SGCUTPARHOLDERLINKDEF_H_ diff --git a/PWGUD/Core/UDHelpers.h b/PWGUD/Core/UDHelpers.h index 1248164dd0f..d52ba7e2f5c 100644 --- a/PWGUD/Core/UDHelpers.h +++ b/PWGUD/Core/UDHelpers.h @@ -19,6 +19,7 @@ #include "PWGUD/Core/DGCutparHolder.h" #include "PWGUD/Core/UPCHelpers.h" +#include "Common/Core/RecoDecay.h" #include "Common/DataModel/EventSelection.h" #include "Common/DataModel/TrackSelectionTables.h" @@ -29,6 +30,7 @@ #include "TLorentzVector.h" +#include #include #include @@ -533,6 +535,184 @@ bool FITveto(T const& bc, DGCutparHolder const& diffCuts) return false; } +inline void setBit(uint64_t w[4], int bit, bool val) +{ + if (!val) { + return; + } + const int word = bit >> 6; + const int offs = bit & 63; + w[word] |= (static_cast(1) << offs); +} + +template +inline void buildFT0FV0Words(TFT0 const& ft0, TFV0A const& fv0a, + uint64_t thr1[4], uint64_t thr2[4], + float thr1_FT0A = 25., float thr1_FT0C = 50., float thr1_FV0A = 50., + float thr2_FT0A = 50., float thr2_FT0C = 100., float thr2_FV0A = 100.) +{ + thr1[0] = thr1[1] = thr1[2] = thr1[3] = 0ull; + thr2[0] = thr2[1] = thr2[2] = thr2[3] = 0ull; + + constexpr int kFT0AOffset = 0; + constexpr int kFT0COffset = 96; + constexpr int kFV0Offset = 208; + + auto ampsA = ft0.amplitudeA(); + auto chanA = ft0.channelA(); + const int nA = std::min(ampsA.size(), chanA.size()); + + for (int i = 0; i < nA; ++i) { + const auto a = ampsA[i]; + const int c = chanA[i]; + + if (c < 0 || c >= 96) { + continue; + } + + setBit(thr1, kFT0AOffset + c, a >= thr1_FT0A); + setBit(thr2, kFT0AOffset + c, a >= thr2_FT0A); + } + + auto ampsC = ft0.amplitudeC(); + auto chanC = ft0.channelC(); + const int nC = std::min(ampsC.size(), chanC.size()); + + for (int i = 0; i < nC; ++i) { + const auto a = ampsC[i]; + const int c = chanC[i]; // physical FT0C channel id + + if (c < 0 || c >= 112) { + continue; + } + + setBit(thr1, kFT0COffset + c, a >= thr1_FT0C); + setBit(thr2, kFT0COffset + c, a >= thr2_FT0C); + } + + auto ampsV = fv0a.amplitude(); + auto chanV = fv0a.channel(); + const int nV = std::min(ampsV.size(), chanV.size()); + + for (int i = 0; i < nV; ++i) { + const auto a = ampsV[i]; + const int c = chanV[i]; + + if (c < 0 || c >= 48) { + continue; + } + + setBit(thr1, kFV0Offset + c, a >= thr1_FV0A); + setBit(thr2, kFV0Offset + c, a >= thr2_FV0A); + } +} + +// ----------------------------------------------------------------------------- +// return eta and phi of a given FIT channel based on the bitset +// Bit layout contract: +constexpr int kFT0Bits = 208; // FT0 total channels +constexpr int kFV0Bits = 48; // FV0A channels +constexpr int kTotalBits = 256; // 4*64 + +// FT0 side split +constexpr int kFT0AChannels = 96; // FT0A channels are [0..95] +constexpr int kFT0CChannels = 112; // FT0C channels are [96..207] +static_assert(kFT0AChannels + kFT0CChannels == kFT0Bits); + +using Bits256 = std::array; + +inline Bits256 makeBits256(uint64_t w0, uint64_t w1, uint64_t w2, uint64_t w3) +{ + return {w0, w1, w2, w3}; +} + +inline bool testBit(Bits256 const& w, int bit) +{ + if (bit < 0 || bit >= kTotalBits) { + return false; + } + return (w[bit >> 6] >> (bit & 63)) & 1ULL; +} + +struct FitBitRef { + enum class Det : uint8_t { FT0, + FV0, + Unknown }; + Det det = Det::Unknown; + int ch = -1; // FT0: 0..207, FV0: 0..47 + bool isC = false; // only meaningful for FT0 +}; + +inline FitBitRef decodeFitBit(int bit) +{ + FitBitRef out; + if (bit >= 0 && bit < kFT0Bits) { + out.det = FitBitRef::Det::FT0; + out.ch = bit; // FT0 channel id + out.isC = (bit >= kFT0AChannels); // C side if in upper range + return out; + } + if (bit >= kFT0Bits && bit < kTotalBits) { + out.det = FitBitRef::Det::FV0; + out.ch = bit - kFT0Bits; // FV0A channel id 0..47 + return out; + } + return out; +} + +template +inline double getPhiFT0_fromChannel(FT0DetT& ft0Det, int ft0Ch, OffsetsT const& offsetFT0, int i) +{ + ft0Det.calculateChannelCenter(); + auto chPos = ft0Det.getChannelCenter(ft0Ch); + + const double x = chPos.X() + offsetFT0[i].getX(); + const double y = chPos.Y() + offsetFT0[i].getY(); + + return RecoDecay::phi(x, y); +} + +template +inline double getEtaFT0_fromChannel(FT0DetT& ft0Det, int ft0Ch, OffsetsT const& offsetFT0, int i) +{ + ft0Det.calculateChannelCenter(); + auto chPos = ft0Det.getChannelCenter(ft0Ch); + + double x = chPos.X() + offsetFT0[i].getX(); + double y = chPos.Y() + offsetFT0[i].getY(); + double z = chPos.Z() + offsetFT0[i].getZ(); + + // If this channel belongs to FT0C, flip z (matches your original intent) + const bool isC = (ft0Ch >= kFT0AChannels); + if (isC) { + z = -z; + } + + const double r = std::sqrt(x * x + y * y); + const double theta = std::atan2(r, z); + return -std::log(std::tan(0.5 * theta)); +} + +template +inline bool getPhiEtaFromFitBit(FT0DetT& ft0Det, + int bit, + OffsetsT const& offsetFT0, + int iRunOffset, + double& phi, + double& eta) +{ + auto ref = decodeFitBit(bit); + if (ref.det != FitBitRef::Det::FT0) { + return false; + } + + // FT0A: 0..95, FT0C: 96..207 + const int ft0Ch = bit; + phi = getPhiFT0_fromChannel(ft0Det, ft0Ch, offsetFT0, iRunOffset); + eta = getEtaFT0_fromChannel(ft0Det, ft0Ch, offsetFT0, iRunOffset); + return true; +} + // ----------------------------------------------------------------------------- template diff --git a/PWGUD/DataModel/UDTables.h b/PWGUD/DataModel/UDTables.h index 65fdc63eb4b..f129bda8215 100644 --- a/PWGUD/DataModel/UDTables.h +++ b/PWGUD/DataModel/UDTables.h @@ -407,6 +407,35 @@ DECLARE_SOA_TABLE(UDTracksFlags, "AOD", "UDTRACKFLAG", DECLARE_SOA_TABLE(UDTracksLabels, "AOD", "UDTRACKLABEL", udtrack::TrackId); +namespace udcollfitbits +{ + +DECLARE_SOA_INDEX_COLUMN(UDCollision, udCollision); /// Link to the UDCOLLISION table + +DECLARE_SOA_COLUMN(Thr1W0, thr1W0, uint64_t); /// 1 MIP thresholds for FT0A ch 0 - ch 63 +DECLARE_SOA_COLUMN(Thr1W1, thr1W1, uint64_t); /// 1 MIP thresholds for FT0A ch 64 - ch 96 & FT0C ch 0 - ch 31 +DECLARE_SOA_COLUMN(Thr1W2, thr1W2, uint64_t); /// 1 MIP thresholds for FT0C ch 32 - ch 96 +DECLARE_SOA_COLUMN(Thr1W3, thr1W3, uint64_t); /// 1 MIP thresholds for FT0C ch 97 - 112 & FV0 0 - 47 + +DECLARE_SOA_COLUMN(Thr2W0, thr2W0, uint64_t); /// 2 MIP thresholds for FT0A ch 0 - ch 63 +DECLARE_SOA_COLUMN(Thr2W1, thr2W1, uint64_t); /// 2 MIP thresholds for FT0A ch 63 - ch 96 & FT0C ch 0 - ch 31 +DECLARE_SOA_COLUMN(Thr2W2, thr2W2, uint64_t); /// 2 MIP thresholds for FT0C ch 32 - ch 96 +DECLARE_SOA_COLUMN(Thr2W3, thr2W3, uint64_t); /// 2 MIP thresholds for FT0C ch 97 - 112 & FV0 0 - 47 +} // namespace udcollfitbits + +DECLARE_SOA_TABLE(UDCollisionFITBits, "AOD", "UDCOLLFITBITS", + o2::soa::Index<>, + udcollfitbits::UDCollisionId, /// Link to the UDCOLLISION table + udcollfitbits::Thr1W0, /// 1 MIP thresholds for FT0A ch 0 - ch 63 + udcollfitbits::Thr1W1, /// 1 MIP thresholds for FT0A ch 63 - ch 96 & FT0C ch 0 - ch 31 + udcollfitbits::Thr1W2, /// 1 MIP thresholds for FT0C ch 32 - ch 96 + udcollfitbits::Thr1W3, /// 1 MIP thresholds for FT0C ch 97 - 112 & FV0 0 - 47 + udcollfitbits::Thr2W0, /// 2 MIP thresholds for FT0A ch 0 - ch 63 + udcollfitbits::Thr2W1, /// 2 MIP thresholds for FT0A ch 63 - ch 96 & FT0C ch 0 - ch 31 + udcollfitbits::Thr2W2, /// 2 MIP thresholds for FT0C ch 32 - ch 96 + udcollfitbits::Thr2W3 /// 2 MIP thresholds for FT0C ch 97 - 112 & FV0 0 - 47 +); + using UDTrack = UDTracks::iterator; using UDTrackCov = UDTracksCov::iterator; using UDTrackExtra = UDTracksExtra::iterator; diff --git a/PWGUD/TableProducer/CMakeLists.txt b/PWGUD/TableProducer/CMakeLists.txt index fb3bd5e2275..2790472b1ad 100644 --- a/PWGUD/TableProducer/CMakeLists.txt +++ b/PWGUD/TableProducer/CMakeLists.txt @@ -1,72 +1,45 @@ -# 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. add_subdirectory(Converters) -o2physics_add_dpl_workflow(dg-cand-producer - SOURCES dgCandProducer.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::DGCutparHolder O2Physics::AnalysisCCDB O2Physics::EventFilteringUtils - COMPONENT_NAME Analysis) + o2physics_add_dpl_workflow(dg - cand - producer SOURCES dgCandProducer.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::DGCutparHolder O2Physics::AnalysisCCDB O2Physics::EventFilteringUtils COMPONENT_NAME Analysis) -o2physics_add_dpl_workflow(sgcand-producer - SOURCES SGCandProducer.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::SGCutParHolder O2Physics::AnalysisCCDB - COMPONENT_NAME Analysis) + o2physics_add_dpl_workflow(sgcand - producer + SOURCES SGCandProducer.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::SGCutParHolder O2Physics::AnalysisCCDB O2Physics::FITCutParHolder + COMPONENT_NAME Analysis) -o2physics_add_dpl_workflow(dgbccand-producer - SOURCES DGBCCandProducer.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::DGCutparHolder - COMPONENT_NAME Analysis) + o2physics_add_dpl_workflow(dgbccand - producer + SOURCES DGBCCandProducer.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::DGCutparHolder + COMPONENT_NAME Analysis) -o2physics_add_dpl_workflow(upccand-producer - SOURCES UPCCandidateProducer.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::UPCCutparHolder - COMPONENT_NAME Analysis) + o2physics_add_dpl_workflow(upccand - producer + SOURCES UPCCandidateProducer.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::UPCCutparHolder + COMPONENT_NAME Analysis) -o2physics_add_dpl_workflow(tau-event-table-producer - SOURCES tauEventTableProducer.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore - COMPONENT_NAME Analysis) + o2physics_add_dpl_workflow(tau - event - table - producer SOURCES tauEventTableProducer.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore COMPONENT_NAME Analysis) -o2physics_add_dpl_workflow(two-tracks-event-table-producer - SOURCES twoTracksEventTableProducer.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore - COMPONENT_NAME Analysis) + o2physics_add_dpl_workflow(two - tracks - event - table - producer SOURCES twoTracksEventTableProducer.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore COMPONENT_NAME Analysis) -o2physics_add_dpl_workflow(fwd-track-propagation - SOURCES fwdTrackPropagation.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2::GlobalTracking - COMPONENT_NAME Analysis) + o2physics_add_dpl_workflow(fwd - track - propagation SOURCES fwdTrackPropagation.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2::GlobalTracking COMPONENT_NAME Analysis) -o2physics_add_dpl_workflow(udmcparticles-to-udtracks - SOURCES udMcParticles2udTracks.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore - COMPONENT_NAME Analysis) + o2physics_add_dpl_workflow(udmcparticles - to - udtracks SOURCES udMcParticles2udTracks.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore COMPONENT_NAME Analysis) -o2physics_add_dpl_workflow(udmccollisions-to-udcollisions - SOURCES udMcCollisions2udCollisions.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore - COMPONENT_NAME Analysis) + o2physics_add_dpl_workflow(udmccollisions - to - udcollisions SOURCES udMcCollisions2udCollisions.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore COMPONENT_NAME Analysis) -o2physics_add_dpl_workflow(tau-three-prong-event-table-producer - SOURCES tauThreeProngEventTableProducer.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore - COMPONENT_NAME Analysis) + o2physics_add_dpl_workflow(tau - three - prong - event - table - producer SOURCES tauThreeProngEventTableProducer.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore COMPONENT_NAME Analysis) -o2physics_add_dpl_workflow(upc-cand-producer-muon - SOURCES upcCandProducerMuon.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::UPCCutparHolder O2::GlobalTracking - COMPONENT_NAME Analysis) + o2physics_add_dpl_workflow(upc - cand - producer - muon SOURCES upcCandProducerMuon.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::UPCCutparHolder O2::GlobalTracking COMPONENT_NAME Analysis) -o2physics_add_dpl_workflow(upc-cand-producer-global-muon - SOURCES upcCandProducerGlobalMuon.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::UPCCutparHolder O2::GlobalTracking - COMPONENT_NAME Analysis) + o2physics_add_dpl_workflow(upc - cand - producer - global - muon SOURCES upcCandProducerGlobalMuon.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::UPCCutparHolder O2::GlobalTracking COMPONENT_NAME Analysis) diff --git a/PWGUD/TableProducer/SGCandProducer.cxx b/PWGUD/TableProducer/SGCandProducer.cxx index 888dbfb608e..f69acb28e16 100644 --- a/PWGUD/TableProducer/SGCandProducer.cxx +++ b/PWGUD/TableProducer/SGCandProducer.cxx @@ -12,12 +12,13 @@ /// \file SGCandProducer.cxx /// \brief Produces PWGUD derived table from standard tables /// -/// \author Alexander Bylinkin , Uniersity of Bergen -/// \since 23.11.2023 +/// \author Alexander Bylinkin , University of Bergen +/// \since 23.11.2023 /// \author Adam Matyja , INP PAN Krakow, Poland -/// \since May 2025 +/// \since May 2025 // +#include "PWGUD/Core/FITCutParHolder.h" #include "PWGUD/Core/SGSelector.h" #include "PWGUD/Core/UPCHelpers.h" #include "PWGUD/DataModel/UDTables.h" @@ -41,6 +42,7 @@ #include "Framework/runDataProcessing.h" #include "ReconstructionDataFormats/Vertex.h" +#include #include #include #include @@ -75,6 +77,8 @@ struct SGCandProducer { // get an SGCutparHolder SGCutParHolder sameCuts = SGCutParHolder(); // SGCutparHolder Configurable SGCuts{"SGCuts", {}, "SG event cuts"}; + FITCutParHolder fitCuts = FITCutParHolder(); + Configurable FITCuts{"FITCuts", {}, "FIT bitset cuts"}; Configurable verboseInfo{"verboseInfo", false, "Print general info to terminal; default it false."}; Configurable saveAllTracks{"saveAllTracks", true, "save only PV contributors or all tracks associated to a collision"}; Configurable savenonPVCITSOnlyTracks{"savenonPVCITSOnlyTracks", false, "save non PV contributors with ITS only information"}; @@ -87,6 +91,8 @@ struct SGCandProducer { Configurable storeSG{"storeSG", true, "Store SG events in the output"}; Configurable storeDG{"storeDG", true, "Store DG events in the output"}; + Configurable saveFITbitsets{"saveFITbitsets", true, "Write FT0 and FV0 bitset tables to output"}; + Configurable isGoodRCTCollision{"isGoodRCTCollision", true, "Check RCT flags for FT0,ITS,TPC and tracking"}; Configurable isGoodRCTZdc{"isGoodRCTZdc", false, "Check RCT flags for ZDC if present in run"}; @@ -94,7 +100,7 @@ struct SGCandProducer { Configurable fillTrackTables{"fillTrackTables", true, "Fill track tables"}; Configurable fillFwdTrackTables{"fillFwdTrackTables", true, "Fill forward track tables"}; - // SG selector + // SG selector SGSelector sgSelector; ctpRateFetcher mRateFetcher; @@ -119,6 +125,7 @@ struct SGCandProducer { Produces outputFwdTracks; Produces outputFwdTracksExtra; Produces outputTracksLabel; + Produces outputFITBits; // initialize histogram registry HistogramRegistry registry{ @@ -205,78 +212,6 @@ struct SGCandProducer { outputTracksLabel(track.globalIndex()); } - // function to process trigger counters, accounting for BC selection bits - void processCountersTrg(BCs const& bcs, aod::FT0s const&, aod::Zdcs const&) - { - const auto& firstBc = bcs.iteratorAt(0); - if (runNumber != firstBc.runNumber()) - runNumber = firstBc.runNumber(); - - auto hCountersTrg = getHist(TH1, "reco/hCountersTrg"); - auto hCountersTrgBcSel = getHist(TH1, "reco/hCountersTrgBcSel"); - auto hLumi = getHist(TH1, "reco/hLumi"); - auto hLumiBcSel = getHist(TH1, "reco/hLumiBcSel"); - - // Cross sections in ub. Using dummy -1 if lumi estimator is not reliable - float csTCE = 10.36e6; - const float csZEM = 415.2e6; // see AN: https://alice-notes.web.cern.ch/node/1515 - const float csZNC = 214.5e6; // see AN: https://alice-notes.web.cern.ch/node/1515 - if (runNumber > 543437 && runNumber < 543514) { - csTCE = 8.3e6; - } - if (runNumber >= 543514) { - csTCE = 4.10e6; // see AN: https://alice-notes.web.cern.ch/node/1515 - } - - for (const auto& bc : bcs) { - bool hasFT0 = bc.has_foundFT0(); - bool hasZDC = bc.has_foundZDC(); - if (!hasFT0 && !hasZDC) - continue; - bool isSelectedBc = true; - if (rejectAtTFBoundary && !bc.selection_bit(aod::evsel::kNoTimeFrameBorder)) - isSelectedBc = false; - if (noITSROFrameBorder && !bc.selection_bit(aod::evsel::kNoITSROFrameBorder)) - isSelectedBc = false; - if (hasFT0) { - auto ft0TrgMask = bc.ft0().triggerMask(); - if (TESTBIT(ft0TrgMask, o2::fit::Triggers::bitVertex)) { - hCountersTrg->Fill("TVX", 1); - if (isSelectedBc) - hCountersTrgBcSel->Fill("TVX", 1); - } - if (TESTBIT(ft0TrgMask, o2::fit::Triggers::bitVertex) && TESTBIT(ft0TrgMask, o2::fit::Triggers::bitCen)) { - hCountersTrg->Fill("TCE", 1); - hLumi->Fill("TCE", 1. / csTCE); - if (isSelectedBc) { - hCountersTrgBcSel->Fill("TCE", 1); - hLumiBcSel->Fill("TCE", 1. / csTCE); - } - } - } - if (hasZDC) { - if (bc.selection_bit(aod::evsel::kIsBBZNA) || bc.selection_bit(aod::evsel::kIsBBZNC)) { - hCountersTrg->Fill("ZEM", 1); - hLumi->Fill("ZEM", 1. / csZEM); - if (isSelectedBc) { - hCountersTrgBcSel->Fill("ZEM", 1); - hLumiBcSel->Fill("ZEM", 1. / csZEM); - } - } - if (bc.selection_bit(aod::evsel::kIsBBZNC)) { - hCountersTrg->Fill("ZNC", 1); - hLumi->Fill("ZNC", 1. / csZNC); - if (isSelectedBc) { - hCountersTrgBcSel->Fill("ZNC", 1); - hLumiBcSel->Fill("ZNC", 1. / csZNC); - } - } - } - } - } - - PROCESS_SWITCH(SGCandProducer, processCountersTrg, "Produce trigger counters and luminosity histograms", true); - // function to process reconstructed data template void processReco(std::string histdir, TCol const& collision, BCs const& bcs, @@ -284,8 +219,7 @@ struct SGCandProducer { aod::FV0As const& fv0as, aod::FT0s const& ft0s, aod::FDDs const& fdds) { if (verboseInfo) - LOGF(debug, " collision %d", collision.globalIndex()); - + LOGF(debug, " collision %d", collision.globalIndex()); getHist(TH1, histdir + "/Stat")->Fill(0., 1.); // reject collisions at TF boundaries if (rejectAtTFBoundary && !collision.selection_bit(aod::evsel::kNoTimeFrameBorder)) { @@ -393,6 +327,24 @@ struct SGCandProducer { if (verboseInfo) LOGF(info, "%s Coll GID %d", histdir, collision.globalIndex()); outputCollsLabels(collision.globalIndex()); + + uint64_t w1[4] = {0ull, 0ull, 0ull, 0ull}; + uint64_t w2[4] = {0ull, 0ull, 0ull, 0ull}; + + if (fitCuts.saveFITbitsets() && newbc.has_foundFT0() && newbc.has_fv0a()) { + udhelpers::buildFT0FV0Words(newbc.ft0(), newbc.fv0a(), w1, w2, + fitCuts.thr1_FT0A(), + fitCuts.thr1_FT0C(), + fitCuts.thr1_FV0A(), + fitCuts.thr2_FT0A(), + fitCuts.thr2_FT0C(), + fitCuts.thr2_FV0A()); + } + + outputFITBits(outputCollisions.lastIndex(), + w1[0], w1[1], w1[2], w1[3], + w2[0], w2[1], w2[2], w2[3]); + if (newbc.has_zdc()) { auto zdc = newbc.zdc(); udZdcsReduced(outputCollisions.lastIndex(), zdc.timeZNA(), zdc.timeZNC(), zdc.energyCommonZNA(), zdc.energyCommonZNC()); @@ -408,7 +360,7 @@ struct SGCandProducer { } else if (saveAllTracks) { if (track.itsClusterSizes() && track.itsChi2NCl() > 0 && ((track.tpcNClsFindable() == 0 && savenonPVCITSOnlyTracks) || track.tpcNClsFindable() > 50)) updateUDTrackTables(outputCollisions.lastIndex(), track, bc.globalBC()); - // if (track.isPVContributor()) updateUDTrackTables(outputCollisions.lastIndex(), track, bc.globalBC()); + // if (track.isPVContributor()) updateUDTrackTables(outputCollisions.lastIndex(), track, bc.globalBC()); } } } @@ -431,6 +383,7 @@ struct SGCandProducer { ccdb->setCaching(true); ccdb->setFatalWhenNull(false); sameCuts = (SGCutParHolder)SGCuts; + fitCuts = (FITCutParHolder)FITCuts; // add histograms for the different process functions histPointers.clear(); @@ -592,7 +545,7 @@ struct McSGCandProducer { for (const auto& oldmid : oldmids) { auto m = McParts.rawIteratorAt(oldmid); if (verboseInfoMC) - LOGF(debug, " m %d", m.globalIndex()); + LOGF(debug, "m %d", m.globalIndex()); if (mcPartIsSaved.find(oldmid) != mcPartIsSaved.end()) { newval = mcPartIsSaved[oldmid]; } else { @@ -741,7 +694,7 @@ struct McSGCandProducer { if (mcsgId >= 0 && mcOfInterest) { if (mcColIsSaved.find(mcsgId) == mcColIsSaved.end()) { if (verboseInfoMC) - LOGF(info, " Saving McCollision %d", mcsgId); + LOGF(info, "Saving McCollision %d", mcsgId); // update UDMcCollisions auto sgcandMcCol = sgcand.collision_as().mcCollision(); updateUDMcCollisions(sgcandMcCol, globBC); @@ -762,7 +715,7 @@ struct McSGCandProducer { // If the sgcand has no associated McCollision then only the McParticles which are associated // with the tracks of the sgcand are saved if (verboseInfoMC) - LOGF(info, " Saving McCollision %d", -1); + LOGF(info, "Saving McCollision %d", -1); // update UDMcColsLabels (for each UDCollision -> UDMcCollisions) outputMcCollsLabels(-1); @@ -804,7 +757,7 @@ struct McSGCandProducer { // but only consider generated events of interest if (mcOfInterest && mcColIsSaved.find(mccolId) == mcColIsSaved.end()) { if (verboseInfoMC) - LOGF(info, " Saving McCollision %d", mccolId); + LOGF(info, "Saving McCollision %d", mccolId); // update UDMcCollisions updateUDMcCollisions(mccol, globBC); mcColIsSaved[mccolId] = outputMcCollisions.lastIndex(); @@ -848,7 +801,7 @@ struct McSGCandProducer { // update UDMcCollisions and UDMcParticles if (mcColIsSaved.find(mccolId) == mcColIsSaved.end()) { if (verboseInfoMC) - LOGF(info, " Saving McCollision %d", mccolId); + LOGF(info, "Saving McCollision %d", mccolId); // update UDMcCollisions updateUDMcCollisions(mccol, globBC); diff --git a/PWGUD/Tasks/CMakeLists.txt b/PWGUD/Tasks/CMakeLists.txt index 62c6abc732f..94b11d4cba6 100644 --- a/PWGUD/Tasks/CMakeLists.txt +++ b/PWGUD/Tasks/CMakeLists.txt @@ -1,270 +1,184 @@ -# 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(upc-polarisation-jpsi-incoh - SOURCES upcPolarisationJpsiIncoh.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2::DetectorsBase - COMPONENT_NAME Analysis) - -o2physics_add_dpl_workflow(upc - SOURCES upcAnalysis.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2::DetectorsBase - COMPONENT_NAME Analysis) - -o2physics_add_dpl_workflow(sg-spectra - SOURCES sgSpectraAnalyzer.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2::DetectorsBase - COMPONENT_NAME Analysis) - -o2physics_add_dpl_workflow(sg-pid-spectra-table - SOURCES sgPIDSpectraTable.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2::DetectorsBase - COMPONENT_NAME Analysis) - -o2physics_add_dpl_workflow(sg-pid-analyzer - SOURCES sgPIDAnalyzer.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2::DetectorsBase - COMPONENT_NAME Analysis) - -o2physics_add_dpl_workflow(sg-pid-spectra - SOURCES sgPIDSpectra.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2::DetectorsBase - COMPONENT_NAME Analysis) - -o2physics_add_dpl_workflow(sg-incl-jpsi - SOURCES sgInclJpsi.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2::DetectorsBase - COMPONENT_NAME Analysis) - -o2physics_add_dpl_workflow(sg-excl-omega - SOURCES sgExclOmega.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2::DetectorsBase - COMPONENT_NAME Analysis) - -o2physics_add_dpl_workflow(sg-excl-universe - SOURCES sgExcUniverse.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2::DetectorsBase - COMPONENT_NAME Analysis) - -o2physics_add_dpl_workflow(sg-fourpi - SOURCES sgFourPiAnalyzer.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2::DetectorsBase - COMPONENT_NAME Analysis) - -o2physics_add_dpl_workflow(sg-sixpi - SOURCES sgSixPiAnalyzer.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2::DetectorsBase - COMPONENT_NAME Analysis) - -o2physics_add_dpl_workflow(sg-twopi - SOURCES sgTwoPiAnalyzer.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2::DetectorsBase - COMPONENT_NAME Analysis) - -o2physics_add_dpl_workflow(sg-d0 - SOURCES sgD0Analyzer.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2::DetectorsBase - COMPONENT_NAME Analysis) - -o2physics_add_dpl_workflow(sg-fit - SOURCES sgFITAnalyzer.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2::DetectorsBase - COMPONENT_NAME Analysis) - -o2physics_add_dpl_workflow(upc-forward - SOURCES upcForward.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2::DetectorsBase - COMPONENT_NAME Analysis) - -o2physics_add_dpl_workflow(diff-mcdatascanner - SOURCES diffMCDataScanner.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore - COMPONENT_NAME Analysis) - -o2physics_add_dpl_workflow(diff-mcqa - SOURCES diffMCQA.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::DGCutparHolder - COMPONENT_NAME Analysis) - -o2physics_add_dpl_workflow(diff-qa - SOURCES diffQA.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::DGCutparHolder - COMPONENT_NAME Analysis) - -o2physics_add_dpl_workflow(dgcand-analyzer - SOURCES dgCandAnalyzer.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::DGCutparHolder O2Physics::UDGoodRunSelector O2Physics::DGPIDSelector O2Physics::UDFSParser - COMPONENT_NAME Analysis) - -o2physics_add_dpl_workflow(upccand-analyzer - SOURCES upcCandidateAnalyzer.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2::DetectorsBase - COMPONENT_NAME Analysis) - -o2physics_add_dpl_workflow(upccand-producer-qa - SOURCES upcCandidateProducerQa.cpp - PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2::DetectorsBase - COMPONENT_NAME Analysis) - -o2physics_add_dpl_workflow(upc-mft - SOURCES upcMft.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2::ReconstructionDataFormats O2::DetectorsBase O2::DetectorsCommonDataFormats - COMPONENT_NAME Analysis) - -o2physics_add_dpl_workflow(upc-veto - SOURCES upcVetoAnalysis.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2::DetectorsBase - COMPONENT_NAME Analysis) - -o2physics_add_dpl_workflow(tautau13topo - SOURCES upcTauTau13topo.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::DGPIDSelector - COMPONENT_NAME Analysis) - -o2physics_add_dpl_workflow(upc-tau-rl - SOURCES upcTauRl.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2::ReconstructionDataFormats O2::DetectorsBase O2::DetectorsCommonDataFormats - COMPONENT_NAME Analysis) - -o2physics_add_dpl_workflow(polarisation-rho - SOURCES polarisationRho.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::DGPIDSelector - COMPONENT_NAME Analysis) - -o2physics_add_dpl_workflow(upc-jpsi-corr - SOURCES upcJpsiCorr.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::DGPIDSelector - COMPONENT_NAME Analysis) - -o2physics_add_dpl_workflow(exclusive-phi - SOURCES exclusivePhi.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::DGPIDSelector - COMPONENT_NAME Analysis) - -o2physics_add_dpl_workflow(upc-photonuclear-jmg - SOURCES upcPhotonuclearAnalysisJMG.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::PWGCFCore O2::ReconstructionDataFormats O2::DetectorsBase O2::DetectorsCommonDataFormats - COMPONENT_NAME Analysis) - -o2physics_add_dpl_workflow(exclusive-two-protons - SOURCES exclusiveTwoProtons.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::DGPIDSelector - COMPONENT_NAME Analysis) - -o2physics_add_dpl_workflow(exclusive-two-protons-sg - SOURCES exclusiveTwoProtonsSG.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::DGPIDSelector - COMPONENT_NAME Analysis) - -o2physics_add_dpl_workflow(exclusive-phi-leptons - SOURCES exclusivePhiLeptons.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::DGPIDSelector - COMPONENT_NAME Analysis) - -o2physics_add_dpl_workflow(exclusive-phi-leptons-trees - SOURCES exclusivePhiLeptonsTrees.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::DGPIDSelector - COMPONENT_NAME Analysis) - -o2physics_add_dpl_workflow(exclusive-pentaquark - SOURCES exclusivePentaquark.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::DGPIDSelector - COMPONENT_NAME Analysis) - -o2physics_add_dpl_workflow(inclusive-phikstar-sd - SOURCES sginclusivePhiKstarSD.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::DGPIDSelector - COMPONENT_NAME Analysis) - -o2physics_add_dpl_workflow(sg-exclusive-phi - SOURCES sgExclusivePhi.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::DGPIDSelector - COMPONENT_NAME Analysis) - -o2physics_add_dpl_workflow(sg-exclusive-phi-its - SOURCES sgExclusivePhiITSselections.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::DGPIDSelector - COMPONENT_NAME Analysis) - -o2physics_add_dpl_workflow(upc-pion-analysis - SOURCES upcPionAnalysis.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::DGPIDSelector - COMPONENT_NAME Analysis) - -o2physics_add_dpl_workflow(fwd-muons-upc - SOURCES FwdMuonsUPC.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::DGPIDSelector - COMPONENT_NAME Analysis) - -o2physics_add_dpl_workflow(upc-event-itsrof-counter - SOURCES upcEventITSROFcounter.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::AnalysisCCDB - COMPONENT_NAME Analysis) - -o2physics_add_dpl_workflow(upc-rho-analysis - SOURCES upcRhoAnalysis.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::DGPIDSelector - COMPONENT_NAME Analysis) - -o2physics_add_dpl_workflow(upc-rho-prime-analysis - SOURCES upcRhoPrimeAnalysis.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::DGPIDSelector - COMPONENT_NAME Analysis) - -o2physics_add_dpl_workflow(event-by-event - SOURCES eventByevent.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::DGPIDSelector - COMPONENT_NAME Analysis) - -o2physics_add_dpl_workflow(exclusive-rho-to-four-pi - SOURCES exclusiveRhoTo4Pi.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::DGPIDSelector - COMPONENT_NAME Analysis) - -o2physics_add_dpl_workflow(upc-quarkonia-central-barrel - SOURCES upcQuarkoniaCentralBarrel.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2::DetectorsBase - COMPONENT_NAME Analysis) - -o2physics_add_dpl_workflow(test-mc-std-tabs-rl - SOURCES testMcStdTabsRl.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2::ReconstructionDataFormats O2::DetectorsBase O2::DetectorsCommonDataFormats - COMPONENT_NAME Analysis) - -o2physics_add_dpl_workflow(decaytree-analyzer - SOURCES decayTreeAnalyzer.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::UDGoodRunSelector O2Physics::decayTree - COMPONENT_NAME Analysis) - -o2physics_add_dpl_workflow(flow-cumulants-upc - SOURCES flowCumulantsUpc.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::AnalysisCCDB O2Physics::GFWCore - COMPONENT_NAME Analysis) - -o2physics_add_dpl_workflow(flow-correlations-upc - SOURCES flowCorrelationsUpc.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::AnalysisCCDB O2Physics::PWGCFCore - COMPONENT_NAME Analysis) - -o2physics_add_dpl_workflow(analysis-mc-dpm-jet-sg-v3 - SOURCES analysisMCDPMJetSGv3.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore - COMPONENT_NAME Analysis) - -o2physics_add_dpl_workflow(upc-test-rct-tables - SOURCES upcTestRctTables.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore - COMPONENT_NAME Analysis) - -o2physics_add_dpl_workflow(sg-exclusive-jpsi-midrapidity - SOURCES sgExclusiveJpsiMidrapidity.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore - COMPONENT_NAME Analysis) +o2physics_add_dpl_workflow(upc - polarisation - jpsi - incoh SOURCES upcPolarisationJpsiIncoh.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2::DetectorsBase COMPONENT_NAME Analysis) + + o2physics_add_dpl_workflow(upc + SOURCES upcAnalysis.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2::DetectorsBase + COMPONENT_NAME Analysis) + + o2physics_add_dpl_workflow(sg - spectra + SOURCES sgSpectraAnalyzer.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2::DetectorsBase + COMPONENT_NAME Analysis) + + o2physics_add_dpl_workflow(sg - pid - spectra - table SOURCES sgPIDSpectraTable.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2::DetectorsBase COMPONENT_NAME Analysis) + + o2physics_add_dpl_workflow(sg - pid - analyzer SOURCES sgPIDAnalyzer.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2::DetectorsBase COMPONENT_NAME Analysis) + + o2physics_add_dpl_workflow(sg - pid - spectra SOURCES sgPIDSpectra.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2::DetectorsBase COMPONENT_NAME Analysis) + + o2physics_add_dpl_workflow(sg - incl - jpsi SOURCES sgInclJpsi.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2::DetectorsBase COMPONENT_NAME Analysis) + + o2physics_add_dpl_workflow(sg - excl - omega SOURCES sgExclOmega.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2::DetectorsBase COMPONENT_NAME Analysis) + + o2physics_add_dpl_workflow(sg - excl - universe SOURCES sgExcUniverse.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2::DetectorsBase COMPONENT_NAME Analysis) + + o2physics_add_dpl_workflow(sg - fourpi + SOURCES sgFourPiAnalyzer.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2::DetectorsBase + COMPONENT_NAME Analysis) + + o2physics_add_dpl_workflow(sg - sixpi + SOURCES sgSixPiAnalyzer.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2::DetectorsBase + COMPONENT_NAME Analysis) + + o2physics_add_dpl_workflow(sg - twopi + SOURCES sgTwoPiAnalyzer.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2::DetectorsBase + COMPONENT_NAME Analysis) + + o2physics_add_dpl_workflow(sg - d0 + SOURCES sgD0Analyzer.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2::DetectorsBase + COMPONENT_NAME Analysis) + + o2physics_add_dpl_workflow(sg - fit + SOURCES sgFITAnalyzer.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2::DetectorsBase + COMPONENT_NAME Analysis) + + o2physics_add_dpl_workflow(upc - forward + SOURCES upcForward.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2::DetectorsBase + COMPONENT_NAME Analysis) + + o2physics_add_dpl_workflow(diff - mcdatascanner + SOURCES diffMCDataScanner.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore + COMPONENT_NAME Analysis) + + o2physics_add_dpl_workflow(diff - mcqa + SOURCES diffMCQA.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::DGCutparHolder + COMPONENT_NAME Analysis) + + o2physics_add_dpl_workflow(diff - qa + SOURCES diffQA.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::DGCutparHolder + COMPONENT_NAME Analysis) + + o2physics_add_dpl_workflow(dgcand - analyzer + SOURCES dgCandAnalyzer.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::DGCutparHolder O2Physics::UDGoodRunSelector O2Physics::DGPIDSelector O2Physics::UDFSParser + COMPONENT_NAME Analysis) + + o2physics_add_dpl_workflow(upccand - analyzer + SOURCES upcCandidateAnalyzer.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2::DetectorsBase + COMPONENT_NAME Analysis) + + o2physics_add_dpl_workflow(upccand - producer - qa SOURCES upcCandidateProducerQa.cpp PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2::DetectorsBase COMPONENT_NAME Analysis) + + o2physics_add_dpl_workflow(upc - mft + SOURCES upcMft.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2::ReconstructionDataFormats O2::DetectorsBase O2::DetectorsCommonDataFormats + COMPONENT_NAME Analysis) + + o2physics_add_dpl_workflow(upc - veto + SOURCES upcVetoAnalysis.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2::DetectorsBase + COMPONENT_NAME Analysis) + + o2physics_add_dpl_workflow(tautau13topo + SOURCES upcTauTau13topo.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::DGPIDSelector + COMPONENT_NAME Analysis) + + o2physics_add_dpl_workflow(upc - tau - rl SOURCES upcTauRl.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2::ReconstructionDataFormats O2::DetectorsBase O2::DetectorsCommonDataFormats COMPONENT_NAME Analysis) + + o2physics_add_dpl_workflow(polarisation - rho + SOURCES polarisationRho.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::DGPIDSelector + COMPONENT_NAME Analysis) + + o2physics_add_dpl_workflow(upc - jpsi - corr SOURCES upcJpsiCorr.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::DGPIDSelector COMPONENT_NAME Analysis) + + o2physics_add_dpl_workflow(exclusive - phi + SOURCES exclusivePhi.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::DGPIDSelector + COMPONENT_NAME Analysis) + + o2physics_add_dpl_workflow(upc - photonuclear - jmg SOURCES upcPhotonuclearAnalysisJMG.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::PWGCFCore O2::ReconstructionDataFormats O2::DetectorsBase O2::DetectorsCommonDataFormats COMPONENT_NAME Analysis) + + o2physics_add_dpl_workflow(exclusive - two - protons SOURCES exclusiveTwoProtons.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::DGPIDSelector COMPONENT_NAME Analysis) + + o2physics_add_dpl_workflow(exclusive - two - protons - sg SOURCES exclusiveTwoProtonsSG.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::DGPIDSelector COMPONENT_NAME Analysis) + + o2physics_add_dpl_workflow(exclusive - phi - leptons SOURCES exclusivePhiLeptons.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::DGPIDSelector COMPONENT_NAME Analysis) + + o2physics_add_dpl_workflow(exclusive - phi - leptons - trees SOURCES exclusivePhiLeptonsTrees.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::DGPIDSelector COMPONENT_NAME Analysis) + + o2physics_add_dpl_workflow(exclusive - pentaquark + SOURCES exclusivePentaquark.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::DGPIDSelector + COMPONENT_NAME Analysis) + + o2physics_add_dpl_workflow(inclusive - phikstar - sd SOURCES sginclusivePhiKstarSD.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::DGPIDSelector COMPONENT_NAME Analysis) + + o2physics_add_dpl_workflow(sg - exclusive - phi SOURCES sgExclusivePhi.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::DGPIDSelector COMPONENT_NAME Analysis) + + o2physics_add_dpl_workflow(sg - exclusive - phi - its SOURCES sgExclusivePhiITSselections.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::DGPIDSelector COMPONENT_NAME Analysis) + + o2physics_add_dpl_workflow(upc - pion - analysis SOURCES upcPionAnalysis.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::DGPIDSelector COMPONENT_NAME Analysis) + + o2physics_add_dpl_workflow(fwd - muons - upc SOURCES FwdMuonsUPC.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::DGPIDSelector COMPONENT_NAME Analysis) + + o2physics_add_dpl_workflow(upc - event - itsrof - counter SOURCES upcEventITSROFcounter.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::AnalysisCCDB COMPONENT_NAME Analysis) + + o2physics_add_dpl_workflow(upc - rho - analysis SOURCES upcRhoAnalysis.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::DGPIDSelector COMPONENT_NAME Analysis) + + o2physics_add_dpl_workflow(upc - rho - prime - analysis SOURCES upcRhoPrimeAnalysis.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::DGPIDSelector COMPONENT_NAME Analysis) + + o2physics_add_dpl_workflow(event - by - event SOURCES eventByevent.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::DGPIDSelector COMPONENT_NAME Analysis) + + o2physics_add_dpl_workflow(exclusive - rho - to - four - pi SOURCES exclusiveRhoTo4Pi.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::DGPIDSelector COMPONENT_NAME Analysis) + + o2physics_add_dpl_workflow(upc - quarkonia - central - barrel SOURCES upcQuarkoniaCentralBarrel.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2::DetectorsBase COMPONENT_NAME Analysis) + + o2physics_add_dpl_workflow(test - mc - std - tabs - rl SOURCES testMcStdTabsRl.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2::ReconstructionDataFormats O2::DetectorsBase O2::DetectorsCommonDataFormats COMPONENT_NAME Analysis) + + o2physics_add_dpl_workflow(decaytree - analyzer + SOURCES decayTreeAnalyzer.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::UDGoodRunSelector O2Physics::decayTree + COMPONENT_NAME Analysis) + + o2physics_add_dpl_workflow(flow - cumulants - upc SOURCES flowCumulantsUpc.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::AnalysisCCDB O2Physics::GFWCore COMPONENT_NAME Analysis) + + o2physics_add_dpl_workflow(flow - correlations - upc SOURCES flowCorrelationsUpc.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::AnalysisCCDB O2Physics::PWGCFCore COMPONENT_NAME Analysis) + + o2physics_add_dpl_workflow(analysis - mc - dpm - jet - sg - v3 SOURCES analysisMCDPMJetSGv3.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore COMPONENT_NAME Analysis) + + o2physics_add_dpl_workflow(upc - test - rct - tables SOURCES upcTestRctTables.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore COMPONENT_NAME Analysis) + + o2physics_add_dpl_workflow(sg - exclusive - jpsi - midrapidity SOURCES sgExclusiveJpsiMidrapidity.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore COMPONENT_NAME Analysis) + + o2physics_add_dpl_workflow(fitbit - mapping + SOURCES upcTestFITBitMapping.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore + COMPONENT_NAME Analysis) + + o2physics_add_dpl_workflow(fit - multiplicity + SOURCES upcFITMultiplicity.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore + COMPONENT_NAME Analysis) diff --git a/PWGUD/Tasks/upcFITMultiplicity.cxx b/PWGUD/Tasks/upcFITMultiplicity.cxx new file mode 100644 index 00000000000..25b1d5c910a --- /dev/null +++ b/PWGUD/Tasks/upcFITMultiplicity.cxx @@ -0,0 +1,479 @@ +// 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. +// +// \brief FIT bits to phi, eta mapping + multiplicity from FIT bits +// \author Sandor Lokos, sandor.lokos@cern.ch +// \since March 2026 + +#include "PWGUD/Core/SGSelector.h" +#include "PWGUD/Core/UDHelpers.h" +#include "PWGUD/DataModel/UDTables.h" + +#include "FT0Base/Geometry.h" +#include "Framework/AnalysisTask.h" +#include "Framework/HistogramRegistry.h" +#include "Framework/Logger.h" +#include "Framework/runDataProcessing.h" + +#include +#include +#include + +using namespace o2; +using namespace o2::framework; + +using UDCollisionsFull = soa::Join< + aod::UDCollisions, + aod::UDCollisionsSels, + aod::UDCollisionSelExtras, + aod::UDZdcsReduced>; + +struct UpcTestFITBitMapping { + + SGSelector sgSelector; + + Configurable whichThr{"whichThr", 1, "Use 1=Thr1 bits or 2=Thr2 bits"}; + Configurable maxEvents{"maxEvents", -1, "Process at most this many collisions (-1 = all)"}; + Configurable debugPrintEvery{"debugPrintEvery", 1000, "Print every N events (-1 disables)"}; + Configurable debugPrintFirst{"debugPrintFirst", 10, "Always print first N events"}; + Configurable useRctFlag{"useRctFlag", true, "use RCT flags for event selection"}; + Configurable cutRctFlag{"cutRctFlag", 2, "0 = off, 1 = CBT, 2 = CBT+ZDC, 3 = CBThadron, 4 = CBThadron+ZDC"}; + + Configurable applyGapSideZDCVeto{"applyGapSideZDCVeto", true, "Apply ZDC neutron veto on the gap side"}; + Configurable cutZNAnoNeutron{"cutZNAnoNeutron", 1.f, "Maximum allowed ZNA energy for zero-neutron condition"}; + Configurable cutZNCnoNeutron{"cutZNCnoNeutron", 1.f, "Maximum allowed ZNC energy for zero-neutron condition"}; + + Configurable useFT0TimeCut{"useFT0TimeCut", true, "Apply direct FT0 timing cut"}; + Configurable cutFT0TimeA{"cutFT0TimeA", 2., "FT0-A time cut [ns]"}; + Configurable cutFT0TimeC{"cutFT0TimeC", 2., "FT0-C time cut [ns]"}; + + Configurable useFT0AVeto{"useFT0AVeto", true, "Apply FT0-A total amplitude veto"}; + Configurable cutFT0AmpAVeto{"cutFT0AmpAVeto", 100., "Maximum allowed FT0-A total amplitude for veto"}; + + Configurable useFV0AVeto{"useFV0AVeto", true, "Apply FV0-A total amplitude veto"}; + Configurable cutFV0AmpAVeto{"cutFV0AmpAVeto", 50., "Maximum allowed FV0-A total amplitude for veto"}; + + struct OffsetXYZ { + double x{0.}, y{0.}, z{0.}; + double getX() const { return x; } + double getY() const { return y; } + double getZ() const { return z; } + }; + + std::array offsetFT0{}; + int iRunOffset = 0; + + o2::ft0::Geometry ft0Det{}; + + HistogramRegistry registry{ + "registry", + {{"debug/hEventCounter", "Event counter;step;events", {HistType::kTH1F, {{20, -0.5, 19.5}}}}, + {"debug/hFitBitsSize", "fitBits.size() per collision;fitBits.size();events", {HistType::kTH1F, {{10, -0.5, 9.5}}}}, + {"debug/hCollisionIndexMod", "Collision index mod 100;collision.globalIndex() % 100;events", {HistType::kTH1F, {{100, -0.5, 99.5}}}}, + {"debug/hFT0AChannelOccupancy", "FT0A fired channel occupancy;FT0A channel;counts", {HistType::kTH1F, {{97, -0.5, 96.5}}}}, + {"debug/hFT0CChannelOccupancy", "FT0C fired channel occupancy;FT0C channel;counts", {HistType::kTH1F, {{112, 95.5, 207.5}}}}, + {"debug/hFT0CChannelOccupancy_2tracks", "FT0C fired channel occupancy with 2 tracks;FT0C channel;counts", {HistType::kTH1F, {{112, 95.5, 207.5}}}}, + {"debug/hFT0CChannelOccupancy_ntracks", "FT0C fired channel occupancy with >2 tracks;FT0C channel;counts", {HistType::kTH1F, {{112, 95.5, 207.5}}}}, + + {"map/hPhiA", "FT0A #varphi;#varphi;counts", {HistType::kTH1F, {{9, 0, 2 * M_PI}}}}, + {"map/hEtaA", "FT0A #eta;#eta;counts", {HistType::kTH1F, {{7, 3.4, 4.8}}}}, + {"map/hEtaPhiA", "FT0A #eta vs #varphi;#eta;#varphi", {HistType::kTH2F, {{7, 3.4, 4.8}, {9, 0, 2 * M_PI}}}}, + + {"map/hPhiC", "FT0C #varphi;#varphi;counts", {HistType::kTH1F, {{9, 0, 2 * M_PI}}}}, + {"map/hEtaC", "FT0C #eta;#eta;counts", {HistType::kTH1F, {{5, -3.1, -2.1}}}}, + {"map/hEtaPhiC", "FT0C #eta vs #varphi;#eta;#varphi", {HistType::kTH2F, {{5, -3.1, -2.1}, {9, 0, 2 * M_PI}}}}, + + {"map/hPhiC_2tracks", "FT0C #varphi with 2 tracks;#varphi;counts", {HistType::kTH1F, {{9, 0, 2 * M_PI}}}}, + {"map/hEtaC_2tracks", "FT0C #eta with 2 tracks;#eta;counts", {HistType::kTH1F, {{5, -3.1, -2.1}}}}, + {"map/hEtaPhiC_2tracks", "FT0C #eta vs #varphi with 2 tracks;#eta;#varphi", {HistType::kTH2F, {{5, -3.1, -2.1}, {9, 0, 2 * M_PI}}}}, + + {"map/hPhiC_ntracks", "FT0C #varphi with >2 tracks;#varphi;counts", {HistType::kTH1F, {{9, 0, 2 * M_PI}}}}, + {"map/hEtaC_ntracks", "FT0C #eta with >2 tracks;#eta;counts", {HistType::kTH1F, {{5, -3.1, -2.1}}}}, + {"map/hEtaPhiC_ntracks", "FT0C #eta vs #varphi with >2 tracks;#eta;#varphi", {HistType::kTH2F, {{5, -3.1, -2.1}, {9, 0, 2 * M_PI}}}}, + + {"mult/hPnFT0A", "P(n): FT0A fired-channel multiplicity;N_{fired}^{FT0A};events", {HistType::kTH1F, {{97, -0.5, 96.5}}}}, + {"mult/hPnFT0C", "P(n): FT0C fired-channel multiplicity;N_{fired}^{FT0C};events", {HistType::kTH1F, {{50, -0.5, 49.5}}}}, + {"mult/hPnFV0A", "P(n): FV0A fired-channel multiplicity;N_{fired}^{FV0A};events", {HistType::kTH1F, {{49, -0.5, 48.5}}}}, + + {"mult/hNfiredA_vs_C", "FT0A vs FT0C fired channels;N_{fired}^{FT0A};N_{fired}^{FT0C}", {HistType::kTH2F, {{97, -0.5, 96.5}, {113, -0.5, 112.5}}}}, + + {"qaBeforeCuts/hFT0AAmplitudeVsTime", "FT0A amplitude vs time before cuts;FT0A time (ns);FT0A total amplitude", {HistType::kTH2F, {{200, -40., 40.}, {300, 0., 3000.}}}}, + {"qaBeforeCuts/hFT0CAmplitudeVsTime", "FT0C amplitude vs time before cuts;FT0C time (ns);FT0C total amplitude", {HistType::kTH2F, {{200, -40., 40.}, {300, 0., 3000.}}}}, + + {"qaBeforeCuts/hZNEnergy", "ZNA vs ZNC energy before cuts;ZNA energy;ZNC energy", {HistType::kTH2F, {{250, -5.0, 20.}, {250, -5.0, 20.}}}}, + + {"map/hXYA", "FT0A fired channels in x-y;x [cm];y [cm]", {HistType::kTH2F, {{12, -18., 18.}, {12, -18., 18.}}}}, + {"map/hXYC", "FT0C fired channels in x-y;x [cm];y [cm]", {HistType::kTH2F, {{12, -18., 18.}, {12, -18., 18.}}}}, + {"map/hXYC_2tracks", "FT0C fired channels in x-y with 2 tracks;x [cm];y [cm]", {HistType::kTH2F, {{12, -18., 18.}, {12, -18., 18.}}}}, + {"map/hXYC_ntracks", "FT0C fired channels in x-y with >2 tracks;x [cm];y [cm]", {HistType::kTH2F, {{12, -18., 18.}, {12, -18., 18.}}}}}}; + + int countParticlesInRange(udhelpers::Bits256 const& thr1, udhelpers::Bits256 const& thr2, int first, int last) + { + int n = 0; + for (int bit = first; bit <= last; ++bit) { + const bool aboveThr1 = udhelpers::testBit(thr1, bit); + const bool aboveThr2 = udhelpers::testBit(thr2, bit); + + if (aboveThr2) { + n += 2; + } else if (aboveThr1) { + n += 1; + } + } + return n; + } + + template + bool isGoodRctFlag(const C& collision) + { + switch (cutRctFlag) { + case 1: // CBT + return sgSelector.isCBTOk(collision); + case 2: // CBT + ZDC + return sgSelector.isCBTZdcOk(collision); + case 3: // CBT hadron + return sgSelector.isCBTHadronOk(collision); + case 4: // CBT hadron + ZDC + return sgSelector.isCBTHadronZdcOk(collision); + default: // no RCT cut applied + return true; + } + } + + template + bool isZeroNeutronA(const C& collision) + { + const float eZNA = collision.energyCommonZNA(); // exact accessor to be checked + return eZNA <= cutZNAnoNeutron; + } + + template + bool isZeroNeutronC(const C& collision) + { + const float eZNC = collision.energyCommonZNC(); // exact accessor to be checked + return eZNC <= cutZNCnoNeutron; + } + + template + bool collisionPassesCuts(const C& collision) + { + /* good vertex */ + if (!collision.vtxITSTPC()) { + return false; + } + registry.fill(HIST("debug/hEventCounter"), 4.); + + /* same bunch pile-up rejection */ + if (!collision.sbp()) { + return false; + } + registry.fill(HIST("debug/hEventCounter"), 5.); + + /* ITS ROF rejection */ + if (!collision.itsROFb()) { + return false; + } + registry.fill(HIST("debug/hEventCounter"), 6.); + + /* Timeframe border collision rejection */ + if (!collision.tfb()) { + return false; + } + registry.fill(HIST("debug/hEventCounter"), 7.); + + /* z-vertex cut */ + if (std::abs(collision.posZ()) > 10.0) { + return false; + } + registry.fill(HIST("debug/hEventCounter"), 8.); + + /* RCT flag check*/ + if (useRctFlag) { + if (!isGoodRctFlag(collision)) { + return false; + } + registry.fill(HIST("debug/hEventCounter"), 9.); // passed RCT flag + } + + /* FT0-A veto on total amplitude */ + if (useFT0AVeto) { + const float ampA = collision.totalFT0AmplitudeA(); + if (ampA > cutFT0AmpAVeto) { + return false; + } + registry.fill(HIST("debug/hEventCounter"), 10.); + } + + /* FV0-A veto on total amplitude */ + if (useFV0AVeto) { + const float ampA = collision.totalFV0AmplitudeA(); + if (ampA > cutFV0AmpAVeto) { + return false; + } + registry.fill(HIST("debug/hEventCounter"), 11.); + } + + /* direct FT0 timing cuts */ + if (useFT0TimeCut) { + const float tA = collision.timeFT0A(); + const float tC = collision.timeFT0C(); + + if (abs(tA) > cutFT0TimeA) { + return false; + } + if (abs(tC) > cutFT0TimeC) { + return false; + } + registry.fill(HIST("debug/hEventCounter"), 12.); + } + + int gapSide = 0; // Veto on A-side for now. + if (applyGapSideZDCVeto) { + if (gapSide == 0) { // gap-A + if (!isZeroNeutronA(collision)) { + return false; + } + } else if (gapSide == 1) { // gap-C + if (!isZeroNeutronC(collision)) { + return false; + } + } + registry.fill(HIST("debug/hEventCounter"), 13.); + } + + /* + if (applyGapSideZDCVeto) { + if (!isZeroNeutronA(collision) || !isZeroNeutronC(collision)) { + return false; + } + registry.fill(HIST("debug/hEventCounter"), 13.); + } + */ + return true; + } + + void init(InitContext&) + { + ft0Det.calculateChannelCenter(); + + LOGF(info, "UpcTestFITBitMapping initialized. whichThr=%d", static_cast(whichThr)); + + LOGF(info, "=== FT0A geometry dump ==="); + for (int ch = 0; ch < udhelpers::kFT0AChannels; ++ch) { + auto pos = ft0Det.getChannelCenter(ch); + + const double x = pos.X(); + const double y = pos.Y(); + const double z = pos.Z(); + + const double phi = RecoDecay::phi(x, y); + const double r = std::sqrt(x * x + y * y); + const double theta = std::atan2(r, z); + const double eta = -std::log(std::tan(0.5 * theta)); + + LOGF(info, "FT0A ch=%3d x=%+8.4f y=%+8.4f z=%+8.4f phi=%+8.4f eta=%+8.4f", + ch, x, y, z, phi, eta); + } + + LOGF(info, "=== FT0C geometry dump ==="); + for (int ch = udhelpers::kFT0AChannels; ch < udhelpers::kFT0Bits; ++ch) { + auto pos = ft0Det.getChannelCenter(ch); + + const double x = pos.X(); + const double y = pos.Y(); + const double z = pos.Z(); + + const double phi = RecoDecay::phi(x, y); + const double r = std::sqrt(x * x + y * y); + const double theta = std::atan2(r, z); + const double eta = -std::log(std::tan(0.5 * theta)); + + LOGF(info, "FT0C ch=%3d x=%+8.4f y=%+8.4f z=%+8.4f phi=%+8.4f eta=%+8.4f", + ch, x, y, z, phi, eta); + } + + LOGF(info, "=== end of FT0 geometry dump ==="); + } + + void process(UDCollisionsFull::iterator const& collision, aod::UDCollisionFITBits const& fitBits) + { + if (maxEvents >= 0 && collision.globalIndex() >= maxEvents) { + return; + } + + registry.fill(HIST("debug/hEventCounter"), 0.); + registry.fill(HIST("debug/hFitBitsSize"), fitBits.size()); + registry.fill(HIST("debug/hCollisionIndexMod"), collision.globalIndex() % 100); + + if (fitBits.size() == 0) { + if (collision.globalIndex() < debugPrintFirst || + (debugPrintEvery > 0 && collision.globalIndex() % debugPrintEvery == 0)) { + LOGF(info, "collision %d: fitBits.size() = 0", collision.globalIndex()); + } + registry.fill(HIST("debug/hEventCounter"), 1.); + return; + + } else if (fitBits.size() == 1) { + LOGF(debug, "collision %d: fitBits.size() = %d , as it should be", collision.globalIndex(), fitBits.size()); + registry.fill(HIST("debug/hEventCounter"), 2.); + + } else { // > 1 case + if (collision.globalIndex() < debugPrintFirst || + (debugPrintEvery > 0 && collision.globalIndex() % debugPrintEvery == 0)) { + LOGF(warn, "collision %d: fitBits.size() = %d (expected 0 or 1)", collision.globalIndex(), fitBits.size()); + } + registry.fill(HIST("debug/hEventCounter"), 3.); + return; + } + + const float ft0TimeA = collision.timeFT0A(); + const float ft0TimeC = collision.timeFT0C(); + const float ft0AmpA = collision.totalFT0AmplitudeA(); + const float ft0AmpC = collision.totalFT0AmplitudeC(); + + registry.fill(HIST("qaBeforeCuts/hFT0AAmplitudeVsTime"), ft0TimeA, ft0AmpA); + registry.fill(HIST("qaBeforeCuts/hFT0CAmplitudeVsTime"), ft0TimeC, ft0AmpC); + registry.fill(HIST("qaBeforeCuts/hZNEnergy"), collision.energyCommonZNA(), collision.energyCommonZNC()); + + /* Checking collision level cuts */ + if (!collisionPassesCuts(collision)) { + return; + } + + /* Only one row per collision is expected. */ + auto row = fitBits.begin(); + + const auto w1 = udhelpers::makeBits256(row.thr1W0(), row.thr1W1(), row.thr1W2(), row.thr1W3()); + const auto w2 = udhelpers::makeBits256(row.thr2W0(), row.thr2W1(), row.thr2W2(), row.thr2W3()); + + const int nFT0A = countParticlesInRange(w1, w2, 0, udhelpers::kFT0AChannels - 1); + const int nFT0C = countParticlesInRange(w1, w2, udhelpers::kFT0AChannels, udhelpers::kFT0Bits - 1); + const int nFV0A = countParticlesInRange(w1, w2, udhelpers::kFT0Bits, udhelpers::kTotalBits - 1); + + registry.fill(HIST("mult/hPnFT0A"), nFT0A); + registry.fill(HIST("mult/hPnFT0C"), nFT0C); + registry.fill(HIST("mult/hPnFV0A"), nFV0A); + registry.fill(HIST("mult/hNfiredA_vs_C"), nFT0A, nFT0C); + + if (collision.globalIndex() < debugPrintFirst || (debugPrintEvery > 0 && collision.globalIndex() % debugPrintEvery == 0)) { + LOGF(info, + "collision %d: fitBits.size=%d nFT0A=%d nFT0C=%d nFV0A=%d", + collision.globalIndex(), fitBits.size(), nFT0A, nFT0C, nFV0A); + } + /// Only print the first 5 entries for debugging purpose + if (collision.globalIndex() < 5) { + for (int bit = 96; bit < 208; ++bit) { + if (udhelpers::testBit(w1, bit)) { + LOGF(info, "ANALYSIS sees one fired bit %d", bit); + } + if (udhelpers::testBit(w2, bit)) { + LOGF(info, "ANALYSIS sees two fired bits %d", bit); + } + } + } + + /// Checking for special event geometry of rho (resonances that decays into 2 tracks, in general) + if (nFT0C == 2) { + for (int bit = 0; bit < udhelpers::kFT0Bits; ++bit) { + if (!udhelpers::testBit(w1, bit)) { + continue; + } + + double phi = 0., eta = 0.; + const bool ok = udhelpers::getPhiEtaFromFitBit(ft0Det, bit, offsetFT0, iRunOffset, phi, eta); + if (!ok) { + continue; + } + + auto pos = ft0Det.getChannelCenter(bit); + + const double x = pos.X() - offsetFT0[iRunOffset].getX(); + const double y = pos.Y() - offsetFT0[iRunOffset].getY(); + + if (bit >= udhelpers::kFT0AChannels) { + registry.fill(HIST("debug/hFT0CChannelOccupancy_2tracks"), bit); + registry.fill(HIST("map/hPhiC_2tracks"), phi); + registry.fill(HIST("map/hEtaC_2tracks"), eta); + registry.fill(HIST("map/hEtaPhiC_2tracks"), eta, phi); + registry.fill(HIST("map/hXYC_2tracks"), x, y); + } + } + } + + if (nFT0C > 2) { + for (int bit = 0; bit < udhelpers::kFT0Bits; ++bit) { + if (!udhelpers::testBit(w1, bit)) { + continue; + } + + double phi = 0., eta = 0.; + const bool ok = udhelpers::getPhiEtaFromFitBit(ft0Det, bit, offsetFT0, iRunOffset, phi, eta); + if (!ok) { + continue; + } + + auto pos = ft0Det.getChannelCenter(bit); + + const double x = pos.X() - offsetFT0[iRunOffset].getX(); + const double y = pos.Y() - offsetFT0[iRunOffset].getY(); + + if (bit >= udhelpers::kFT0AChannels) { + registry.fill(HIST("debug/hFT0CChannelOccupancy_ntracks"), bit); + registry.fill(HIST("map/hPhiC_ntracks"), phi); + registry.fill(HIST("map/hEtaC_ntracks"), eta); + registry.fill(HIST("map/hEtaPhiC_ntracks"), eta, phi); + registry.fill(HIST("map/hXYC_ntracks"), x, y); + } + } + } + + /* Mapping for at least 1 fired channel only */ + for (int bit = 0; bit < udhelpers::kFT0Bits; ++bit) { + if (!udhelpers::testBit(w1, bit)) { + continue; + } + + double phi = 0., eta = 0.; + const bool ok = udhelpers::getPhiEtaFromFitBit(ft0Det, bit, offsetFT0, iRunOffset, phi, eta); + if (!ok) { + continue; + } + + auto pos = ft0Det.getChannelCenter(bit); + + const double x = pos.X() - offsetFT0[iRunOffset].getX(); + const double y = pos.Y() - offsetFT0[iRunOffset].getY(); + + if (bit < udhelpers::kFT0AChannels) { + // LOGF(info,"phi = %.4f, phiBin = %i",phi,phiBin); + registry.fill(HIST("debug/hFT0AChannelOccupancy"), bit); + registry.fill(HIST("map/hPhiA"), phi); + registry.fill(HIST("map/hEtaA"), eta); + registry.fill(HIST("map/hEtaPhiA"), eta, phi); + registry.fill(HIST("map/hXYA"), x, y); + } else { + registry.fill(HIST("debug/hFT0CChannelOccupancy"), bit); + registry.fill(HIST("map/hPhiC"), phi); + registry.fill(HIST("map/hEtaC"), eta); + registry.fill(HIST("map/hEtaPhiC"), eta, phi); + registry.fill(HIST("map/hXYC"), x, y); + } + } + + registry.fill(HIST("debug/hEventCounter"), 4.); + } +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{ + adaptAnalysisTask(cfgc, TaskName{"fitbitmapping"})}; +} diff --git a/PWGUD/Tasks/upcTestFITBitMapping.cxx b/PWGUD/Tasks/upcTestFITBitMapping.cxx new file mode 100644 index 00000000000..91f91e67411 --- /dev/null +++ b/PWGUD/Tasks/upcTestFITBitMapping.cxx @@ -0,0 +1,404 @@ +// 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. +// +// \brief FIT bits to phi, eta mapping + multiplicity from FIT bits +// \author Sandor Lokos, sandor.lokos@cern.ch +// \since March 2026 + +#include "PWGUD/Core/SGSelector.h" +#include "PWGUD/Core/UDHelpers.h" +#include "PWGUD/DataModel/UDTables.h" + +#include "FT0Base/Geometry.h" +#include "Framework/AnalysisTask.h" +#include "Framework/HistogramRegistry.h" +#include "Framework/Logger.h" +#include "Framework/runDataProcessing.h" + +#include +#include +#include + +using namespace o2; +using namespace o2::framework; + +using UDCollisionsFull = soa::Join< + aod::UDCollisions, + aod::UDCollisionsSels, + aod::UDCollisionSelExtras, + aod::UDZdcsReduced>; + +// using UDCollisionsFull = aod::UDCollisions; + +struct UpcTestFITBitMapping { + + SGSelector sgSelector; + + Configurable whichThr{"whichThr", 1, "Use 1=Thr1 bits or 2=Thr2 bits"}; + Configurable maxEvents{"maxEvents", -1, "Process at most this many collisions (-1 = all)"}; + Configurable debugPrintEvery{"debugPrintEvery", 1000, "Print every N events (-1 disables)"}; + Configurable debugPrintFirst{"debugPrintFirst", 10, "Always print first N events"}; + Configurable useRctFlag{"useRctFlag", true, "use RCT flags for event selection"}; + Configurable cutRctFlag{"cutRctFlag", 2, "0 = off, 1 = CBT, 2 = CBT+ZDC, 3 = CBThadron, 4 = CBThadron+ZDC"}; + + Configurable applyGapSideZDCVeto{"applyGapSideZDCVeto", true, "Apply ZDC neutron veto on the gap side"}; + Configurable cutZNAnoNeutron{"cutZNAnoNeutron", 1.f, "Maximum allowed ZNA energy for zero-neutron condition"}; + Configurable cutZNCnoNeutron{"cutZNCnoNeutron", 1.f, "Maximum allowed ZNC energy for zero-neutron condition"}; + + Configurable useFT0TimeCut{"useFT0TimeCut", true, "Apply direct FT0 timing cut"}; + Configurable cutFT0TimeA{"cutFT0TimeA", 2., "FT0-A time cut [ns]"}; + Configurable cutFT0TimeC{"cutFT0TimeC", 2., "FT0-C time cut [ns]"}; + + Configurable useFT0AVeto{"useFT0AVeto", true, "Apply FT0-A total amplitude veto"}; + Configurable cutFT0AmpAVeto{"cutFT0AmpAVeto", 100., "Maximum allowed FT0-A total amplitude for veto"}; + + Configurable useFV0AVeto{"useFV0AVeto", true, "Apply FV0-A total amplitude veto"}; + Configurable cutFV0AmpAVeto{"cutFV0AmpAVeto", 50., "Maximum allowed FV0-A total amplitude for veto"}; + + struct OffsetXYZ { + double x{0.}, y{0.}, z{0.}; + double getX() const { return x; } + double getY() const { return y; } + double getZ() const { return z; } + }; + + std::array offsetFT0{}; + int iRunOffset = 0; + + o2::ft0::Geometry ft0Det{}; + + HistogramRegistry registry{ + "registry", + {{"debug/hEventCounter", "Event counter;step;events", {HistType::kTH1F, {{20, -0.5, 19.5}}}}, + {"debug/hFitBitsSize", "fitBits.size() per collision;fitBits.size();events", {HistType::kTH1F, {{10, -0.5, 9.5}}}}, + {"debug/hCollisionIndexMod", "Collision index mod 100;collision.globalIndex() % 100;events", {HistType::kTH1F, {{100, -0.5, 99.5}}}}, + {"debug/hFT0AChannelOccupancy", "FT0A fired channel occupancy;FT0A channel;counts", {HistType::kTH1F, {{97, -0.5, 96.5}}}}, + {"debug/hFT0CChannelOccupancy", "FT0C fired channel occupancy;FT0C channel;counts", {HistType::kTH1F, {{112, 95.5, 207.5}}}}, + + {"map/hPhiA", "FT0A #varphi;#varphi;counts", {HistType::kTH1F, {{9, 0, 2 * M_PI}}}}, + {"map/hEtaA", "FT0A #eta;#eta;counts", {HistType::kTH1F, {{7, 3.4, 4.8}}}}, + {"map/hEtaPhiA", "FT0A #eta vs #varphi;#eta;#varphi", {HistType::kTH2F, {{7, 3.4, 4.8}, {9, 0, 2 * M_PI}}}}, + + {"map/hPhiC", "FT0C #varphi;#varphi;counts", {HistType::kTH1F, {{9, 0, 2 * M_PI}}}}, + {"map/hEtaC", "FT0C #eta;#eta;counts", {HistType::kTH1F, {{5, -3.1, -2.1}}}}, + {"map/hEtaPhiC", "FT0C #eta vs #varphi;#eta;#varphi", {HistType::kTH2F, {{5, -3.1, -2.1}, {9, 0, 2 * M_PI}}}}, + + {"mult/hPnFT0A", "P(n): FT0A fired-channel multiplicity;N_{fired}^{FT0A};events", {HistType::kTH1F, {{97, -0.5, 96.5}}}}, + {"mult/hPnFT0C", "P(n): FT0C fired-channel multiplicity;N_{fired}^{FT0C};events", {HistType::kTH1F, {{50, -0.5, 49.5}}}}, + {"mult/hPnFV0A", "P(n): FV0A fired-channel multiplicity;N_{fired}^{FV0A};events", {HistType::kTH1F, {{49, -0.5, 48.5}}}}, + + {"mult/hNfiredA_vs_C", "FT0A vs FT0C fired channels;N_{fired}^{FT0A};N_{fired}^{FT0C}", {HistType::kTH2F, {{97, -0.5, 96.5}, {113, -0.5, 112.5}}}}, + + {"qaBeforeCuts/hFT0AAmplitudeVsTime", "FT0A amplitude vs time before cuts;FT0A time (ns);FT0A total amplitude", {HistType::kTH2F, {{200, -40., 40.}, {300, 0., 3000.}}}}, + {"qaBeforeCuts/hFT0CAmplitudeVsTime", "FT0C amplitude vs time before cuts;FT0C time (ns);FT0C total amplitude", {HistType::kTH2F, {{200, -40., 40.}, {300, 0., 3000.}}}}, + + {"map/hXYA", "FT0A fired channels in x-y;x [cm];y [cm]", {HistType::kTH2F, {{12, -18., 18.}, {12, -18., 18.}}}}, + {"map/hXYC", "FT0C fired channels in x-y;x [cm];y [cm]", {HistType::kTH2F, {{12, -18., 18.}, {12, -18., 18.}}}}}}; + + int countParticlesInRange(udhelpers::Bits256 const& thr1, udhelpers::Bits256 const& thr2, int first, int last) + { + int n = 0; + for (int bit = first; bit <= last; ++bit) { + const bool aboveThr1 = udhelpers::testBit(thr1, bit); + const bool aboveThr2 = udhelpers::testBit(thr2, bit); + + if (aboveThr2) { + n += 2; + } else if (aboveThr1) { + n += 1; + } + } + return n; + } + + template + bool isGoodRctFlag(const C& collision) + { + switch (cutRctFlag) { + case 1: // CBT + return sgSelector.isCBTOk(collision); + case 2: // CBT + ZDC + return sgSelector.isCBTZdcOk(collision); + case 3: // CBT hadron + return sgSelector.isCBTHadronOk(collision); + case 4: // CBT hadron + ZDC + return sgSelector.isCBTHadronZdcOk(collision); + default: // no RCT cut applied + return true; + } + } + + template + bool isZeroNeutronA(const C& collision) + { + const float eZNA = collision.energyCommonZNA(); // exact accessor to be checked + return eZNA <= cutZNAnoNeutron; + } + + template + bool isZeroNeutronC(const C& collision) + { + const float eZNC = collision.energyCommonZNC(); // exact accessor to be checked + return eZNC <= cutZNCnoNeutron; + } + + template + bool collisionPassesCuts(const C& collision) + { + /* good vertex */ + if (!collision.vtxITSTPC()) { + return false; + } + registry.fill(HIST("debug/hEventCounter"), 4.); + + /* same bunch pile-up rejection */ + if (!collision.sbp()) { + return false; + } + registry.fill(HIST("debug/hEventCounter"), 5.); + + /* ITS ROF rejection */ + if (!collision.itsROFb()) { + return false; + } + registry.fill(HIST("debug/hEventCounter"), 6.); + + /* Timeframe border collision rejection */ + if (!collision.tfb()) { + return false; + } + registry.fill(HIST("debug/hEventCounter"), 7.); + + /* z-vertex cut */ + if (std::abs(collision.posZ()) > 10.0) { + return false; + } + registry.fill(HIST("debug/hEventCounter"), 8.); + + /* RCT flag check*/ + if (useRctFlag) { + if (!isGoodRctFlag(collision)) { + return false; + } + registry.fill(HIST("debug/hEventCounter"), 9.); // passed RCT flag + } + + /* FT0-A veto on total amplitude */ + if (useFT0AVeto) { + const float ampA = collision.totalFT0AmplitudeA(); + if (ampA > cutFT0AmpAVeto) { + return false; + } + registry.fill(HIST("debug/hEventCounter"), 10.); + } + + /* FV0-A veto on total amplitude */ + if (useFV0AVeto) { + const float ampA = collision.totalFV0AmplitudeA(); + if (ampA > cutFV0AmpAVeto) { + return false; + } + registry.fill(HIST("debug/hEventCounter"), 11.); + } + + /* direct FT0 timing cuts */ + if (useFT0TimeCut) { + const float tA = collision.timeFT0A(); + const float tC = collision.timeFT0C(); + + if (abs(tA) > cutFT0TimeA) { + return false; + } + if (abs(tC) > cutFT0TimeC) { + return false; + } + registry.fill(HIST("debug/hEventCounter"), 12.); + } + + /* + int gapSide = 0 ; // Veto on A-side for now. + if (applyGapSideZDCVeto) { + if (gapSide == 0) { // gap-A + if (!isZeroNeutronA(collision)) { + return false; + } + } else if (gapSide == 1) { // gap-C + if (!isZeroNeutronC(collision)) { + return false; + } + } + registry.fill(HIST("debug/hEventCounter"), 13.); + } + */ + + if (applyGapSideZDCVeto) { + if (!isZeroNeutronA(collision) || !isZeroNeutronC(collision)) { + return false; + } + registry.fill(HIST("debug/hEventCounter"), 13.); + } + + return true; + } + + void init(InitContext&) + { + ft0Det.calculateChannelCenter(); + + LOGF(info, "UpcTestFITBitMapping initialized. whichThr=%d", static_cast(whichThr)); + + LOGF(info, "=== FT0A geometry dump ==="); + for (int ch = 0; ch < udhelpers::kFT0AChannels; ++ch) { + auto pos = ft0Det.getChannelCenter(ch); + + const double x = pos.X(); + const double y = pos.Y(); + const double z = pos.Z(); + + const double phi = RecoDecay::phi(x, y); + const double r = std::sqrt(x * x + y * y); + const double theta = std::atan2(r, z); + const double eta = -std::log(std::tan(0.5 * theta)); + + LOGF(info, "FT0A ch=%3d x=%+8.4f y=%+8.4f z=%+8.4f phi=%+8.4f eta=%+8.4f", + ch, x, y, z, phi, eta); + } + + LOGF(info, "=== FT0C geometry dump ==="); + for (int ch = udhelpers::kFT0AChannels; ch < udhelpers::kFT0Bits; ++ch) { + auto pos = ft0Det.getChannelCenter(ch); + + const double x = pos.X(); + const double y = pos.Y(); + const double z = pos.Z(); + + const double phi = RecoDecay::phi(x, y); + const double r = std::sqrt(x * x + y * y); + const double theta = std::atan2(r, z); + const double eta = -std::log(std::tan(0.5 * theta)); + + LOGF(info, "FT0C ch=%3d x=%+8.4f y=%+8.4f z=%+8.4f phi=%+8.4f eta=%+8.4f", + ch, x, y, z, phi, eta); + } + + LOGF(info, "=== end of FT0 geometry dump ==="); + } + + void process(UDCollisionsFull::iterator const& collision, aod::UDCollisionFITBits const& fitBits) + { + if (maxEvents >= 0 && collision.globalIndex() >= maxEvents) { + return; + } + + registry.fill(HIST("debug/hEventCounter"), 0.); + registry.fill(HIST("debug/hFitBitsSize"), fitBits.size()); + registry.fill(HIST("debug/hCollisionIndexMod"), collision.globalIndex() % 100); + + if (fitBits.size() == 0) { + if (collision.globalIndex() < debugPrintFirst || + (debugPrintEvery > 0 && collision.globalIndex() % debugPrintEvery == 0)) { + LOGF(info, "collision %d: fitBits.size() = 0", collision.globalIndex()); + } + registry.fill(HIST("debug/hEventCounter"), 1.); + return; + + } else if (fitBits.size() == 1) { + LOGF(debug, "collision %d: fitBits.size() = %d , as it should be", collision.globalIndex(), fitBits.size()); + registry.fill(HIST("debug/hEventCounter"), 2.); + + } else { // > 1 case + if (collision.globalIndex() < debugPrintFirst || + (debugPrintEvery > 0 && collision.globalIndex() % debugPrintEvery == 0)) { + LOGF(warn, "collision %d: fitBits.size() = %d (expected 0 or 1)", collision.globalIndex(), fitBits.size()); + } + registry.fill(HIST("debug/hEventCounter"), 3.); + return; + } + + /* Checking collision level cuts */ + if (!collisionPassesCuts(collision)) { + return; + } + + /* Only one row per collision is expected. */ + auto row = fitBits.begin(); + + const auto w1 = udhelpers::makeBits256(row.thr1W0(), row.thr1W1(), row.thr1W2(), row.thr1W3()); + const auto w2 = udhelpers::makeBits256(row.thr2W0(), row.thr2W1(), row.thr2W2(), row.thr2W3()); + + const int nFT0A = countParticlesInRange(w1, w2, 0, udhelpers::kFT0AChannels - 1); + const int nFT0C = countParticlesInRange(w1, w2, udhelpers::kFT0AChannels, udhelpers::kFT0Bits - 1); + const int nFV0A = countParticlesInRange(w1, w2, udhelpers::kFT0Bits, udhelpers::kTotalBits - 1); + + registry.fill(HIST("mult/hPnFT0A"), nFT0A); + registry.fill(HIST("mult/hPnFT0C"), nFT0C); + registry.fill(HIST("mult/hPnFV0A"), nFV0A); + registry.fill(HIST("mult/hNfiredA_vs_C"), nFT0A, nFT0C); + + if (collision.globalIndex() < debugPrintFirst || + (debugPrintEvery > 0 && collision.globalIndex() % debugPrintEvery == 0)) { + LOGF(info, + "collision %d: fitBits.size=%d nFT0A=%d nFT0C=%d nFV0A=%d", + collision.globalIndex(), fitBits.size(), nFT0A, nFT0C, nFV0A); + } + if (collision.globalIndex() < 5) { + for (int bit = 96; bit < 208; ++bit) { + if (udhelpers::testBit(w1, bit)) { + LOGF(info, "ANALYSIS sees one fired bit %d", bit); + } + if (udhelpers::testBit(w2, bit)) { + LOGF(info, "ANALYSIS sees two fired bits %d", bit); + } + } + } + + /* Mapping for at least 1 fired channel only */ + for (int bit = 0; bit < udhelpers::kFT0Bits; ++bit) { + if (!udhelpers::testBit(w1, bit)) { + continue; + } + + double phi = 0., eta = 0.; + const bool ok = udhelpers::getPhiEtaFromFitBit(ft0Det, bit, offsetFT0, iRunOffset, phi, eta); + if (!ok) { + continue; + } + + auto pos = ft0Det.getChannelCenter(bit); + + const double x = pos.X() - offsetFT0[iRunOffset].getX(); + const double y = pos.Y() - offsetFT0[iRunOffset].getY(); + + if (bit < udhelpers::kFT0AChannels) { + // LOGF(info,"phi = %.4f, phiBin = %i",phi,phiBin); + registry.fill(HIST("debug/hFT0AChannelOccupancy"), bit); + registry.fill(HIST("map/hPhiA"), phi); + registry.fill(HIST("map/hEtaA"), eta); + registry.fill(HIST("map/hEtaPhiA"), eta, phi); + registry.fill(HIST("map/hXYA"), x, y); + } else { + registry.fill(HIST("debug/hFT0CChannelOccupancy"), bit); + registry.fill(HIST("map/hPhiC"), phi); + registry.fill(HIST("map/hEtaC"), eta); + registry.fill(HIST("map/hEtaPhiC"), eta, phi); + registry.fill(HIST("map/hXYC"), x, y); + } + } + + registry.fill(HIST("debug/hEventCounter"), 4.); + } +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{ + adaptAnalysisTask(cfgc, TaskName{"fitbitmapping"})}; +}