File indexing completed on 2026-08-12 08:20:49
0001
0002
0003
0004
0005
0006
0007
0008
0009 #pragma once
0010
0011 #include "Acts/Definitions/Algebra.hpp"
0012 #include "Acts/Utilities/AxisDefinitions.hpp"
0013 #include "Acts/Utilities/BinningData.hpp"
0014 #include "Acts/Utilities/BinningType.hpp"
0015 #include "Acts/Utilities/Enumerate.hpp"
0016 #include "Acts/Utilities/IMultiAxis.hpp"
0017 #include "Acts/Utilities/ProtoAxis.hpp"
0018
0019 #include <algorithm>
0020 #include <array>
0021 #include <cstddef>
0022 #include <iostream>
0023 #include <stdexcept>
0024 #include <string>
0025 #include <vector>
0026
0027 namespace Acts {
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039 class BinUtility {
0040 public:
0041
0042 BinUtility()
0043 : m_binningData(),
0044 m_transform(Transform3::Identity()),
0045 m_itransform(Transform3::Identity()) {
0046 m_binningData.reserve(3);
0047 }
0048
0049
0050
0051
0052 explicit BinUtility(const Transform3& tForm)
0053 : m_binningData(), m_transform(tForm), m_itransform(tForm.inverse()) {
0054 m_binningData.reserve(3);
0055 }
0056
0057
0058
0059
0060
0061 explicit BinUtility(const BinningData& bData,
0062 const Transform3& tForm = Transform3::Identity())
0063 : m_binningData(), m_transform(tForm), m_itransform(tForm.inverse()) {
0064 m_binningData.reserve(3);
0065 m_binningData.emplace_back(bData);
0066 }
0067
0068
0069
0070
0071
0072
0073
0074
0075
0076 BinUtility(std::size_t bins, float min, float max, BinningOption opt = open,
0077 AxisDirection value = AxisDirection::AxisX,
0078 const Transform3& tForm = Transform3::Identity())
0079 : m_binningData(), m_transform(tForm), m_itransform(tForm.inverse()) {
0080 m_binningData.reserve(3);
0081 m_binningData.emplace_back(opt, value, bins, min, max);
0082 }
0083
0084
0085
0086
0087
0088
0089
0090 explicit BinUtility(std::vector<float>& bValues, BinningOption opt = open,
0091 AxisDirection value = AxisDirection::AxisPhi,
0092 const Transform3& tForm = Transform3::Identity())
0093 : m_binningData(), m_transform(tForm), m_itransform(tForm.inverse()) {
0094 m_binningData.reserve(3);
0095 m_binningData.emplace_back(opt, value, bValues);
0096 }
0097
0098
0099
0100
0101 explicit BinUtility(const IAxis& axis)
0102 : m_binningData(),
0103 m_transform(Transform3::Identity()),
0104 m_itransform(Transform3::Identity()) {
0105 m_binningData.reserve(3);
0106 m_binningData.emplace_back(axis);
0107 }
0108
0109
0110
0111
0112 explicit BinUtility(const IMultiAxis& axes)
0113 : m_binningData(),
0114 m_transform(Transform3::Identity()),
0115 m_itransform(Transform3::Identity()) {
0116 m_binningData.reserve(3);
0117 for (const IAxis& axis : axes) {
0118 m_binningData.emplace_back(axis);
0119 }
0120 }
0121
0122
0123
0124
0125
0126 [[deprecated("Use BinUtility(const IAxis&) with a directed axis instead")]]
0127 explicit BinUtility(const DirectedProtoAxis& dpAxis)
0128 : m_binningData(),
0129 m_transform(Transform3::Identity()),
0130 m_itransform(Transform3::Identity()) {
0131 m_binningData.reserve(3);
0132 m_binningData.emplace_back(dpAxis);
0133 }
0134
0135
0136
0137
0138 explicit BinUtility(const std::vector<DirectedProtoAxis>& dpAxes)
0139 : m_binningData(),
0140 m_transform(Transform3::Identity()),
0141 m_itransform(Transform3::Identity()) {
0142 m_binningData.reserve(3);
0143 for (const auto& dpAxis : dpAxes) {
0144 m_binningData.emplace_back(dpAxis);
0145 }
0146 }
0147
0148
0149
0150
0151
0152 BinUtility& operator+=(const BinUtility& gbu) {
0153 const std::vector<BinningData>& bData = gbu.binningData();
0154
0155 m_transform = m_transform * gbu.transform();
0156 m_itransform = m_transform.inverse();
0157 if (m_binningData.size() + bData.size() > 3) {
0158 throw std::runtime_error{"BinUtility does not support dim > 3"};
0159 }
0160 m_binningData.insert(m_binningData.end(), bData.begin(), bData.end());
0161 return (*this);
0162 }
0163
0164
0165
0166
0167 bool operator==(const BinUtility& other) const {
0168 return (m_transform.isApprox(other.m_transform) &&
0169 m_binningData == other.binningData());
0170 }
0171
0172
0173
0174 const std::vector<BinningData>& binningData() const { return m_binningData; }
0175
0176
0177
0178 std::size_t bins() const { return bins(0) * bins(1) * bins(2); }
0179
0180
0181
0182
0183
0184
0185
0186
0187 std::array<std::size_t, 3> binTriple(const Vector3& position) const {
0188
0189 const Vector3 bPosition = m_itransform * position;
0190
0191 std::size_t mdim = m_binningData.size();
0192
0193 std::size_t bin0 = m_binningData[0].searchGlobal(bPosition);
0194 std::size_t bin1 = mdim > 1 ? m_binningData[1].searchGlobal(bPosition) : 0;
0195 std::size_t bin2 = mdim > 2 ? m_binningData[2].searchGlobal(bPosition) : 0;
0196
0197 return {{bin0, bin1, bin2}};
0198 }
0199
0200
0201
0202
0203
0204
0205
0206 std::size_t bin(const Vector3& position, std::size_t ba = 0) const {
0207 if (ba >= m_binningData.size()) {
0208 return 0;
0209 }
0210 std::size_t bEval = m_binningData[ba].searchGlobal(m_itransform * position);
0211 return bEval;
0212 }
0213
0214
0215
0216
0217
0218
0219
0220
0221
0222
0223
0224
0225 std::size_t bin(const Vector2& lposition, std::size_t ba = 0) const {
0226 if (ba >= m_binningData.size()) {
0227 return 0;
0228 }
0229 return m_binningData[ba].searchLocal(lposition);
0230 }
0231
0232
0233
0234
0235
0236
0237
0238
0239
0240
0241
0242
0243 std::size_t bin(float value, std::size_t ba = 0) const {
0244 if (ba >= m_binningData.size()) {
0245 return 0;
0246 }
0247 return m_binningData[ba].search(value);
0248 }
0249
0250
0251
0252
0253
0254
0255
0256
0257
0258
0259 int nextDirection(const Vector3& position, const Vector3& direction,
0260 std::size_t ba = 0) const {
0261 if (ba >= m_binningData.size()) {
0262 return 0;
0263 }
0264 return m_binningData[ba].nextDirection(position, direction);
0265 }
0266
0267
0268
0269
0270
0271 bool inside(const Vector3& position) const {
0272
0273 const Vector3& bPosition = m_itransform * position;
0274 return std::ranges::all_of(m_binningData, [&](const auto& bData) {
0275 return bData.inside(bPosition);
0276 });
0277 }
0278
0279
0280
0281 std::size_t dimensions() const { return m_binningData.size(); }
0282
0283
0284
0285
0286
0287
0288 std::size_t max(std::size_t ba = 0) const {
0289 if (ba >= m_binningData.size()) {
0290 return 0;
0291 }
0292 return (m_binningData[ba].bins() - 1);
0293 }
0294
0295
0296
0297
0298
0299
0300 std::size_t bins(std::size_t ba) const {
0301 if (ba >= m_binningData.size()) {
0302 return 1;
0303 }
0304 return (m_binningData[ba].bins());
0305 }
0306
0307
0308
0309
0310 const Transform3& transform() const { return m_transform; }
0311
0312
0313
0314
0315
0316
0317 AxisDirection binningValue(std::size_t ba = 0) const {
0318 if (ba >= m_binningData.size()) {
0319 throw std::runtime_error{"Dimension out of bounds"};
0320 }
0321 return (m_binningData[ba].binvalue);
0322 }
0323
0324
0325
0326
0327
0328
0329 std::size_t serialize(const std::array<std::size_t, 3>& bin) const {
0330 std::size_t serializedBin = bin[0];
0331 if (m_binningData.size() == 2) {
0332 serializedBin += bin[1] * m_binningData[0].bins();
0333 } else if (m_binningData.size() == 3) {
0334 serializedBin +=
0335 (bin[1] * m_binningData[0].bins() * bin[2] * m_binningData[1].bins());
0336 }
0337 return serializedBin;
0338 }
0339
0340
0341
0342
0343
0344
0345
0346 std::ostream& toStream(std::ostream& sl,
0347 const std::string& indent = "") const {
0348 sl << indent << "BinUtility for " << m_binningData.size()
0349 << "- dimensional array:" << std::endl;
0350 for (auto [ibd, bd] : enumerate(m_binningData)) {
0351 sl << indent << "dimension : " << ibd << std::endl;
0352 sl << bd.toString(indent) << std::endl;
0353 }
0354 return sl;
0355 }
0356
0357
0358
0359
0360
0361
0362 std::string toString(const std::string& indent = "") const {
0363 std::stringstream ss;
0364 toStream(ss, indent);
0365 return ss.str();
0366 }
0367
0368
0369 friend std::ostream& operator<<(std::ostream& sl, const BinUtility& bgen) {
0370 return bgen.toStream(sl);
0371 }
0372
0373 private:
0374 std::vector<BinningData> m_binningData;
0375 Transform3 m_transform;
0376 Transform3 m_itransform;
0377 };
0378
0379 }