Skip to content

Commit 57edbca

Browse files
committed
Working Pn analyzer without cuts
1 parent ea76f12 commit 57edbca

3 files changed

Lines changed: 208 additions & 53 deletions

File tree

PWGUD/DataModel/UDTables.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -408,6 +408,9 @@ DECLARE_SOA_TABLE(UDTracksLabels, "AOD", "UDTRACKLABEL",
408408

409409
namespace udcollfitbits
410410
{
411+
412+
DECLARE_SOA_INDEX_COLUMN(UDCollision, udCollision); /// Link to the UDCOLLISION table
413+
411414
DECLARE_SOA_COLUMN(Thr1W0, thr1W0, uint64_t); /// 1 MIP thresholds for FT0A ch 0 - ch 63
412415
DECLARE_SOA_COLUMN(Thr1W1, thr1W1, uint64_t); /// 1 MIP thresholds for FT0A ch 64 - ch 96 & FT0C ch 0 - ch 31
413416
DECLARE_SOA_COLUMN(Thr1W2, thr1W2, uint64_t); /// 1 MIP thresholds for FT0C ch 32 - ch 96
@@ -421,6 +424,7 @@ DECLARE_SOA_COLUMN(Thr2W3, thr2W3, uint64_t); /// 2 MIP thresholds for FT0C ch 9
421424

422425
DECLARE_SOA_TABLE(UDCollisionFITBits, "AOD", "UDCOLLFITBITS",
423426
o2::soa::Index<>,
427+
udcollfitbits::UDCollisionId, /// Link to the UDCOLLISION table
424428
udcollfitbits::Thr1W0, /// 1 MIP thresholds for FT0A ch 0 - ch 63
425429
udcollfitbits::Thr1W1, /// 1 MIP thresholds for FT0A ch 63 - ch 96 & FT0C ch 0 - ch 31
426430
udcollfitbits::Thr1W2, /// 1 MIP thresholds for FT0C ch 32 - ch 96

PWGUD/TableProducer/SGCandProducer.cxx

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -339,8 +339,9 @@ struct SGCandProducer {
339339
fitCuts.thr2_FV0A());
340340
}
341341

342-
outputFITBits(w1[0], w1[1], w1[2], w1[3],
343-
w2[0], w2[1], w2[2], w2[3]);
342+
outputFITBits(outputCollisions.lastIndex(),
343+
w1[0], w1[1], w1[2], w1[3],
344+
w2[0], w2[1], w2[2], w2[3]);
344345

345346
if (newbc.has_zdc()) {
346347
auto zdc = newbc.zdc();

PWGUD/Tasks/upcTestFITBitMapping.cxx

Lines changed: 201 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -9,105 +9,255 @@
99
// granted to it by virtue of its status as an Intergovernmental Organization
1010
// or submit itself to any jurisdiction.
1111
//
12-
// \FIT bits to phi, eta mapping
12+
// \brief FIT bits to phi, eta mapping + multiplicity from FIT bits
1313
// \author Sandor Lokos, sandor.lokos@cern.ch
14-
// \since March 2026
14+
// \since March 2026
1515

16-
#include "PWGUD/Core/UDHelpers.h" // udhelpers::Bits256, makeBits256, testBit, getPhiEtaFromFitBit
17-
#include "PWGUD/DataModel/UDTables.h" // aod::UDCollisionFITBits
16+
#include "PWGUD/Core/SGSelector.h"
17+
#include "PWGUD/Core/UDHelpers.h"
18+
#include "PWGUD/DataModel/UDTables.h"
1819

19-
#include "FT0Base/Geometry.h" // o2::ft0::Geometry
20+
#include "FT0Base/Geometry.h"
2021
#include "Framework/AnalysisTask.h"
2122
#include "Framework/HistogramRegistry.h"
23+
#include "Framework/Logger.h"
2224
#include "Framework/runDataProcessing.h"
2325

2426
#include <array>
2527
#include <cmath>
28+
#include <cstdint>
2629

2730
using namespace o2;
2831
using namespace o2::framework;
2932

33+
// using UDCollisionsFull = soa::Join<
34+
// aod::UDCollisions,
35+
// aod::UDCollisionsSels,
36+
// aod::UDCollisionSelExtras>;
37+
38+
using UDCollisionsFull = aod::UDCollisions;
39+
3040
struct UpcTestFITBitMapping {
31-
Configurable<int> whichThr{"whichThr", 1, "Use 1=Thr1 bits or 2=Thr2 bits"};
32-
Configurable<int> maxEvents{"maxEvents", -1, "Process at most this many rows (-1 = all)"};
41+
42+
SGSelector sgSelector;
43+
44+
Configurable<int> whichThr{"whichThr", 1, "Use 1=Thr1 bits or 2=Thr2 bits"};
45+
Configurable<int> maxEvents{"maxEvents", -1, "Process at most this many collisions (-1 = all)"};
46+
Configurable<int> debugPrintEvery{"debugPrintEvery", 1000, "Print every N events (-1 disables)"};
47+
Configurable<int> debugPrintFirst{"debugPrintFirst", 10, "Always print first N events"};
48+
Configurable<bool> useRctFlag{"useRctFlag", false, "use RCT flags for event selection"};
49+
Configurable<int> cutRctFlag{"cutRctFlag", 0, "0 = off, 1 = CBT, 2 = CBT+ZDC, 3 = CBThadron, 4 = CBThadron+ZDC"};
3350

34-
// Minimal offset container compatible with UDHelpers.h expectations: getX/getY/getZ
3551
struct OffsetXYZ {
36-
double x{0}, y{0}, z{0};
52+
double x{0.}, y{0.}, z{0.};
3753
double getX() const { return x; }
3854
double getY() const { return y; }
3955
double getZ() const { return z; }
4056
};
4157

42-
std::array<OffsetXYZ, 1> offsetFT0{}; // iRunOffset = 0 for now
58+
std::array<OffsetXYZ, 1> offsetFT0{};
4359
int iRunOffset = 0;
4460

4561
o2::ft0::Geometry ft0Det{};
4662

4763
HistogramRegistry registry{
4864
"registry",
4965
{
50-
{"hPhiA", "FT0A #varphi;#varphi;counts", {HistType::kTH1F, {{18, 0.0, 2. * M_PI}}}},
51-
{"hEtaA", "FT0A #eta;#eta;counts", {HistType::kTH1F, {{8, 3.5, 5.0}}}},
52-
{"hEtaPhiA", "FT0A #eta vs #varphi;#eta;#varphi", {HistType::kTH2F, {{8, 3.5, 5.0}, {18, 0.0, 2. * M_PI}}}},
66+
{"debug/hEventCounter", "Event counter;step;events", {HistType::kTH1F, {{6, -0.5, 5.5}}}},
67+
{"debug/hFitBitsSize", "fitBits.size() per collision;fitBits.size();events", {HistType::kTH1F, {{10, -0.5, 9.5}}}},
68+
{"debug/hCollisionIndexMod", "Collision index mod 100;collision.globalIndex() % 100;events", {HistType::kTH1F, {{100, -0.5, 99.5}}}},
69+
70+
{"map/hPhiA", "FT0A #varphi;#varphi;counts", {HistType::kTH1F, {{18, 0.0, 2. * M_PI}}}},
71+
{"map/hEtaA", "FT0A #eta;#eta;counts", {HistType::kTH1F, {{8, 3.5, 5.0}}}},
72+
{"map/hEtaPhiA", "FT0A #eta vs #varphi;#eta;#varphi", {HistType::kTH2F, {{8, 3.5, 5.0}, {18, 0.0, 2. * M_PI}}}},
5373

54-
{"hPhiC", "FT0C #varphi;#varphi;counts", {HistType::kTH1F, {{18, 0.0, 2. * M_PI}}}},
55-
{"hEtaC", "FT0C #eta;#eta;counts", {HistType::kTH1F, {{8, -3.5, -2.0}}}},
56-
{"hEtaPhiC", "FT0C #eta vs #varphi;#eta;#varphi", {HistType::kTH2F, {{8, -3.5, -2.0}, {18, 0.0, 2. * M_PI}}}},
74+
{"map/hPhiC", "FT0C #varphi;#varphi;counts", {HistType::kTH1F, {{18, 0.0, 2. * M_PI}}}},
75+
{"map/hEtaC", "FT0C #eta;#eta;counts", {HistType::kTH1F, {{8, -3.5, -2.0}}}},
76+
{"map/hEtaPhiC", "FT0C #eta vs #varphi;#eta;#varphi", {HistType::kTH2F, {{8, -3.5, -2.0}, {18, 0.0, 2. * M_PI}}}},
77+
78+
{"mult/hPnFT0A", "P(n): FT0A fired-channel multiplicity;N_{fired}^{FT0A};events", {HistType::kTH1F, {{97, -0.5, 96.5}}}},
79+
{"mult/hPnFT0C", "P(n): FT0C fired-channel multiplicity;N_{fired}^{FT0C};events", {HistType::kTH1F, {{113, -0.5, 112.5}}}},
80+
{"mult/hPnFT0", "P(n): FT0 fired-channel multiplicity;N_{fired}^{FT0};events", {HistType::kTH1F, {{209, -0.5, 208.5}}}},
81+
{"mult/hPnFV0A", "P(n): FV0A fired-channel multiplicity;N_{fired}^{FV0A};events", {HistType::kTH1F, {{49, -0.5, 48.5}}}},
82+
{"mult/hPnFIT", "P(n): FIT fired-channel multiplicity;N_{fired}^{FIT};events", {HistType::kTH1F, {{257, -0.5, 256.5}}}},
83+
84+
{"mult/hNfiredA_vs_C", "FT0A vs FT0C fired channels;N_{fired}^{FT0A};N_{fired}^{FT0C}",
85+
{HistType::kTH2F, {{97, -0.5, 96.5}, {113, -0.5, 112.5}}}}
5786
}};
5887

88+
int countBitsInRange(udhelpers::Bits256 const& bits, int first, int last) const
89+
{
90+
int n = 0;
91+
for (int i = first; i <= last; ++i) {
92+
if (udhelpers::testBit(bits, i)) {
93+
++n;
94+
}
95+
}
96+
return n;
97+
}
98+
99+
// template <typename C>
100+
// bool isGoodRctFlag(const C& collision)
101+
// {
102+
// switch (cutRctFlag) {
103+
// case 1: // CBT
104+
// return sgSelector.isCBTOk(collision);
105+
// case 2: // CBT + ZDC
106+
// return sgSelector.isCBTZdcOk(collision);
107+
// case 3: // CBT hadron
108+
// return sgSelector.isCBTHadronOk(collision);
109+
// case 4: // CBT hadron + ZDC
110+
// return sgSelector.isCBTHadronZdcOk(collision);
111+
// default: // no RCT cut applied
112+
// return true;
113+
// }
114+
// }
115+
116+
117+
// template <typename C>
118+
// bool collisionPassesCuts(const C& collision)
119+
// {
120+
// /* good vertex */
121+
// if (!collision.vtxITSTPC()) {
122+
// return false;
123+
// }
124+
// registry.fill(HIST("debug/hEventCounter"), 4.);
125+
126+
// /* same bunch pile-up rejection */
127+
// if (!collision.sbp()) {
128+
// return false;
129+
// }
130+
// registry.fill(HIST("debug/hEventCounter"), 5.);
131+
132+
// /* ITS ROF rejection */
133+
// if (!collision.itsROFb()) {
134+
// return false;
135+
// }
136+
// registry.fill(HIST("debug/hEventCounter"), 6.);
137+
138+
// /* Timeframe border collision rejection */
139+
// if (!collision.tfb()) {
140+
// return false;
141+
// }
142+
// registry.fill(HIST("debug/hEventCounter"), 7.);
143+
144+
// /* z-vertex cut */
145+
// if (std::abs(collision.posZ()) > 10.0) {
146+
// return false;
147+
// }
148+
// registry.fill(HIST("debug/hEventCounter"), 8.);
149+
150+
// /* RCT flag check*/
151+
// if (useRctFlag) {
152+
// if (!isGoodRctFlag(collision)) {
153+
// return false;
154+
// }
155+
// registry.fill(HIST("debug/hEventCounter"), 9.); // passed RCT flag
156+
// }
157+
// return true;
158+
// }
159+
59160
void init(InitContext&)
60161
{
61-
// UDHelpers calls calculateChannelCenter() inside, but doing it once here is fine.
62162
ft0Det.calculateChannelCenter();
163+
LOGF(info, "UpcTestFITBitMapping initialized. whichThr=%d", static_cast<int>(whichThr));
63164
}
64165

65-
void process(aod::UDCollisionFITBits const& bitsTable)
166+
void process(UDCollisionsFull::iterator const& collision, aod::UDCollisionFITBits const& fitBits)
66167
{
67-
int64_t nProcessed = 0;
168+
if (maxEvents >= 0 && collision.globalIndex() >= maxEvents) {
169+
return;
170+
}
171+
172+
registry.fill(HIST("debug/hEventCounter"), 0.);
173+
registry.fill(HIST("debug/hFitBitsSize"), fitBits.size());
174+
registry.fill(HIST("debug/hCollisionIndexMod"), collision.globalIndex() % 100);
68175

69-
for (auto const& row : bitsTable) {
70-
if (maxEvents >= 0 && nProcessed >= maxEvents) {
71-
break;
176+
if (fitBits.size() == 0) {
177+
if (collision.globalIndex() < debugPrintFirst ||
178+
(debugPrintEvery > 0 && collision.globalIndex() % debugPrintEvery == 0)) {
179+
LOGF(info, "collision %d: fitBits.size() = 0", collision.globalIndex());
72180
}
73-
++nProcessed;
181+
registry.fill(HIST("debug/hEventCounter"), 1.);
182+
return;
183+
184+
} else if (fitBits.size() == 1) {
185+
LOGF(debug, "collision %d: fitBits.size() = %d , as it should be", collision.globalIndex(), fitBits.size());
186+
registry.fill(HIST("debug/hEventCounter"), 2.);
187+
188+
} else { // > 1 case
189+
if (collision.globalIndex() < debugPrintFirst ||
190+
(debugPrintEvery > 0 && collision.globalIndex() % debugPrintEvery == 0)) {
191+
LOGF(warn, "collision %d: fitBits.size() = %d (expected 0 or 1)", collision.globalIndex(), fitBits.size());
192+
}
193+
registry.fill(HIST("debug/hEventCounter"), 3.);
194+
return;
195+
}
74196

75-
// Use udhelpers' canonical packed type + builder
76-
udhelpers::Bits256 w{};
77-
if (whichThr == 2) {
78-
w = udhelpers::makeBits256(row.thr2W0(), row.thr2W1(), row.thr2W2(), row.thr2W3());
79-
} else {
80-
w = udhelpers::makeBits256(row.thr1W0(), row.thr1W1(), row.thr1W2(), row.thr1W3());
197+
/* Checking collision level cuts */
198+
// if (!collisionPassesCuts(collision)) {
199+
// return;
200+
// }
201+
202+
/* Only one row per collision is expected. */
203+
// auto const& row = *fitBits.begin();
204+
auto row = fitBits.begin();
205+
206+
udhelpers::Bits256 w{};
207+
if (whichThr == 2) {
208+
w = udhelpers::makeBits256(row.thr2W0(), row.thr2W1(), row.thr2W2(), row.thr2W3());
209+
} else {
210+
w = udhelpers::makeBits256(row.thr1W0(), row.thr1W1(), row.thr1W2(), row.thr1W3());
211+
}
212+
213+
const int nFT0A = countBitsInRange(w, 0, udhelpers::kFT0AChannels - 1);
214+
const int nFT0C = countBitsInRange(w, udhelpers::kFT0AChannels, udhelpers::kFT0Bits - 1);
215+
const int nFT0 = nFT0A + nFT0C;
216+
const int nFV0A = countBitsInRange(w, udhelpers::kFT0Bits, udhelpers::kTotalBits - 1);
217+
const int nFIT = nFT0 + nFV0A;
218+
219+
registry.fill(HIST("mult/hPnFT0A"), nFT0A);
220+
registry.fill(HIST("mult/hPnFT0C"), nFT0C);
221+
registry.fill(HIST("mult/hPnFT0"), nFT0);
222+
registry.fill(HIST("mult/hPnFV0A"), nFV0A);
223+
registry.fill(HIST("mult/hPnFIT"), nFIT);
224+
registry.fill(HIST("mult/hNfiredA_vs_C"), nFT0A, nFT0C);
225+
226+
if (collision.globalIndex() < debugPrintFirst ||
227+
(debugPrintEvery > 0 && collision.globalIndex() % debugPrintEvery == 0)) {
228+
LOGF(info,
229+
"collision %d: fitBits.size=%d nFT0A=%d nFT0C=%d nFT0=%d nFV0A=%d nFIT=%d",
230+
collision.globalIndex(), fitBits.size(), nFT0A, nFT0C, nFT0, nFV0A, nFIT);
231+
}
232+
233+
for (int bit = 0; bit < udhelpers::kFT0Bits; ++bit) {
234+
if (!udhelpers::testBit(w, bit)) {
235+
continue;
81236
}
82237

83-
// Loop FT0 bits only (0..207). FV0 starts at 208 but ignored here.
84-
for (int bit = 0; bit < udhelpers::kFT0Bits; ++bit) {
85-
if (!udhelpers::testBit(w, bit)) {
86-
continue;
87-
}
88-
89-
double phi = 0., eta = 0.;
90-
const bool ok = udhelpers::getPhiEtaFromFitBit(ft0Det, bit, offsetFT0, iRunOffset, phi, eta);
91-
if (!ok) {
92-
continue;
93-
}
94-
95-
if (bit < udhelpers::kFT0AChannels) {
96-
registry.fill(HIST("hPhiA"), phi);
97-
registry.fill(HIST("hEtaA"), eta);
98-
registry.fill(HIST("hEtaPhiA"), eta, phi);
99-
} else {
100-
registry.fill(HIST("hPhiC"), phi);
101-
registry.fill(HIST("hEtaC"), eta);
102-
registry.fill(HIST("hEtaPhiC"), eta, phi);
103-
}
238+
double phi = 0., eta = 0.;
239+
const bool ok = udhelpers::getPhiEtaFromFitBit(ft0Det, bit, offsetFT0, iRunOffset, phi, eta);
240+
if (!ok) {
241+
continue;
242+
}
243+
244+
if (bit < udhelpers::kFT0AChannels) {
245+
registry.fill(HIST("map/hPhiA"), phi);
246+
registry.fill(HIST("map/hEtaA"), eta);
247+
registry.fill(HIST("map/hEtaPhiA"), eta, phi);
248+
} else {
249+
registry.fill(HIST("map/hPhiC"), phi);
250+
registry.fill(HIST("map/hEtaC"), eta);
251+
registry.fill(HIST("map/hEtaPhiC"), eta, phi);
104252
}
105253
}
254+
255+
registry.fill(HIST("debug/hEventCounter"), 4.);
106256
}
107257
};
108258

109259
WorkflowSpec defineDataProcessing(ConfigContext const& cfgc)
110260
{
111261
return WorkflowSpec{
112262
adaptAnalysisTask<UpcTestFITBitMapping>(cfgc, TaskName{"fitbit-mapping"})};
113-
}
263+
}

0 commit comments

Comments
 (0)