Skip to content

Commit 3cea0ac

Browse files
aalkinalibuildjesgum
authored
[ALICE3] Introduce flat LUT container for the TrackSmearer and rebase OTF code to use it (#15826)
Co-authored-by: ALICE Action Bot <alibuild@cern.ch> Co-authored-by: jesgum <jesper.gumprecht@gmail.com>
1 parent aff6bc8 commit 3cea0ac

File tree

11 files changed

+1680
-14
lines changed

11 files changed

+1680
-14
lines changed

ALICE3/Core/CMakeLists.txt

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,28 +12,30 @@
1212
o2physics_add_library(ALICE3Core
1313
SOURCES TOFResoALICE3.cxx
1414
TrackUtilities.cxx
15-
DelphesO2TrackSmearer.cxx
15+
FlatLutEntry.cxx
16+
FlatTrackSmearer.cxx
1617
GeometryContainer.cxx
1718
PUBLIC_LINK_LIBRARIES O2::Framework
1819
O2Physics::AnalysisCore)
1920

2021
o2physics_target_root_dictionary(ALICE3Core
2122
HEADERS TOFResoALICE3.h
2223
TrackUtilities.h
23-
DelphesO2TrackSmearer.h
24+
FlatLutEntry.h
2425
GeometryContainer.h
2526
LINKDEF ALICE3CoreLinkDef.h)
2627

2728
o2physics_add_library(FastTracker
2829
SOURCES FastTracker.cxx
2930
DetLayer.cxx
30-
DelphesO2LutWriter.cxx
31+
FlatLutEntry.cxx
32+
FlatLutWriter.cxx
3133
PUBLIC_LINK_LIBRARIES O2::Framework
3234
O2Physics::AnalysisCore
3335
O2Physics::ALICE3Core)
3436

3537
o2physics_target_root_dictionary(FastTracker
3638
HEADERS FastTracker.h
3739
DetLayer.h
38-
DelphesO2LutWriter.h
40+
FlatLutWriter.h
3941
LINKDEF FastTrackerLinkDef.h)

ALICE3/Core/FastTrackerLinkDef.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,6 @@
1818

1919
#pragma link C++ class o2::fastsim::GeometryContainer + ;
2020
#pragma link C++ class o2::fastsim::FastTracker + ;
21-
#pragma link C++ class o2::fastsim::DelphesO2LutWriter + ;
21+
#pragma link C++ class o2::fastsim::FlatLutWriter + ;
2222

2323
#endif // ALICE3_CORE_FASTTRACKERLINKDEF_H_

ALICE3/Core/FlatLutEntry.cxx

Lines changed: 270 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,270 @@
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+
#include "FlatLutEntry.h"
13+
14+
#include <Framework/Logger.h>
15+
#include <Framework/RuntimeError.h>
16+
17+
#include <cstring>
18+
19+
namespace o2::delphes
20+
{
21+
22+
float map_t::fracPositionWithinBin(float val) const
23+
{
24+
float width = (max - min) / nbins;
25+
int bin;
26+
float returnVal = 0.5f;
27+
if (log) {
28+
bin = static_cast<int>((std::log10(val) - min) / width);
29+
returnVal = ((std::log10(val) - min) / width) - bin;
30+
} else {
31+
bin = static_cast<int>((val - min) / width);
32+
returnVal = val / width - bin;
33+
}
34+
return returnVal;
35+
}
36+
37+
int map_t::find(float val) const
38+
{
39+
float width = (max - min) / nbins;
40+
int bin;
41+
if (log) {
42+
bin = static_cast<int>((std::log10(val) - min) / width);
43+
} else {
44+
bin = static_cast<int>((val - min) / width);
45+
}
46+
if (bin < 0) {
47+
return 0;
48+
}
49+
if (bin > nbins - 1) {
50+
return nbins - 1;
51+
}
52+
return bin;
53+
}
54+
55+
void map_t::print() const
56+
{
57+
LOGF(info, "nbins = %d, min = %f, max = %f, log = %s \n", nbins, min, max, log ? "on" : "off");
58+
}
59+
60+
bool lutHeader_t::check_version() const
61+
{
62+
return (version == LUTCOVM_VERSION);
63+
}
64+
65+
void lutHeader_t::print() const
66+
{
67+
LOGF(info, " version: %d \n", version);
68+
LOGF(info, " pdg: %d \n", pdg);
69+
LOGF(info, " field: %f \n", field);
70+
LOGF(info, " nchmap: ");
71+
nchmap.print();
72+
LOGF(info, " radmap: ");
73+
radmap.print();
74+
LOGF(info, " etamap: ");
75+
etamap.print();
76+
LOGF(info, " ptmap: ");
77+
ptmap.print();
78+
}
79+
80+
void FlatLutData::initialize(const lutHeader_t& header)
81+
{
82+
mNchBins = header.nchmap.nbins;
83+
mRadBins = header.radmap.nbins;
84+
mEtaBins = header.etamap.nbins;
85+
mPtBins = header.ptmap.nbins;
86+
87+
size_t headerSize = sizeof(lutHeader_t);
88+
size_t numEntries = static_cast<size_t>(mNchBins) * mRadBins * mEtaBins * mPtBins;
89+
size_t entriesSize = numEntries * sizeof(lutEntry_t);
90+
size_t totalSize = headerSize + entriesSize;
91+
92+
mData.resize(totalSize);
93+
// Write header at the beginning
94+
std::memcpy(mData.data(), &header, headerSize);
95+
updateRef();
96+
}
97+
98+
size_t FlatLutData::getEntryOffset(int nch_bin, int rad_bin, int eta_bin, int pt_bin) const
99+
{
100+
size_t headerSize = sizeof(lutHeader_t);
101+
102+
// Linear index: nch varies slowest, pt varies fastest
103+
// idx = nch * (rad*eta*pt) + rad * (eta*pt) + eta * pt + pt
104+
size_t linearIdx = static_cast<size_t>(nch_bin) * (mRadBins * mEtaBins * mPtBins) + static_cast<size_t>(rad_bin) * (mEtaBins * mPtBins) + static_cast<size_t>(eta_bin) * mPtBins + static_cast<size_t>(pt_bin);
105+
106+
return headerSize + linearIdx * sizeof(lutEntry_t);
107+
}
108+
109+
const lutEntry_t* FlatLutData::getEntryRef(int nch_bin, int rad_bin, int eta_bin, int pt_bin) const
110+
{
111+
size_t offset = getEntryOffset(nch_bin, rad_bin, eta_bin, pt_bin);
112+
return reinterpret_cast<const lutEntry_t*>(mDataRef.data() + offset);
113+
}
114+
115+
lutEntry_t* FlatLutData::getEntry(int nch_bin, int rad_bin, int eta_bin, int pt_bin)
116+
{
117+
size_t offset = getEntryOffset(nch_bin, rad_bin, eta_bin, pt_bin);
118+
return reinterpret_cast<lutEntry_t*>(mData.data() + offset);
119+
}
120+
121+
const lutHeader_t& FlatLutData::getHeaderRef() const
122+
{
123+
return *reinterpret_cast<const lutHeader_t*>(mDataRef.data());
124+
}
125+
126+
lutHeader_t& FlatLutData::getHeader()
127+
{
128+
return *reinterpret_cast<lutHeader_t*>(mData.data());
129+
}
130+
131+
void FlatLutData::updateRef()
132+
{
133+
mDataRef = std::span{mData.data(), mData.size()};
134+
}
135+
136+
void FlatLutData::cacheDimensions()
137+
{
138+
auto const& header = getHeaderRef();
139+
mNchBins = header.nchmap.nbins;
140+
mRadBins = header.radmap.nbins;
141+
mEtaBins = header.etamap.nbins;
142+
mPtBins = header.ptmap.nbins;
143+
}
144+
145+
void FlatLutData::resetDimensions()
146+
{
147+
mNchBins = 0;
148+
mRadBins = 0;
149+
mEtaBins = 0;
150+
mPtBins = 0;
151+
}
152+
153+
void FlatLutData::adopt(const uint8_t* buffer, size_t size)
154+
{
155+
mData.resize(size);
156+
std::memcpy(mData.data(), buffer, size);
157+
updateRef();
158+
cacheDimensions();
159+
}
160+
161+
void FlatLutData::view(const uint8_t* buffer, size_t size)
162+
{
163+
mData.clear();
164+
mDataRef = std::span{buffer, size};
165+
cacheDimensions();
166+
}
167+
168+
void FlatLutData::validateBuffer(const uint8_t* buffer, size_t size)
169+
{
170+
auto header = PreviewHeader(buffer, size);
171+
auto mNchBins = header.nchmap.nbins;
172+
auto mRadBins = header.radmap.nbins;
173+
auto mEtaBins = header.etamap.nbins;
174+
auto mPtBins = header.ptmap.nbins;
175+
176+
size_t expectedSize = sizeof(lutHeader_t) + static_cast<size_t>(mNchBins) * mRadBins * mEtaBins * mPtBins * sizeof(lutEntry_t);
177+
178+
if (size < expectedSize) {
179+
throw framework::runtime_error_f("Buffer size mismatch: expected %zu, got %zu", expectedSize, size);
180+
}
181+
}
182+
183+
lutHeader_t FlatLutData::PreviewHeader(const uint8_t* buffer, size_t size)
184+
{
185+
if (size < sizeof(lutHeader_t)) {
186+
throw framework::runtime_error_f("Buffer too small for LUT header: expected at least %zu, got %zu", sizeof(lutHeader_t), size);
187+
}
188+
const auto* header = reinterpret_cast<const lutHeader_t*>(buffer);
189+
if (!header->check_version()) {
190+
throw framework::runtime_error_f("LUT header version mismatch: expected %d, got %d", LUTCOVM_VERSION, header->version);
191+
}
192+
return *header;
193+
}
194+
195+
FlatLutData FlatLutData::AdoptFromBuffer(const uint8_t* buffer, size_t size)
196+
{
197+
validateBuffer(buffer, size);
198+
FlatLutData data;
199+
200+
// Copy buffer
201+
data.adopt(buffer, size);
202+
return data;
203+
}
204+
205+
FlatLutData FlatLutData::ViewFromBuffer(const uint8_t* buffer, size_t size)
206+
{
207+
validateBuffer(buffer, size);
208+
FlatLutData data;
209+
210+
// Store reference to external buffer
211+
// WARNING: Caller must ensure buffer lifetime exceeds FlatLutData usage
212+
data.view(buffer, size);
213+
return data;
214+
}
215+
216+
FlatLutData FlatLutData::ViewFromBuffer(std::span<std::byte> const& span)
217+
{
218+
return ViewFromBuffer(reinterpret_cast<const uint8_t*>(span.data()), span.size_bytes());
219+
}
220+
221+
bool FlatLutData::isLoaded() const
222+
{
223+
return ((!mData.empty()) || (!mDataRef.empty()));
224+
}
225+
226+
lutHeader_t FlatLutData::PreviewHeader(std::ifstream& file, const char* filename)
227+
{
228+
lutHeader_t tempHeader;
229+
file.read(reinterpret_cast<char*>(&tempHeader), sizeof(lutHeader_t));
230+
if (file.gcount() != static_cast<std::streamsize>(sizeof(lutHeader_t))) {
231+
throw framework::runtime_error_f("Failed to read LUT header from %s", filename);
232+
}
233+
if (!tempHeader.check_version()) {
234+
throw framework::runtime_error_f("LUT header version mismatch: expected %d, got %d", LUTCOVM_VERSION, tempHeader.version);
235+
}
236+
return tempHeader;
237+
}
238+
239+
FlatLutData FlatLutData::loadFromFile(std::ifstream& file, const char* filename)
240+
{
241+
// Read header first
242+
lutHeader_t tempHeader = PreviewHeader(file, filename);
243+
244+
FlatLutData data;
245+
246+
// Initialize flat data structure
247+
data.initialize(tempHeader);
248+
249+
// Read all entries sequentially into flat buffer
250+
size_t headerSize = sizeof(lutHeader_t);
251+
size_t numEntries = static_cast<size_t>(data.mNchBins) * data.mRadBins * data.mEtaBins * data.mPtBins;
252+
size_t entriesSize = numEntries * sizeof(lutEntry_t);
253+
254+
file.read(reinterpret_cast<char*>(data.data() + headerSize), entriesSize);
255+
if (file.gcount() != static_cast<std::streamsize>(entriesSize)) {
256+
throw framework::runtime_error_f("Failed to read LUT entries from %s: expected %zu bytes, got %zu", filename, entriesSize, static_cast<size_t>(file.gcount()));
257+
}
258+
259+
LOGF(info, "Successfully loaded LUT from %s: %zu entries", filename, numEntries);
260+
return data;
261+
}
262+
263+
void FlatLutData::reset()
264+
{
265+
mData.clear();
266+
updateRef();
267+
resetDimensions();
268+
}
269+
270+
} // namespace o2::delphes

0 commit comments

Comments
 (0)