File indexing completed on 2026-05-14 07:40:07
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/ProtoAxis.hpp"
0017
0018 #include <algorithm>
0019 #include <array>
0020 #include <cstddef>
0021 #include <iostream>
0022 #include <iterator>
0023 #include <memory>
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 BinUtility(const BinUtility& sbu) = default;
0103
0104
0105
0106 BinUtility(BinUtility&& sbu) = default;
0107
0108
0109
0110
0111 explicit BinUtility(const DirectedProtoAxis& dpAxis)
0112 : m_binningData(),
0113 m_transform(Transform3::Identity()),
0114 m_itransform(Transform3::Identity()) {
0115 m_binningData.reserve(3);
0116 m_binningData.emplace_back(dpAxis);
0117 }
0118
0119
0120
0121
0122 explicit BinUtility(const std::vector<DirectedProtoAxis>& dpAxes)
0123 : m_binningData(),
0124 m_transform(Transform3::Identity()),
0125 m_itransform(Transform3::Identity()) {
0126 m_binningData.reserve(3);
0127 for (const auto& dpAxis : dpAxes) {
0128 m_binningData.emplace_back(dpAxis);
0129 }
0130 }
0131
0132
0133
0134
0135
0136 BinUtility& operator=(const BinUtility& sbu) {
0137 if (this != &sbu) {
0138 m_binningData = sbu.m_binningData;
0139 m_transform = sbu.m_transform;
0140 m_itransform = sbu.m_itransform;
0141 }
0142 return (*this);
0143 }
0144
0145
0146
0147 BinUtility& operator=(BinUtility&&) = default;
0148
0149
0150
0151
0152
0153 BinUtility& operator+=(const BinUtility& gbu) {
0154 const std::vector<BinningData>& bData = gbu.binningData();
0155
0156 m_transform = m_transform * gbu.transform();
0157 m_itransform = m_transform.inverse();
0158 if (m_binningData.size() + bData.size() > 3) {
0159 throw std::runtime_error{"BinUtility does not support dim > 3"};
0160 }
0161 m_binningData.insert(m_binningData.end(), bData.begin(), bData.end());
0162 return (*this);
0163 }
0164
0165
0166 ~BinUtility() = default;
0167
0168
0169
0170
0171 bool operator==(const BinUtility& other) const {
0172 return (m_transform.isApprox(other.m_transform) &&
0173 m_binningData == other.binningData());
0174 }
0175
0176
0177
0178 const std::vector<BinningData>& binningData() const { return m_binningData; }
0179
0180
0181
0182 std::size_t bins() const { return bins(0) * bins(1) * bins(2); }
0183
0184
0185
0186
0187
0188
0189
0190
0191 std::array<std::size_t, 3> binTriple(const Vector3& position) const {
0192
0193 const Vector3 bPosition = m_itransform * position;
0194
0195 std::size_t mdim = m_binningData.size();
0196
0197 std::size_t bin0 = m_binningData[0].searchGlobal(bPosition);
0198 std::size_t bin1 = mdim > 1 ? m_binningData[1].searchGlobal(bPosition) : 0;
0199 std::size_t bin2 = mdim > 2 ? m_binningData[2].searchGlobal(bPosition) : 0;
0200
0201 return {{bin0, bin1, bin2}};
0202 }
0203
0204
0205
0206
0207
0208
0209
0210 std::size_t bin(const Vector3& position, std::size_t ba = 0) const {
0211 if (ba >= m_binningData.size()) {
0212 return 0;
0213 }
0214 std::size_t bEval = m_binningData[ba].searchGlobal(m_itransform * position);
0215 return bEval;
0216 }
0217
0218
0219
0220
0221
0222
0223
0224
0225
0226
0227 int nextDirection(const Vector3& position, const Vector3& direction,
0228 std::size_t ba = 0) const {
0229 if (ba >= m_binningData.size()) {
0230 return 0;
0231 }
0232 return m_binningData[ba].nextDirection(position, direction);
0233 }
0234
0235
0236
0237
0238
0239
0240
0241
0242
0243
0244
0245
0246 std::size_t bin(const Vector2& lposition, std::size_t ba = 0) const {
0247 if (ba >= m_binningData.size()) {
0248 return 0;
0249 }
0250 return m_binningData[ba].searchLocal(lposition);
0251 }
0252
0253
0254
0255
0256 bool inside(const Vector3& position) const {
0257
0258 const Vector3& bPosition = m_itransform * position;
0259 return std::ranges::all_of(m_binningData, [&](const auto& bData) {
0260 return bData.inside(bPosition);
0261 });
0262 }
0263
0264
0265
0266 std::size_t dimensions() const { return m_binningData.size(); }
0267
0268
0269
0270
0271
0272
0273 std::size_t max(std::size_t ba = 0) const {
0274 if (ba >= m_binningData.size()) {
0275 return 0;
0276 }
0277 return (m_binningData[ba].bins() - 1);
0278 }
0279
0280
0281
0282
0283
0284
0285 std::size_t bins(std::size_t ba) const {
0286 if (ba >= m_binningData.size()) {
0287 return 1;
0288 }
0289 return (m_binningData[ba].bins());
0290 }
0291
0292
0293
0294
0295 const Transform3& transform() const { return m_transform; }
0296
0297
0298
0299
0300
0301
0302 AxisDirection binningValue(std::size_t ba = 0) const {
0303 if (ba >= m_binningData.size()) {
0304 throw std::runtime_error{"Dimension out of bounds"};
0305 }
0306 return (m_binningData[ba].binvalue);
0307 }
0308
0309
0310
0311
0312
0313
0314 std::size_t serialize(const std::array<std::size_t, 3>& bin) const {
0315 std::size_t serializedBin = bin[0];
0316 if (m_binningData.size() == 2) {
0317 serializedBin += bin[1] * m_binningData[0].bins();
0318 } else if (m_binningData.size() == 3) {
0319 serializedBin +=
0320 (bin[1] * m_binningData[0].bins() * bin[2] * m_binningData[1].bins());
0321 }
0322 return serializedBin;
0323 }
0324
0325
0326
0327
0328
0329
0330
0331 std::ostream& toStream(std::ostream& sl,
0332 const std::string& indent = "") const {
0333 sl << indent << "BinUtility for " << m_binningData.size()
0334 << "- dimensional array:" << std::endl;
0335 for (auto [ibd, bd] : enumerate(m_binningData)) {
0336 sl << indent << "dimension : " << ibd << std::endl;
0337 sl << bd.toString(indent) << std::endl;
0338 }
0339 return sl;
0340 }
0341
0342
0343
0344
0345
0346
0347 std::string toString(const std::string& indent = "") const {
0348 std::stringstream ss;
0349 toStream(ss, indent);
0350 return ss.str();
0351 }
0352
0353
0354 friend std::ostream& operator<<(std::ostream& sl, const BinUtility& bgen) {
0355 return bgen.toStream(sl);
0356 }
0357
0358 private:
0359 std::vector<BinningData> m_binningData;
0360 Transform3 m_transform;
0361 Transform3 m_itransform;
0362 };
0363
0364 }