Skip to content

Commit 48b88e3

Browse files
authored
Merge branch 'AliceO2Group:dev' into devel_fst_numactl
2 parents 95f3190 + d661c23 commit 48b88e3

112 files changed

Lines changed: 4537 additions & 1014 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.gitignore

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,3 +90,9 @@ bazel-*
9090
DataFormats/Detectors/CTP/include/DataFormatsCTP/Scalers.h
9191
dpl-config.json
9292
O2.code-workspace
93+
94+
# Python bytecode
95+
*.pyc
96+
97+
# Claude code
98+
.claude/settings.local.json

Common/Field/src/MagFieldFast.cxx

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -61,8 +61,11 @@ MagFieldFast::MagFieldFast(float factor, int nomField, const string inpFmt) : mF
6161
bool MagFieldFast::LoadData(const string inpFName)
6262
{
6363
// load field from text file
64-
65-
std::ifstream in(gSystem->ExpandPathName(inpFName.data()), std::ifstream::in);
64+
TString sName(inpFName);
65+
if (gSystem->ExpandPathName(sName)) {
66+
LOG(fatal) << "Failed to expand file name " << inpFName;
67+
}
68+
std::ifstream in(sName.Data(), std::ifstream::in);
6669
if (in.fail()) {
6770
LOG(fatal) << "Failed to open file " << inpFName;
6871
return false;

Common/Field/src/MagneticField.cxx

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,10 @@
1414
/// \author ruben.shahoyan@cern.ch
1515

1616
#include "Field/MagneticField.h"
17-
#include <TFile.h> // for TFile
18-
#include <TPRegexp.h> // for TPRegexp
19-
#include <TSystem.h> // for TSystem, gSystem
17+
#include <TFile.h> // for TFile
18+
#include <TPRegexp.h> // for TPRegexp
19+
#include <TString.h> // for TString
20+
#include <TSystem.h> // for TSystem, gSystem
2021
#include <fairlogger/Logger.h> // for FairLogger
2122
#include "FairParamList.h"
2223
#include "FairRun.h"
@@ -242,7 +243,8 @@ Bool_t MagneticField::loadParameterization()
242243
LOG(fatal) << "MagneticField::loadParameterization: Field data " << getParameterName()
243244
<< " are already loaded from " << getDataFileName() << "\n";
244245
}
245-
const char* fname = gSystem->ExpandPathName(getDataFileName());
246+
TString fname = getDataFileName();
247+
gSystem->ExpandPathName(fname);
246248
TFile* file = TFile::Open(fname);
247249
if (!file) {
248250
LOG(fatal) << "MagneticField::loadParameterization: Failed to open magnetic field data file " << fname << "\n";

Common/MathUtils/CMakeLists.txt

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,13 @@ o2_add_test(
5757
PUBLIC_LINK_LIBRARIES O2::MathUtils
5858
LABELS utils)
5959

60+
o2_add_test(
61+
Chebyshev3D
62+
SOURCES test/testChebyshev3D.cxx
63+
COMPONENT_NAME MathUtils
64+
PUBLIC_LINK_LIBRARIES O2::MathUtils
65+
LABELS utils)
66+
6067
o2_add_test(
6168
Utils
6269
SOURCES test/testUtils.cxx

Common/MathUtils/include/MathUtils/Chebyshev3DCalc.h

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818

1919
#include <TNamed.h> // for TNamed
2020
#include <cstdio> // for FILE, stdout
21+
#include <cmath> // for std::fma
2122
#include "Rtypes.h" // for Float_t, UShort_t, Int_t, Double_t, etc
2223

2324
class TString;
@@ -208,9 +209,14 @@ inline Float_t Chebyshev3DCalc::chebyshevEvaluation1D(Float_t x, const Float_t*
208209
for (int i = ncf; i--;) {
209210
b2 = b1;
210211
b1 = b0;
211-
b0 = array[i] + x2 * b1 - b2;
212+
// Clenshaw recurrence, grouped as fma(x2, b1, array[i] - b2). Mathematically
213+
// identical to `array[i] + x2 * b1 - b2`, but `array[i] - b2` does not depend
214+
// on the just-updated b1, so the loop-carried chain collapses to a single FMA
215+
// latency instead of a dependent multiply+add+subtract. This kernel dominates
216+
// magnetic-field evaluation in (e.g.) muon track extrapolation.
217+
b0 = std::fma(x2, b1, array[i] - b2);
212218
}
213-
return b0 - x * b1;
219+
return std::fma(-x, b1, b0);
214220
}
215221

216222
/// Evaluates Chebyshev parameterization for 3D function.
Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
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+
/// \file testChebyshev3D.cxx
13+
/// \brief Accuracy of the Chebyshev3D evaluation kernel.
14+
///
15+
/// Guards `Chebyshev3DCalc::Eval` / `chebyshevEvaluation1D` (the Clenshaw
16+
/// recurrence that dominates magnetic-field evaluation in track extrapolation).
17+
/// We build an in-memory parameterization of a known smooth function and check
18+
/// that `Eval` reproduces it to the requested precision over many random points,
19+
/// and that the per-dimension and double-precision overloads agree with the
20+
/// float vector overload. Any breakage of the recurrence (e.g. a wrong FMA
21+
/// regrouping) makes the reproduction error explode and fails the test.
22+
23+
#define BOOST_TEST_MODULE Test Chebyshev3D
24+
#define BOOST_TEST_MAIN
25+
#define BOOST_TEST_DYN_LINK
26+
#include <boost/test/unit_test.hpp>
27+
#include <cmath>
28+
#include <random>
29+
#include "MathUtils/Chebyshev3D.h"
30+
31+
using o2::math_utils::Chebyshev3D;
32+
33+
namespace
34+
{
35+
// A smooth, low-degree (≤3 per variable) vector function over the fit box, of
36+
// the kind a Chebyshev parameterization reproduces to ~float precision. Stands
37+
// in for a slowly-varying magnetic field B(x,y,z).
38+
void referenceField(float* in, float* out)
39+
{
40+
const float x = in[0], y = in[1], z = in[2];
41+
out[0] = 0.50f + 0.020f * x - 1.0e-4f * x * y + 3.0e-3f * z - 2.0e-6f * x * x * z;
42+
out[1] = -0.30f + 0.015f * y + 5.0e-5f * y * z - 1.0e-3f * x;
43+
out[2] = 5.00f - 4.0e-4f * x * x + 6.0e-4f * y * y + 1.0e-3f * x * y - 2.0e-6f * x * y * z;
44+
}
45+
} // namespace
46+
47+
BOOST_AUTO_TEST_CASE(Chebyshev3D_eval_accuracy)
48+
{
49+
const Float_t bmin[3] = {-40.f, -40.f, -200.f};
50+
const Float_t bmax[3] = {40.f, 40.f, 200.f};
51+
const Int_t np[3] = {7, 7, 7}; // > polynomial degree in every dimension
52+
const Float_t fitPrec = 1.0e-5f;
53+
54+
Chebyshev3D cheb(referenceField, 3, bmin, bmax, np, fitPrec);
55+
56+
// Deterministic interior sampling (fixed seed -> no flakiness). Stay a hair
57+
// inside the box so we never hit the boundary-clamping branch.
58+
std::mt19937 rng(20260604u);
59+
std::uniform_real_distribution<float> ux(bmin[0] + 1.f, bmax[0] - 1.f);
60+
std::uniform_real_distribution<float> uy(bmin[1] + 1.f, bmax[1] - 1.f);
61+
std::uniform_real_distribution<float> uz(bmin[2] + 1.f, bmax[2] - 1.f);
62+
63+
float maxAbsErr = 0.f; // |cheb - reference| (kernel reproduces the function)
64+
float maxDimMismatch = 0.f; // |vector overload - per-dim overload|
65+
float maxDoubleMismatch = 0.f; // |float overload - double overload|
66+
67+
for (int i = 0; i < 20000; ++i) {
68+
float par[3] = {ux(rng), uy(rng), uz(rng)};
69+
float ref[3];
70+
referenceField(par, ref);
71+
72+
float res[3];
73+
cheb.Eval(par, res);
74+
75+
double pard[3] = {par[0], par[1], par[2]};
76+
double resd[3];
77+
cheb.Eval(pard, resd);
78+
79+
for (int d = 0; d < 3; ++d) {
80+
BOOST_REQUIRE(std::isfinite(res[d]));
81+
maxAbsErr = std::max(maxAbsErr, std::abs(res[d] - ref[d]));
82+
// Single-component overload must match the vector overload (same kernel).
83+
maxDimMismatch = std::max(maxDimMismatch, std::abs(res[d] - cheb.Eval(par, d)));
84+
// Double overload differs only by intermediate precision.
85+
maxDoubleMismatch = std::max(maxDoubleMismatch, std::abs(static_cast<float>(resd[d]) - res[d]));
86+
}
87+
}
88+
89+
BOOST_TEST_MESSAGE("Chebyshev3D max |eval - reference| = " << maxAbsErr);
90+
BOOST_TEST_MESSAGE("Chebyshev3D max vector-vs-perdim = " << maxDimMismatch);
91+
BOOST_TEST_MESSAGE("Chebyshev3D max float-vs-double = " << maxDoubleMismatch);
92+
93+
// Reproduction of the known function: fit precision (1e-5) plus a little float
94+
// slack from the three nested Clenshaw sums (observed ~1.4e-6). A broken
95+
// recurrence misses this by orders of magnitude (coefficient-scale error / NaN).
96+
BOOST_CHECK_SMALL(maxAbsErr, 1.0e-4f);
97+
// The two float entry points share the kernel: expect bit-for-bit agreement.
98+
BOOST_CHECK_SMALL(maxDimMismatch, 1.0e-6f);
99+
// float vs double evaluation of the same coefficients: within float epsilon.
100+
BOOST_CHECK_SMALL(maxDoubleMismatch, 1.0e-3f);
101+
}

Common/Utils/include/CommonUtils/ConfigurableParamHelper.h

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616

1717
#include "CommonUtils/ConfigurableParam.h"
1818
#include "TClass.h"
19+
#include <memory>
1920
#include <type_traits>
2021
#include <typeinfo>
2122
#include "TFile.h"
@@ -105,22 +106,23 @@ class ConfigurableParamHelper : virtual public ConfigurableParam
105106
if (!isInitialized()) {
106107
initialize();
107108
}
108-
auto members = getDataMembers();
109-
_ParamHelper::printMembersImpl(getName(), members, showProv, useLogger, withPadding, showHash);
109+
auto members = std::unique_ptr<std::vector<ParamDataMember>>(getDataMembers());
110+
_ParamHelper::printMembersImpl(getName(), members.get(), showProv, useLogger, withPadding, showHash);
110111
}
111112

112113
//
113114
size_t getHash() const final
114115
{
115-
return _ParamHelper::getHashImpl(getName(), getDataMembers());
116+
auto members = std::unique_ptr<std::vector<ParamDataMember>>(getDataMembers());
117+
return _ParamHelper::getHashImpl(getName(), members.get());
116118
}
117119

118120
// ----------------------------------------------------------------
119121

120122
void output(std::ostream& out) const final
121123
{
122-
auto members = getDataMembers();
123-
_ParamHelper::outputMembersImpl(out, getName(), members, true, false);
124+
auto members = std::unique_ptr<std::vector<ParamDataMember>>(getDataMembers());
125+
_ParamHelper::outputMembersImpl(out, getName(), members.get(), true, false);
124126
}
125127

126128
// ----------------------------------------------------------------
@@ -242,22 +244,23 @@ class ConfigurableParamPromoter : public Base, virtual public ConfigurableParam
242244
if (!isInitialized()) {
243245
initialize();
244246
}
245-
auto members = getDataMembers();
246-
_ParamHelper::printMembersImpl(getName(), members, showProv, useLogger, withPadding, showHash);
247+
auto members = std::unique_ptr<std::vector<ParamDataMember>>(getDataMembers());
248+
_ParamHelper::printMembersImpl(getName(), members.get(), showProv, useLogger, withPadding, showHash);
247249
}
248250

249251
//
250252
size_t getHash() const final
251253
{
252-
return _ParamHelper::getHashImpl(getName(), getDataMembers());
254+
auto members = std::unique_ptr<std::vector<ParamDataMember>>(getDataMembers());
255+
return _ParamHelper::getHashImpl(getName(), members.get());
253256
}
254257

255258
// ----------------------------------------------------------------
256259

257260
void output(std::ostream& out) const final
258261
{
259-
auto members = getDataMembers();
260-
_ParamHelper::outputMembersImpl(out, getName(), members, true, false);
262+
auto members = std::unique_ptr<std::vector<ParamDataMember>>(getDataMembers());
263+
_ParamHelper::outputMembersImpl(out, getName(), members.get(), true, false);
261264
}
262265

263266
// ----------------------------------------------------------------

DataFormats/Detectors/FIT/common/include/DataFormatsFIT/LookUpTable.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
#include <Rtypes.h>
2525
#include <iostream>
2626
#include <tuple>
27+
#include <TString.h>
2728
#include <TSystem.h>
2829
#include <map>
2930
#include <string>
@@ -236,7 +237,9 @@ class LookupTableBase
236237
}
237238
inputDir += "/share/Detectors/FT0/files/";
238239
filepath = inputDir + "LookupTable_FT0.json";
239-
filepath = gSystem->ExpandPathName(filepath.data()); // Expand $(ALICE_ROOT) into real system path
240+
TString expandedFilepath = filepath;
241+
gSystem->ExpandPathName(expandedFilepath); // Expand $(ALICE_ROOT) into real system path
242+
filepath = expandedFilepath.Data();
240243
} else {
241244
filepath = pathToFile;
242245
}

DataFormats/Detectors/ITSMFT/ITS/include/DataFormatsITS/TrackITS.h

Lines changed: 39 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,11 @@ namespace its
3535

3636
class TrackITS : public o2::track::TrackParCov
3737
{
38+
public:
39+
static constexpr unsigned int ExtendedPatternShift = 24;
40+
static constexpr int MaxLayersInTrackPattern = 8;
41+
42+
private:
3843
enum UserBits {
3944
kSharedClusters = 1 << 28
4045
};
@@ -106,16 +111,47 @@ class TrackITS : public o2::track::TrackParCov
106111
GPUhdi() uint32_t getPattern() const { return mPattern; }
107112
bool hasHitOnLayer(uint32_t i) const { return mPattern & (0x1 << i); }
108113
bool isFakeOnLayer(uint32_t i) const { return !(mPattern & (0x1 << (16 + i))); }
109-
bool isExtendedOnLayer(uint32_t i) const { return (mPattern & (0x1 << (24 + i))); } // only correct if getNClusters <= 8 on layers <= 8
110-
uint32_t getLastClusterLayer() const
114+
bool isExtendedOnLayer(uint32_t i) const { return (mPattern & (0x1 << (ExtendedPatternShift + i))); } // only correct if getNClusters <= 8 on layers <= 8
115+
template <int NLayers>
116+
GPUhdi() static constexpr uint32_t getLayerPatternMask()
117+
{
118+
return (NLayers >= 32) ? 0xffffffffu : ((1u << NLayers) - 1u);
119+
}
120+
template <int NLayers>
121+
GPUhdi() void setExtendedLayerPattern(uint32_t pattern)
122+
{
123+
pattern &= getLayerPatternMask<NLayers>();
124+
setUserField(static_cast<uint16_t>(pattern));
125+
if constexpr (NLayers <= MaxLayersInTrackPattern) {
126+
setPattern(getPattern() | (pattern << ExtendedPatternShift));
127+
}
128+
}
129+
template <int NLayers>
130+
GPUhdi() uint32_t getExtendedLayerPattern() const
131+
{
132+
const auto mask = getLayerPatternMask<NLayers>();
133+
if constexpr (NLayers <= MaxLayersInTrackPattern) {
134+
const auto pattern = (getPattern() >> ExtendedPatternShift) & mask;
135+
if (pattern) {
136+
return pattern;
137+
}
138+
}
139+
return getUserField() & mask;
140+
}
141+
GPUhdi() void clearExtendedLayerPattern()
142+
{
143+
setUserField(0);
144+
getParamOut().setUserField(0);
145+
}
146+
GPUhdi() uint32_t getLastClusterLayer() const
111147
{
112148
uint32_t r{0}, v{mPattern & ((1 << 16) - 1)};
113149
while (v >>= 1) {
114150
r++;
115151
}
116152
return r;
117153
}
118-
uint32_t getFirstClusterLayer() const
154+
GPUhdi() uint32_t getFirstClusterLayer() const
119155
{
120156
int s{0};
121157
while (!(mPattern & (1 << s))) {

DataFormats/Detectors/ITSMFT/common/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ o2_target_root_dictionary(DataFormatsITSMFT
3535
include/DataFormatsITSMFT/GBTCalibData.h
3636
include/DataFormatsITSMFT/NoiseMap.h
3737
include/DataFormatsITSMFT/TimeDeadMap.h
38+
include/DataFormatsITSMFT/StuckPixelData.h
3839
include/DataFormatsITSMFT/Cluster.h
3940
include/DataFormatsITSMFT/CompCluster.h
4041
include/DataFormatsITSMFT/ClusterPattern.h

0 commit comments

Comments
 (0)