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