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