Back to home page

sPhenix code displayed by LXR

 
 

    


File indexing completed on 2025-08-05 08:09:28

0001 // This file is part of the Acts project.
0002 //
0003 // Copyright (C) 2016-2018 CERN for the benefit of the Acts project
0004 //
0005 // This Source Code Form is subject to the terms of the Mozilla Public
0006 // License, v. 2.0. If a copy of the MPL was not distributed with this
0007 // file, You can obtain one at http://mozilla.org/MPL/2.0/.
0008 
0009 #pragma once
0010 
0011 #include "Acts/Definitions/Algebra.hpp"
0012 #include "Acts/Utilities/BinningData.hpp"
0013 #include "Acts/Utilities/BinningType.hpp"
0014 #include "Acts/Utilities/Enumerate.hpp"
0015 
0016 #include <array>
0017 #include <cstddef>
0018 #include <iostream>
0019 #include <iterator>
0020 #include <memory>
0021 #include <string>
0022 #include <vector>
0023 
0024 namespace Acts {
0025 
0026 /// @class BinUtility
0027 ///
0028 /// The BinUtility class that translated global and local position into a bins
0029 /// of a BinnedArray, most performant is equidistant binning without a
0030 /// transform,
0031 /// however, optionally a transform can be provided, e.g. for binning on shifted
0032 /// object, the transform is usually shared with the geometric object the Array
0033 /// is
0034 /// defined on, for performance reasons, also the inverse transform is stored.
0035 ///
0036 class BinUtility {
0037  public:
0038   /// Constructor for equidistant
0039   BinUtility()
0040       : m_binningData(),
0041         m_transform(Transform3::Identity()),
0042         m_itransform(Transform3::Identity()) {
0043     m_binningData.reserve(3);
0044   }
0045 
0046   /// Constructor with only a Transform3
0047   ///
0048   /// @param tForm is the local to global transform
0049   BinUtility(const Transform3& tForm)
0050       : m_binningData(), m_transform(tForm), m_itransform(tForm.inverse()) {
0051     m_binningData.reserve(3);
0052   }
0053 
0054   /// Constructor from BinningData directly
0055   ///
0056   /// @param bData is the provided binning data
0057   /// @param tForm is the (optional) transform
0058   BinUtility(const BinningData& bData,
0059              const Transform3& tForm = Transform3::Identity())
0060       : m_binningData(), m_transform(tForm), m_itransform(tForm.inverse()) {
0061     m_binningData.reserve(3);
0062     m_binningData.push_back(bData);
0063   }
0064 
0065   /// Constructor for equidistant
0066   ///
0067   /// @param bins is the number of bins
0068   /// @param min in the minimal value
0069   /// @param max is the maximal value
0070   /// @param opt is the binning option : open, closed
0071   /// @param value is the binninb value : binX, binY, binZ, etc.
0072   /// @param tForm is the (optional) transform
0073   BinUtility(std::size_t bins, float min, float max, BinningOption opt = open,
0074              BinningValue value = binX,
0075              const Transform3& tForm = Transform3::Identity())
0076       : m_binningData(), m_transform(tForm), m_itransform(tForm.inverse()) {
0077     m_binningData.reserve(3);
0078     m_binningData.push_back(BinningData(opt, value, bins, min, max));
0079   }
0080 
0081   /// Constructor for arbitrary
0082   ///
0083   /// @param bValues is the boundary values of the binning
0084   /// @param opt is the binning option : open, closed
0085   /// @param value is the binninb value : binX, binY, binZ, etc.
0086   /// @param tForm is the (optional) transform
0087   BinUtility(std::vector<float>& bValues, BinningOption opt = open,
0088              BinningValue value = binPhi,
0089              const Transform3& tForm = Transform3::Identity())
0090       : m_binningData(), m_transform(tForm), m_itransform(tForm.inverse()) {
0091     m_binningData.reserve(3);
0092     m_binningData.push_back(BinningData(opt, value, bValues));
0093   }
0094 
0095   /// Copy constructor
0096   ///
0097   /// @param sbu is the source bin utility
0098   BinUtility(const BinUtility& sbu) = default;
0099 
0100   BinUtility(BinUtility&& sbu) = default;
0101 
0102   /// Assignment operator
0103   ///
0104   /// @param sbu is the source bin utility
0105   BinUtility& operator=(const BinUtility& sbu) {
0106     if (this != &sbu) {
0107       m_binningData = sbu.m_binningData;
0108       m_transform = sbu.m_transform;
0109       m_itransform = sbu.m_itransform;
0110     }
0111     return (*this);
0112   }
0113 
0114   BinUtility& operator=(BinUtility&&) = default;
0115 
0116   /// Operator+= to make multidimensional BinUtility
0117   ///
0118   /// @param gbu is the additional BinUtility to be chosen
0119   BinUtility& operator+=(const BinUtility& gbu) {
0120     const std::vector<BinningData>& bData = gbu.binningData();
0121 
0122     m_transform = m_transform * gbu.transform();
0123     m_itransform = m_transform.inverse();
0124     if (m_binningData.size() + bData.size() > 3) {
0125       throw "BinUtility does not support dim > 3";
0126     }
0127     m_binningData.insert(m_binningData.end(), bData.begin(), bData.end());
0128     return (*this);
0129   }
0130 
0131   /// Virtual Destructor
0132   ~BinUtility() = default;
0133 
0134   /// Equality operator
0135   bool operator==(const BinUtility& other) const {
0136     return (m_transform.isApprox(other.m_transform) &&
0137             m_binningData == other.binningData());
0138   }
0139 
0140   /// Return the binning data vector
0141   const std::vector<BinningData>& binningData() const { return m_binningData; }
0142 
0143   /// Return the total number of bins
0144   std::size_t bins() const { return bins(0) * bins(1) * bins(2); }
0145 
0146   /// Bin-triple fast access
0147   ///
0148   /// - calculate the bin triple with one transform
0149   ///
0150   /// @param position is the 3D position to be evaluated
0151   ///
0152   /// @return is the bin value in 3D
0153   std::array<std::size_t, 3> binTriple(const Vector3& position) const {
0154     /// transform or not
0155     const Vector3 bPosition = m_itransform * position;
0156     // get the dimension
0157     std::size_t mdim = m_binningData.size();
0158     /// now get the bins
0159     std::size_t bin0 = m_binningData[0].searchGlobal(bPosition);
0160     std::size_t bin1 = mdim > 1 ? m_binningData[1].searchGlobal(bPosition) : 0;
0161     std::size_t bin2 = mdim > 2 ? m_binningData[2].searchGlobal(bPosition) : 0;
0162     /// return the triple
0163     return {{bin0, bin1, bin2}};
0164   }
0165 
0166   /// Bin from a 3D vector (already in binning frame)
0167   ///
0168   /// @param position is the 3D position to be evaluated
0169   /// @param ba is the bin dimension
0170   ///
0171   /// @return is the bin value
0172   std::size_t bin(const Vector3& position, std::size_t ba = 0) const {
0173     if (ba >= m_binningData.size()) {
0174       return 0;
0175     }
0176     std::size_t bEval = m_binningData[ba].searchGlobal(m_itransform * position);
0177     return bEval;
0178   }
0179 
0180   /// Return the other direction for fast interlinking
0181   ///
0182   /// @param position is the global position for the next search
0183   /// @param direction is the global position for the next search
0184   /// @param ba is the bin accessor
0185   ///
0186   /// @todo the
0187   ///
0188   /// @return the next bin
0189   int nextDirection(const Vector3& position, const Vector3& direction,
0190                     std::size_t ba = 0) const {
0191     if (ba >= m_binningData.size()) {
0192       return 0;
0193     }
0194     return m_binningData[ba].nextDirection(position, direction);
0195   }
0196 
0197   /// Bin from a 2D vector (following local parameters defintitions)
0198   /// - no optional transform applied
0199   /// - USE WITH CARE !!
0200   ///
0201   /// You need to make sure that the local position is actually in the binning
0202   /// frame of the BinUtility
0203   ///
0204   /// @param lposition is the local position to be set
0205   /// @param ba is the bin dimension
0206   ///
0207   /// @return bin calculated from local
0208   std::size_t bin(const Vector2& lposition, std::size_t ba = 0) const {
0209     if (ba >= m_binningData.size()) {
0210       return 0;
0211     }
0212     return m_binningData[ba].searchLocal(lposition);
0213   }
0214   /// Check if bin is inside from Vector2 - optional transform applied
0215   ///
0216   /// @param position is the global position to be evaluated
0217   /// @return is a boolean check
0218   bool inside(const Vector3& position) const {
0219     /// transform or not
0220     const Vector3& bPosition = m_itransform * position;
0221     // loop and break
0222     for (auto& bData : m_binningData) {
0223       if (!(bData.inside(bPosition))) {
0224         return false;
0225       }
0226     }
0227     // survived all the checks
0228     return true;
0229   }
0230 
0231   /// First bin maximal value
0232   /// @return the dimension of the binning data
0233   std::size_t dimensions() const { return m_binningData.size(); }
0234 
0235   /// First bin maximal value
0236   ///
0237   /// @param ba is the binaccessor
0238   ///
0239   /// @return std::size_t is the maximal bin of the accessor entry
0240   std::size_t max(std::size_t ba = 0) const {
0241     if (ba >= m_binningData.size()) {
0242       return 0;
0243     }
0244     return (m_binningData[ba].bins() - 1);
0245   }
0246 
0247   /// Number of bins
0248   ///
0249   /// @param ba is the binaccessor
0250   ///
0251   /// @return std::size_t is the bins of the accessor entry
0252   std::size_t bins(std::size_t ba) const {
0253     if (ba >= m_binningData.size()) {
0254       return 1;
0255     }
0256     return (m_binningData[ba].bins());
0257   }
0258 
0259   /// Transform applied to global positions before lookup
0260   ///
0261   /// @return Shared pointer to transform
0262   const Transform3& transform() const { return m_transform; }
0263 
0264   /// The type/value of the binning
0265   ///
0266   /// @param ba is the binaccessor
0267   ///
0268   /// @return the binning value of the accessor entry
0269   BinningValue binningValue(std::size_t ba = 0) const {
0270     if (ba >= m_binningData.size()) {
0271       throw "dimension out of bounds";
0272     }
0273     return (m_binningData[ba].binvalue);
0274   }
0275 
0276   /// Serialize the bin triple
0277   /// - this creates a simple std::size_t from a triple object
0278   ///
0279   /// @param bin is the bin to be serialized
0280   std::size_t serialize(const std::array<std::size_t, 3>& bin) const {
0281     std::size_t serializedBin = bin[0];
0282     if (m_binningData.size() == 2) {
0283       serializedBin += bin[1] * m_binningData[0].bins();
0284     } else if (m_binningData.size() == 3) {
0285       serializedBin +=
0286           (bin[1] * m_binningData[0].bins() * bin[2] * m_binningData[1].bins());
0287     }
0288     return serializedBin;
0289   }
0290 
0291   /// Output Method for std::ostream, to be overloaded by child classes
0292   ///
0293   /// @param sl is the ostream to be dumped into
0294   /// @param indent the current indentation
0295   ///
0296   /// @return the input stream
0297   std::ostream& toStream(std::ostream& sl,
0298                          const std::string& indent = "") const {
0299     sl << indent << "BinUtility for " << m_binningData.size()
0300        << "- dimensional array:" << std::endl;
0301     for (auto [ibd, bd] : enumerate(m_binningData)) {
0302       sl << indent << "dimension     : " << ibd << std::endl;
0303       sl << bd.toString(indent) << std::endl;
0304     }
0305     return sl;
0306   }
0307 
0308   /// Output into a string
0309   ///
0310   /// @param indent the current indentation
0311   ///
0312   /// @return a string with the stream information
0313   std::string toString(const std::string& indent = "") const {
0314     std::stringstream ss;
0315     toStream(ss, indent);
0316     return ss.str();
0317   }
0318 
0319  private:
0320   std::vector<BinningData> m_binningData;  /// vector of BinningData
0321   Transform3 m_transform;                  /// shared transform
0322   Transform3 m_itransform;                 /// unique inverse transform
0323 };
0324 
0325 /// Overload of << operator for std::ostream for debug output
0326 std::ostream& operator<<(std::ostream& sl, const BinUtility& bgen);
0327 
0328 }  // namespace Acts