File indexing completed on 2025-08-05 08:09:28
0001
0002
0003
0004
0005
0006
0007
0008
0009 #pragma once
0010
0011 #include "Acts/Definitions/Algebra.hpp"
0012 #include "Acts/Utilities/BinningType.hpp"
0013 #include "Acts/Utilities/ThrowAssert.hpp"
0014 #include "Acts/Utilities/VectorHelpers.hpp"
0015
0016 #include <algorithm>
0017 #include <cmath>
0018 #include <memory>
0019 #include <sstream>
0020 #include <string>
0021 #include <utility>
0022 #include <vector>
0023
0024 namespace Acts {
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041 class BinningData {
0042 public:
0043 BinningType type{};
0044 BinningOption option{};
0045 BinningValue binvalue{};
0046 float min{};
0047 float max{};
0048 float step{};
0049 bool zdim{};
0050
0051
0052 std::unique_ptr<const BinningData> subBinningData;
0053
0054 bool subBinningAdditive{};
0055
0056
0057
0058
0059
0060
0061 BinningData(BinningValue bValue, float bMin, float bMax)
0062 : type(equidistant),
0063 option(open),
0064 binvalue(bValue),
0065 min(bMin),
0066 max(bMax),
0067 step((bMax - bMin)),
0068 zdim(true),
0069 subBinningData(nullptr),
0070 m_bins(1),
0071 m_boundaries({{min, max}}),
0072 m_totalBins(1),
0073 m_totalBoundaries(std::vector<float>()),
0074 m_functionPtr(&searchEquidistantWithBoundary) {}
0075
0076
0077
0078
0079
0080
0081
0082
0083
0084
0085
0086
0087 BinningData(BinningOption bOption, BinningValue bValue, std::size_t bBins,
0088 float bMin, float bMax,
0089 std::unique_ptr<const BinningData> sBinData = nullptr,
0090 bool sBinAdditive = false)
0091 : type(equidistant),
0092 option(bOption),
0093 binvalue(bValue),
0094 min(bMin),
0095 max(bMax),
0096 step((bMax - bMin) / bBins),
0097 zdim(bBins == 1 ? true : false),
0098 subBinningData(std::move(sBinData)),
0099 subBinningAdditive(sBinAdditive),
0100 m_bins(bBins),
0101 m_boundaries(std::vector<float>()),
0102 m_totalBins(bBins),
0103 m_totalBoundaries(std::vector<float>()) {
0104
0105 m_functionPtr = &searchEquidistantWithBoundary;
0106
0107 m_boundaries.reserve(m_bins + 1);
0108 for (std::size_t ib = 0; ib < m_bins + 1; ++ib) {
0109 m_boundaries.push_back(min + ib * step);
0110 }
0111
0112 checkSubStructure();
0113 }
0114
0115
0116
0117
0118
0119
0120
0121 BinningData(BinningOption bOption, BinningValue bValue,
0122 const std::vector<float>& bBoundaries,
0123 std::unique_ptr<const BinningData> sBinData = nullptr)
0124 : type(arbitrary),
0125 option(bOption),
0126 binvalue(bValue),
0127 zdim(bBoundaries.size() == 2 ? true : false),
0128 subBinningData(std::move(sBinData)),
0129 subBinningAdditive(true),
0130 m_bins(bBoundaries.size() - 1),
0131 m_boundaries(bBoundaries),
0132 m_totalBins(bBoundaries.size() - 1),
0133 m_totalBoundaries(bBoundaries) {
0134
0135 throw_assert(m_boundaries.size() > 1, "Must have more than one boundary");
0136 min = m_boundaries[0];
0137 max = m_boundaries[m_boundaries.size() - 1];
0138
0139 m_functionPtr = &searchInVectorWithBoundary;
0140
0141 checkSubStructure();
0142 }
0143
0144
0145
0146
0147 BinningData(const BinningData& bdata)
0148 : type(bdata.type),
0149 option(bdata.option),
0150 binvalue(bdata.binvalue),
0151 min(bdata.min),
0152 max(bdata.max),
0153 step(bdata.step),
0154 zdim(bdata.zdim),
0155 subBinningData(nullptr),
0156 subBinningAdditive(bdata.subBinningAdditive),
0157 m_bins(bdata.m_bins),
0158 m_boundaries(bdata.m_boundaries),
0159 m_totalBins(bdata.m_totalBins),
0160 m_totalBoundaries(bdata.m_totalBoundaries) {
0161
0162 subBinningData =
0163 bdata.subBinningData
0164 ? std::make_unique<const BinningData>(*bdata.subBinningData)
0165 : nullptr;
0166
0167
0168 if (type == equidistant) {
0169 m_functionPtr = &searchEquidistantWithBoundary;
0170 } else {
0171 m_functionPtr = &searchInVectorWithBoundary;
0172 }
0173 }
0174
0175
0176
0177
0178 BinningData& operator=(const BinningData& bdata) {
0179 if (this != &bdata) {
0180 type = bdata.type;
0181 option = bdata.option;
0182 binvalue = bdata.binvalue;
0183 min = bdata.min;
0184 max = bdata.max;
0185 step = bdata.step;
0186 zdim = bdata.zdim;
0187 subBinningAdditive = bdata.subBinningAdditive;
0188 subBinningData =
0189 bdata.subBinningData
0190 ? std::make_unique<const BinningData>(*bdata.subBinningData)
0191 : nullptr;
0192 m_bins = bdata.m_bins;
0193 m_boundaries = bdata.m_boundaries;
0194 m_totalBins = bdata.m_totalBins;
0195 m_totalBoundaries = bdata.m_totalBoundaries;
0196
0197 if (type == equidistant) {
0198 m_functionPtr = &searchEquidistantWithBoundary;
0199 } else {
0200 m_functionPtr = &searchInVectorWithBoundary;
0201 }
0202 }
0203 return (*this);
0204 }
0205
0206 BinningData() = default;
0207 ~BinningData() = default;
0208
0209
0210
0211
0212
0213
0214 bool operator==(const BinningData& bData) const {
0215 return (type == bData.type && option == bData.option &&
0216 binvalue == bData.binvalue && min == bData.min &&
0217 max == bData.max && step == bData.step && zdim == bData.zdim &&
0218 ((subBinningData == nullptr && bData.subBinningData == nullptr) ||
0219 (subBinningData != nullptr && bData.subBinningData != nullptr &&
0220 (*subBinningData == *bData.subBinningData))) &&
0221 subBinningAdditive == bData.subBinningAdditive);
0222 }
0223
0224
0225 std::size_t bins() const { return m_totalBins; }
0226
0227
0228
0229 const std::vector<float>& boundaries() const {
0230 if (subBinningData) {
0231 return m_totalBoundaries;
0232 }
0233 return m_boundaries;
0234 }
0235
0236
0237
0238
0239
0240
0241 float value(const Vector2& lposition) const {
0242
0243 if (binvalue == binR || binvalue == binRPhi || binvalue == binX ||
0244 binvalue == binH) {
0245 return lposition[0];
0246 }
0247 if (binvalue == binPhi) {
0248 return lposition[1];
0249 }
0250 return lposition[1];
0251 }
0252
0253
0254
0255
0256
0257
0258 float value(const Vector3& position) const {
0259 using VectorHelpers::eta;
0260 using VectorHelpers::perp;
0261 using VectorHelpers::phi;
0262
0263 if (binvalue == binR || binvalue == binH) {
0264 return (perp(position));
0265 }
0266 if (binvalue == binRPhi) {
0267 return (perp(position) * phi(position));
0268 }
0269 if (binvalue == binEta) {
0270 return (eta(position));
0271 }
0272 if (binvalue < 3) {
0273 return (position[binvalue]);
0274 }
0275
0276 return phi(position);
0277 }
0278
0279
0280
0281
0282
0283
0284 float center(std::size_t bin) const {
0285 const std::vector<float>& bvals = boundaries();
0286
0287 float value =
0288 bin < (bvals.size() - 1) ? 0.5 * (bvals[bin] + bvals[bin + 1]) : 0.;
0289 return value;
0290 }
0291
0292
0293
0294
0295
0296
0297 float width(std::size_t bin) const {
0298 const std::vector<float>& bvals = boundaries();
0299
0300 float value = bin < (bvals.size() - 1) ? bvals[bin + 1] - bvals[bin] : 0.;
0301 return value;
0302 }
0303
0304
0305
0306
0307
0308
0309 bool inside(const Vector3& position) const {
0310
0311 if (option == closed) {
0312 return true;
0313 }
0314
0315
0316 float val = value(position);
0317 return (val > min - 0.001 && val < max + 0.001);
0318 }
0319
0320
0321
0322
0323
0324
0325 bool inside(const Vector2& lposition) const {
0326
0327 if (option == closed) {
0328 return true;
0329 }
0330
0331
0332 float val = value(lposition);
0333 return (val > min - 0.001 && val < max + 0.001);
0334 }
0335
0336
0337
0338
0339
0340
0341 std::size_t searchLocal(const Vector2& lposition) const {
0342 if (zdim) {
0343 return 0;
0344 }
0345 return search(value(lposition));
0346 }
0347
0348
0349
0350
0351
0352
0353 std::size_t searchGlobal(const Vector3& position) const {
0354 if (zdim) {
0355 return 0;
0356 }
0357 return search(value(position));
0358 }
0359
0360
0361
0362
0363
0364
0365 std::size_t search(float value) const {
0366 if (zdim) {
0367 return 0;
0368 }
0369 assert(m_functionPtr != nullptr);
0370 return (!subBinningData) ? (*m_functionPtr)(value, *this)
0371 : searchWithSubStructure(value);
0372 }
0373
0374
0375
0376
0377
0378
0379
0380 std::size_t searchWithSubStructure(float value) const {
0381
0382 std::size_t masterbin = (*m_functionPtr)(value, *this);
0383
0384 if (subBinningAdditive) {
0385
0386 return masterbin + subBinningData->search(value);
0387 }
0388
0389 float gvalue =
0390 value - masterbin * (subBinningData->max - subBinningData->min);
0391
0392 std::size_t subbin = subBinningData->search(gvalue);
0393
0394 return masterbin * subBinningData->bins() + subbin;
0395 }
0396
0397
0398
0399
0400
0401
0402
0403
0404 int nextDirection(const Vector3& position, const Vector3& dir) const {
0405 if (zdim) {
0406 return 0;
0407 }
0408 float val = value(position);
0409 Vector3 probe = position + dir.normalized();
0410 float nextval = value(probe);
0411 return (nextval > val) ? 1 : -1;
0412 }
0413
0414
0415
0416
0417
0418
0419
0420
0421 float centerValue(std::size_t bin) const {
0422 if (zdim) {
0423 return 0.5 * (min + max);
0424 }
0425 float bmin = m_boundaries[bin];
0426 float bmax = bin < m_boundaries.size() ? m_boundaries[bin + 1] : max;
0427 return 0.5 * (bmin + bmax);
0428 }
0429
0430 private:
0431 std::size_t m_bins{};
0432 std::vector<float> m_boundaries;
0433 std::size_t m_totalBins{};
0434 std::vector<float> m_totalBoundaries;
0435
0436 std::size_t (*m_functionPtr)(float,
0437 const BinningData&){};
0438
0439
0440 void checkSubStructure() {
0441
0442 if (subBinningData) {
0443 m_totalBoundaries.clear();
0444
0445 if (subBinningAdditive) {
0446
0447 m_totalBins = m_bins + subBinningData->bins() - 1;
0448
0449 m_totalBoundaries.reserve(m_totalBins + 1);
0450
0451 const std::vector<float>& subBinBoundaries =
0452 subBinningData->boundaries();
0453 float sBinMin = subBinBoundaries[0];
0454
0455 std::vector<float>::const_iterator mbvalue = m_boundaries.begin();
0456 for (; mbvalue != m_boundaries.end(); ++mbvalue) {
0457
0458 if (std::abs((*mbvalue) - sBinMin) < 10e-10) {
0459
0460 m_totalBoundaries.insert(m_totalBoundaries.begin(),
0461 subBinBoundaries.begin(),
0462 subBinBoundaries.end());
0463 ++mbvalue;
0464 } else {
0465 m_totalBoundaries.push_back(*mbvalue);
0466 }
0467 }
0468 } else {
0469
0470 m_totalBins = m_bins * subBinningData->bins();
0471 m_totalBoundaries.reserve(m_totalBins + 1);
0472
0473 const std::vector<float>& subBinBoundaries =
0474 subBinningData->boundaries();
0475
0476 m_totalBoundaries.push_back(min);
0477 for (std::size_t ib = 0; ib < m_bins; ++ib) {
0478 float offset = ib * step;
0479 for (std::size_t isb = 1; isb < subBinBoundaries.size(); ++isb) {
0480 m_totalBoundaries.push_back(offset + subBinBoundaries[isb]);
0481 }
0482 }
0483 }
0484
0485 std::sort(m_totalBoundaries.begin(), m_totalBoundaries.end());
0486 }
0487 }
0488
0489
0490
0491 static std::size_t searchEquidistantWithBoundary(float value,
0492 const BinningData& bData) {
0493
0494
0495 int bin = static_cast<int>((value - bData.min) / bData.step);
0496
0497 if (bData.option == closed) {
0498 if (value < bData.min) {
0499 return (bData.m_bins - 1);
0500 }
0501 if (value > bData.max) {
0502 return 0;
0503 }
0504 }
0505
0506 bin = bin < 0 ? ((bData.option == open) ? 0 : (bData.m_bins - 1)) : bin;
0507 return std::size_t((bin <= int(bData.m_bins - 1))
0508 ? bin
0509 : ((bData.option == open) ? (bData.m_bins - 1) : 0));
0510 }
0511
0512
0513 static std::size_t searchInVectorWithBoundary(float value,
0514 const BinningData& bData) {
0515
0516 if (value <= bData.m_boundaries[0]) {
0517 return (bData.option == closed) ? (bData.m_bins - 1) : 0;
0518 }
0519
0520 if (value >= bData.max) {
0521 return (bData.option == closed) ? 0 : (bData.m_bins - 1);
0522 }
0523
0524 auto lb = std::lower_bound(bData.m_boundaries.begin(),
0525 bData.m_boundaries.end(), value);
0526 return static_cast<std::size_t>(
0527 std::distance(bData.m_boundaries.begin(), lb) - 1);
0528 }
0529
0530 public:
0531
0532
0533
0534 std::string toString(const std::string& indent) const {
0535 std::stringstream sl;
0536 sl << indent << "BinngingData object:" << '\n';
0537 sl << indent << " - type : " << std::size_t(type) << '\n';
0538 sl << indent << " - option : " << std::size_t(option) << '\n';
0539 sl << indent << " - value : " << std::size_t(binvalue) << '\n';
0540 sl << indent << " - bins : " << bins() << '\n';
0541 sl << indent << " - min/max : " << min << " / " << max << '\n';
0542 if (type == equidistant) {
0543 sl << indent << " - step : " << step << '\n';
0544 }
0545 sl << indent << " - boundaries : | ";
0546 for (const auto& b : boundaries()) {
0547 sl << b << " | ";
0548 }
0549 sl << '\n';
0550 return sl.str();
0551 }
0552 };
0553 }