Skip to content

Commit 487bdb1

Browse files
[PWGUD] Fit bit implementation (#15510)
Co-authored-by: amatyja <adam.tomasz.matyja@cern.ch>
1 parent 7814a61 commit 487bdb1

File tree

11 files changed

+499
-85
lines changed

11 files changed

+499
-85
lines changed

PWGUD/Core/CMakeLists.txt

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,3 +64,11 @@ o2physics_add_library(decayTree
6464
o2physics_target_root_dictionary(decayTree
6565
HEADERS decayTree.h
6666
LINKDEF decayTreeLinkDef.h)
67+
68+
o2physics_add_library(FITCutParHolder
69+
SOURCES FITCutParHolder.cxx
70+
PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore)
71+
72+
o2physics_target_root_dictionary(FITCutParHolder
73+
HEADERS FITCutParHolder.h
74+
LINKDEF FITCutParHolderLinkDef.h)

PWGUD/Core/FITCutParHolder.cxx

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
// Copyright 2019-2020 CERN and copyright holders of ALICE O2.
2+
// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders.
3+
// All rights not expressly granted are reserved.
4+
//
5+
// This software is distributed under the terms of the GNU General Public
6+
// License v3 (GPL Version 3), copied verbatim in the file "COPYING".
7+
//
8+
// In applying this license CERN does not waive the privileges and immunities
9+
// granted to it by virtue of its status as an Intergovernmental Organization
10+
// or submit itself to any jurisdiction.
11+
//
12+
// \FIT bit thresholds
13+
// \author Sandor Lokos, sandor.lokos@cern.ch
14+
// \since March 2026
15+
16+
#include "FITCutParHolder.h"
17+
18+
// setter
19+
void FITCutParHolder::SetSaveFITbitsets(bool saveFITbitsets)
20+
{
21+
mSaveFITbitsets = saveFITbitsets;
22+
}
23+
void FITCutParHolder::SetThr1FV0A(float thr1_FV0A)
24+
{
25+
mThr1FV0A = thr1_FV0A;
26+
}
27+
void FITCutParHolder::SetThr1FT0A(float thr1_FT0A)
28+
{
29+
mThr1FT0A = thr1_FT0A;
30+
}
31+
void FITCutParHolder::SetThr1FT0C(float thr1_FT0C)
32+
{
33+
mThr1FT0C = thr1_FT0C;
34+
}
35+
void FITCutParHolder::SetThr2FV0A(float thr2_FV0A)
36+
{
37+
mThr2FV0A = thr2_FV0A;
38+
}
39+
void FITCutParHolder::SetThr2FT0A(float thr2_FT0A)
40+
{
41+
mThr2FT0A = thr2_FT0A;
42+
}
43+
void FITCutParHolder::SetThr2FT0C(float thr2_FT0C)
44+
{
45+
mThr2FT0C = thr2_FT0C;
46+
}
47+
48+
// getter
49+
bool FITCutParHolder::saveFITbitsets() const { return mSaveFITbitsets; }
50+
float FITCutParHolder::thr1_FV0A() const { return mThr1FV0A; }
51+
float FITCutParHolder::thr1_FT0A() const { return mThr1FT0A; }
52+
float FITCutParHolder::thr1_FT0C() const { return mThr1FT0C; }
53+
float FITCutParHolder::thr2_FV0A() const { return mThr2FV0A; }
54+
float FITCutParHolder::thr2_FT0A() const { return mThr2FT0A; }
55+
float FITCutParHolder::thr2_FT0C() const { return mThr2FT0C; }

PWGUD/Core/FITCutParHolder.h

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
// Copyright 2019-2020 CERN and copyright holders of ALICE O2.
2+
// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders.
3+
// All rights not expressly granted are reserved.
4+
//
5+
// This software is distributed under the terms of the GNU General Public
6+
// License v3 (GPL Version 3), copied verbatim in the file "COPYING".
7+
//
8+
// In applying this license CERN does not waive the privileges and immunities
9+
// granted to it by virtue of its status as an Intergovernmental Organization
10+
// or submit itself to any jurisdiction.
11+
//
12+
// \FIT bit thresholds
13+
// \author Sandor Lokos, sandor.lokos@cern.ch
14+
// \since March 2026
15+
16+
#ifndef PWGUD_CORE_FITCUTPARHOLDER_H_
17+
#define PWGUD_CORE_FITCUTPARHOLDER_H_
18+
19+
#include <Rtypes.h>
20+
21+
// object to hold customizable FIT bit thresholds
22+
class FITCutParHolder
23+
{
24+
public:
25+
// constructor
26+
FITCutParHolder(bool saveFITbitsets = true,
27+
float thr1_FV0A = 8.,
28+
float thr1_FT0A = 8.,
29+
float thr1_FT0C = 8.,
30+
float thr2_FV0A = 20.,
31+
float thr2_FT0A = 20.,
32+
float thr2_FT0C = 20.)
33+
: mSaveFITbitsets{saveFITbitsets},
34+
mThr1FV0A{thr1_FV0A},
35+
mThr1FT0A{thr1_FT0A},
36+
mThr1FT0C{thr1_FT0C},
37+
mThr2FV0A{thr2_FV0A},
38+
mThr2FT0A{thr2_FT0A},
39+
mThr2FT0C{thr2_FT0C}
40+
{
41+
}
42+
43+
// setters
44+
void SetSaveFITbitsets(bool);
45+
void SetThr1FV0A(float);
46+
void SetThr1FT0A(float);
47+
void SetThr1FT0C(float);
48+
void SetThr2FV0A(float);
49+
void SetThr2FT0A(float);
50+
void SetThr2FT0C(float);
51+
52+
// getters
53+
bool saveFITbitsets() const;
54+
float thr1_FV0A() const;
55+
float thr1_FT0A() const;
56+
float thr1_FT0C() const;
57+
float thr2_FV0A() const;
58+
float thr2_FT0A() const;
59+
float thr2_FT0C() const;
60+
61+
private:
62+
bool mSaveFITbitsets;
63+
64+
float mThr1FV0A;
65+
float mThr1FT0A;
66+
float mThr1FT0C;
67+
68+
float mThr2FV0A;
69+
float mThr2FT0A;
70+
float mThr2FT0C;
71+
72+
ClassDefNV(FITCutParHolder, 1);
73+
};
74+
75+
#endif // PWGUD_CORE_FITCUTPARHOLDER_H_
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
// Copyright 2019-2020 CERN and copyright holders of ALICE O2.
2+
// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders.
3+
// All rights not expressly granted are reserved.
4+
//
5+
// This software is distributed under the terms of the GNU General Public
6+
// License v3 (GPL Version 3), copied verbatim in the file "COPYING".
7+
//
8+
// In applying this license CERN does not waive the privileges and immunities
9+
// granted to it by virtue of its status as an Intergovernmental Organization
10+
// or submit itself to any jurisdiction.
11+
//
12+
// \FIT bit thresholds
13+
// \author Sandor Lokos, sandor.lokos@cern.ch
14+
// \since March 2026
15+
16+
#ifndef PWGUD_CORE_FITCUTPARHOLDERLINKDEF_H_
17+
#define PWGUD_CORE_FITCUTPARHOLDERLINKDEF_H_
18+
19+
#pragma link off all globals;
20+
#pragma link off all classes;
21+
#pragma link off all functions;
22+
#pragma link C++ class FITCutParHolder + ;
23+
24+
#endif // PWGUD_CORE_FITCUTPARHOLDERLINKDEF_H_

PWGUD/Core/SGCutParHolderLinkDef.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
// In applying this license CERN does not waive the privileges and immunities
99
// granted to it by virtue of its status as an Intergovernmental Organization
1010
// or submit itself to any jurisdiction.
11+
1112
#ifndef PWGUD_CORE_SGCUTPARHOLDERLINKDEF_H_
1213
#define PWGUD_CORE_SGCUTPARHOLDERLINKDEF_H_
1314

PWGUD/Core/UDHelpers.h

Lines changed: 156 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
#include "PWGUD/Core/DGCutparHolder.h"
2020
#include "PWGUD/Core/UPCHelpers.h"
2121

22+
#include "Common/Core/RecoDecay.h"
2223
#include "Common/DataModel/EventSelection.h"
2324
#include "Common/DataModel/TrackSelectionTables.h"
2425

@@ -29,6 +30,7 @@
2930

3031
#include "TLorentzVector.h"
3132

33+
#include <algorithm>
3234
#include <bitset>
3335
#include <vector>
3436

@@ -533,6 +535,160 @@ bool FITveto(T const& bc, DGCutparHolder const& diffCuts)
533535
return false;
534536
}
535537

538+
inline void setBit(uint64_t w[4], int bit, bool val)
539+
{
540+
if (!val) {
541+
return;
542+
}
543+
const int word = bit >> 6;
544+
const int offs = bit & 63;
545+
w[word] |= (static_cast<uint64_t>(1) << offs);
546+
}
547+
548+
template <typename TFT0, typename TFV0A>
549+
inline void buildFT0FV0Words(TFT0 const& ft0, TFV0A const& fv0a,
550+
uint64_t thr1[4], uint64_t thr2[4],
551+
float thr1_FT0A = 25., float thr1_FT0C = 50., float thr1_FV0A = 50.,
552+
float thr2_FT0A = 50., float thr2_FT0C = 100., float thr2_FV0A = 100.)
553+
{
554+
thr1[0] = thr1[1] = thr1[2] = thr1[3] = 0ull;
555+
thr2[0] = thr2[1] = thr2[2] = thr2[3] = 0ull;
556+
557+
constexpr int kFT0AOffset = 0;
558+
constexpr int kFT0COffset = 96;
559+
constexpr int kFV0Offset = 208;
560+
561+
auto ampsA = ft0.amplitudeA();
562+
const int nA = std::min<int>(ampsA.size(), 96);
563+
for (int i = 0; i < nA; ++i) {
564+
const auto a = ampsA[i];
565+
setBit(thr1, kFT0AOffset + i, a >= thr1_FT0A);
566+
setBit(thr2, kFT0AOffset + i, a >= thr2_FT0A);
567+
}
568+
569+
auto ampsC = ft0.amplitudeC();
570+
const int nC = std::min<int>(ampsC.size(), 112);
571+
for (int i = 0; i < nC; ++i) {
572+
const auto a = ampsC[i];
573+
setBit(thr1, kFT0COffset + i, a >= thr1_FT0C);
574+
setBit(thr2, kFT0COffset + i, a >= thr2_FT0C);
575+
}
576+
577+
auto ampsV = fv0a.amplitude();
578+
const int nV = std::min<int>(ampsV.size(), 48);
579+
for (int i = 0; i < nV; ++i) {
580+
const auto a = ampsV[i];
581+
setBit(thr1, kFV0Offset + i, a >= thr1_FV0A);
582+
setBit(thr2, kFV0Offset + i, a >= thr2_FV0A);
583+
}
584+
}
585+
586+
// -----------------------------------------------------------------------------
587+
// return eta and phi of a given FIT channel based on the bitset
588+
// Bit layout contract:
589+
constexpr int kFT0Bits = 208; // FT0 total channels
590+
constexpr int kFV0Bits = 48; // FV0A channels
591+
constexpr int kTotalBits = 256; // 4*64
592+
593+
// FT0 side split
594+
constexpr int kFT0AChannels = 96; // FT0A channels are [0..95]
595+
constexpr int kFT0CChannels = 112; // FT0C channels are [96..207]
596+
static_assert(kFT0AChannels + kFT0CChannels == kFT0Bits);
597+
598+
using Bits256 = std::array<uint64_t, 4>;
599+
600+
inline Bits256 makeBits256(uint64_t w0, uint64_t w1, uint64_t w2, uint64_t w3)
601+
{
602+
return {w0, w1, w2, w3};
603+
}
604+
605+
inline bool testBit(Bits256 const& w, int bit)
606+
{
607+
if (bit < 0 || bit >= kTotalBits) {
608+
return false;
609+
}
610+
return (w[bit >> 6] >> (bit & 63)) & 1ULL;
611+
}
612+
613+
struct FitBitRef {
614+
enum class Det : uint8_t { FT0,
615+
FV0,
616+
Unknown };
617+
Det det = Det::Unknown;
618+
int ch = -1; // FT0: 0..207, FV0: 0..47
619+
bool isC = false; // only meaningful for FT0
620+
};
621+
622+
inline FitBitRef decodeFitBit(int bit)
623+
{
624+
FitBitRef out;
625+
if (bit >= 0 && bit < kFT0Bits) {
626+
out.det = FitBitRef::Det::FT0;
627+
out.ch = bit; // FT0 channel id
628+
out.isC = (bit >= kFT0AChannels); // C side if in upper range
629+
return out;
630+
}
631+
if (bit >= kFT0Bits && bit < kTotalBits) {
632+
out.det = FitBitRef::Det::FV0;
633+
out.ch = bit - kFT0Bits; // FV0A channel id 0..47
634+
return out;
635+
}
636+
return out;
637+
}
638+
639+
template <typename FT0DetT, typename OffsetsT>
640+
inline double getPhiFT0_fromChannel(FT0DetT& ft0Det, int ft0Ch, OffsetsT const& offsetFT0, int i)
641+
{
642+
ft0Det.calculateChannelCenter();
643+
auto chPos = ft0Det.getChannelCenter(ft0Ch);
644+
645+
const double x = chPos.X() + offsetFT0[i].getX();
646+
const double y = chPos.Y() + offsetFT0[i].getY();
647+
648+
return RecoDecay::phi(x, y);
649+
}
650+
651+
template <typename FT0DetT, typename OffsetsT>
652+
inline double getEtaFT0_fromChannel(FT0DetT& ft0Det, int ft0Ch, OffsetsT const& offsetFT0, int i)
653+
{
654+
ft0Det.calculateChannelCenter();
655+
auto chPos = ft0Det.getChannelCenter(ft0Ch);
656+
657+
double x = chPos.X() + offsetFT0[i].getX();
658+
double y = chPos.Y() + offsetFT0[i].getY();
659+
double z = chPos.Z() + offsetFT0[i].getZ();
660+
661+
// If this channel belongs to FT0C, flip z (matches your original intent)
662+
const bool isC = (ft0Ch >= kFT0AChannels);
663+
if (isC) {
664+
z = -z;
665+
}
666+
667+
const double r = std::sqrt(x * x + y * y);
668+
const double theta = std::atan2(r, z);
669+
return -std::log(std::tan(0.5 * theta));
670+
}
671+
672+
template <typename FT0DetT, typename OffsetsT>
673+
inline bool getPhiEtaFromFitBit(FT0DetT& ft0Det,
674+
int bit,
675+
OffsetsT const& offsetFT0,
676+
int iRunOffset,
677+
double& phi,
678+
double& eta)
679+
{
680+
auto ref = decodeFitBit(bit);
681+
if (ref.det != FitBitRef::Det::FT0) {
682+
return false;
683+
}
684+
685+
// FT0A: 0..95, FT0C: 96..207
686+
const int ft0Ch = bit;
687+
phi = getPhiFT0_fromChannel(ft0Det, ft0Ch, offsetFT0, iRunOffset);
688+
eta = getEtaFT0_fromChannel(ft0Det, ft0Ch, offsetFT0, iRunOffset);
689+
return true;
690+
}
691+
536692
// -----------------------------------------------------------------------------
537693

538694
template <typename T>

PWGUD/DataModel/UDTables.h

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -407,6 +407,31 @@ DECLARE_SOA_TABLE(UDTracksFlags, "AOD", "UDTRACKFLAG",
407407
DECLARE_SOA_TABLE(UDTracksLabels, "AOD", "UDTRACKLABEL",
408408
udtrack::TrackId);
409409

410+
namespace udcollfitbits
411+
{
412+
DECLARE_SOA_COLUMN(Thr1W0, thr1W0, uint64_t); /// 1 MIP thresholds for FT0A ch 0 - ch 63
413+
DECLARE_SOA_COLUMN(Thr1W1, thr1W1, uint64_t); /// 1 MIP thresholds for FT0A ch 64 - ch 96 & FT0C ch 0 - ch 31
414+
DECLARE_SOA_COLUMN(Thr1W2, thr1W2, uint64_t); /// 1 MIP thresholds for FT0C ch 32 - ch 96
415+
DECLARE_SOA_COLUMN(Thr1W3, thr1W3, uint64_t); /// 1 MIP thresholds for FT0C ch 97 - 112 & FV0 0 - 47
416+
417+
DECLARE_SOA_COLUMN(Thr2W0, thr2W0, uint64_t); /// 2 MIP thresholds for FT0A ch 0 - ch 63
418+
DECLARE_SOA_COLUMN(Thr2W1, thr2W1, uint64_t); /// 2 MIP thresholds for FT0A ch 63 - ch 96 & FT0C ch 0 - ch 31
419+
DECLARE_SOA_COLUMN(Thr2W2, thr2W2, uint64_t); /// 2 MIP thresholds for FT0C ch 32 - ch 96
420+
DECLARE_SOA_COLUMN(Thr2W3, thr2W3, uint64_t); /// 2 MIP thresholds for FT0C ch 97 - 112 & FV0 0 - 47
421+
} // namespace udcollfitbits
422+
423+
DECLARE_SOA_TABLE(UDCollisionFITBits, "AOD", "UDCOLLFITBITS",
424+
o2::soa::Index<>,
425+
udcollfitbits::Thr1W0, /// 1 MIP thresholds for FT0A ch 0 - ch 63
426+
udcollfitbits::Thr1W1, /// 1 MIP thresholds for FT0A ch 63 - ch 96 & FT0C ch 0 - ch 31
427+
udcollfitbits::Thr1W2, /// 1 MIP thresholds for FT0C ch 32 - ch 96
428+
udcollfitbits::Thr1W3, /// 1 MIP thresholds for FT0C ch 97 - 112 & FV0 0 - 47
429+
udcollfitbits::Thr2W0, /// 2 MIP thresholds for FT0A ch 0 - ch 63
430+
udcollfitbits::Thr2W1, /// 2 MIP thresholds for FT0A ch 63 - ch 96 & FT0C ch 0 - ch 31
431+
udcollfitbits::Thr2W2, /// 2 MIP thresholds for FT0C ch 32 - ch 96
432+
udcollfitbits::Thr2W3 /// 2 MIP thresholds for FT0C ch 97 - 112 & FV0 0 - 47
433+
);
434+
410435
using UDTrack = UDTracks::iterator;
411436
using UDTrackCov = UDTracksCov::iterator;
412437
using UDTrackExtra = UDTracksExtra::iterator;

PWGUD/TableProducer/CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ o2physics_add_dpl_workflow(dg-cand-producer
1818

1919
o2physics_add_dpl_workflow(sgcand-producer
2020
SOURCES SGCandProducer.cxx
21-
PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::SGCutParHolder O2Physics::AnalysisCCDB
21+
PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::SGCutParHolder O2Physics::AnalysisCCDB O2Physics::FITCutParHolder
2222
COMPONENT_NAME Analysis)
2323

2424
o2physics_add_dpl_workflow(dgbccand-producer

0 commit comments

Comments
 (0)