Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-06-30 08:06:51

0001 // This file is part of the Acts project.
0002 //
0003 // Copyright (C) 2023 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/Definitions/Common.hpp"
0013 #include "Acts/Utilities/AxisFwd.hpp"
0014 #include "Acts/Utilities/BinUtility.hpp"
0015 #include "Acts/Utilities/BinningType.hpp"
0016 
0017 #include <sstream>
0018 #include <stdexcept>
0019 #include <string>
0020 #include <vector>
0021 
0022 namespace Acts::Experimental {
0023 
0024 /// @brief  Simple helper class to define a binning structure
0025 ///
0026 /// @note no checks are performed on the consistency, this is
0027 /// only for convenience that the binning can be defined and then
0028 /// translated into concrete axis types
0029 struct ProtoBinning {
0030   /// The binning value of this
0031   BinningValue binValue;
0032   /// The axis type: equidistant or variable
0033   Acts::AxisType axisType = Acts::AxisType::Equidistant;
0034   /// The axis boundary type: Open, Bound or Closed
0035   Acts::AxisBoundaryType boundaryType = Acts::AxisBoundaryType::Bound;
0036   /// The binning edges
0037   std::vector<ActsScalar> edges = {};
0038   /// An expansion for the filling (in bins)
0039   std::size_t expansion = 0u;
0040   /// Indication if this is an auto-range binning
0041   bool autorange = false;
0042 
0043   /// Convenience constructors - for variable binning
0044   ///
0045   /// @param bValue the value/cast in which this is binned
0046   /// @param bType the axis boundary type
0047   /// @param e the bin edges (variable binning)
0048   /// @param exp the expansion (in bins)
0049   ProtoBinning(BinningValue bValue, Acts::AxisBoundaryType bType,
0050                const std::vector<ActsScalar>& e, std::size_t exp = 0u)
0051       : binValue(bValue),
0052         axisType(Acts::AxisType::Variable),
0053         boundaryType(bType),
0054         edges(e),
0055         expansion(exp) {
0056     if (edges.size() < 2u) {
0057       throw std::invalid_argument(
0058           "ProtoBinning: Invalid binning, at least two edges are needed.");
0059     }
0060   }
0061 
0062   /// Convenience constructors - for equidistant binning
0063   ///
0064   /// @param bValue the value/cast in which this is binned
0065   /// @param bType the axis boundary type
0066   /// @param minE the lowest edge of the binning
0067   /// @param maxE the highest edge of the binning
0068   /// @param nbins the number of bins
0069   /// @param exp the expansion (in bins)
0070   ProtoBinning(BinningValue bValue, Acts::AxisBoundaryType bType,
0071                ActsScalar minE, ActsScalar maxE, std::size_t nbins,
0072                std::size_t exp = 0u)
0073       : binValue(bValue), boundaryType(bType), expansion(exp) {
0074     if (minE >= maxE) {
0075       std::string msg = "ProtoBinning: Invalid binning for value '";
0076       msg += binningValueName(bValue);
0077       msg += "', min edge (" + std::to_string(minE) + ") ";
0078       msg += " needs to be smaller than max edge (";
0079       msg += std::to_string(maxE) + ").";
0080       throw std::invalid_argument(msg);
0081     }
0082     if (nbins < 1u) {
0083       throw std::invalid_argument(
0084           "ProtoBinning: Invalid binning, at least one bin is needed.");
0085     }
0086 
0087     ActsScalar stepE = (maxE - minE) / nbins;
0088     edges.reserve(nbins + 1);
0089     for (std::size_t i = 0; i <= nbins; i++) {
0090       edges.push_back(minE + i * stepE);
0091     }
0092   }
0093 
0094   /// Placeholder constructors - for equidistant binning
0095   ///
0096   /// @note this is designed to give a binning prescription
0097   /// when the actual extent is not yet evaluated, only works
0098   /// for equidistant binning obviously
0099   ///
0100   /// @param bValue the value/cast in which this is binned
0101   /// @param bType the axis boundary type
0102   /// @param nbins the number of bins
0103   /// @param exp the expansion (in bins)
0104   ProtoBinning(BinningValue bValue, Acts::AxisBoundaryType bType,
0105                std::size_t nbins, std::size_t exp = 0u)
0106       : binValue(bValue),
0107         boundaryType(bType),
0108         edges(nbins + 1, 0.),
0109         expansion(exp),
0110         autorange(true) {}
0111 
0112   // Return the number of bins
0113   std::size_t bins() const { return edges.size() - 1u; }
0114 
0115   // Screen output
0116   std::string toString() const {
0117     std::stringstream ss;
0118     ss << "ProtoBinning: " << bins() << " bins in "
0119        << binningValueName(binValue);
0120     ss << (axisType == Acts::AxisType::Variable ? ", variable "
0121                                                 : ", equidistant ");
0122     if (!autorange) {
0123       ss << "within [" << edges.front() << ", " << edges.back() << "] ";
0124     } else {
0125       ss << "within automatic range";
0126     }
0127     return ss.str();
0128   }
0129 };
0130 
0131 /// @brief A binning description, it helps for screen output
0132 struct BinningDescription {
0133   /// Convert the binning description into a bin utility
0134   ///
0135   /// @param binUtility the bin utility to be converted into a BinningDescription
0136   static BinningDescription fromBinUtility(const BinUtility& binUtility) {
0137     BinningDescription bDesc;
0138     for (const auto& bData : binUtility.binningData()) {
0139       // One proto binning per binning data
0140       Acts::AxisBoundaryType boundaryType =
0141           bData.option == open ? Acts::AxisBoundaryType::Bound
0142                                : Acts::AxisBoundaryType::Closed;
0143       std::vector<ActsScalar> edges;
0144       if (bData.type == equidistant) {
0145         bDesc.binning.push_back(ProtoBinning(bData.binvalue, boundaryType,
0146                                              bData.min, bData.max, bData.bins(),
0147                                              0u));
0148 
0149       } else {
0150         std::for_each(bData.boundaries().begin(), bData.boundaries().end(),
0151                       [&](ActsScalar edge) { edges.push_back(edge); });
0152         bDesc.binning.push_back(
0153             ProtoBinning(bData.binvalue, boundaryType, edges, 0u));
0154       }
0155     }
0156     return bDesc;
0157   }
0158 
0159   /// Convert to a BinUtility - only basic types are supported
0160   ///
0161   BinUtility toBinUtility() const {
0162     BinUtility binUtility;
0163     for (const auto& b : binning) {
0164       Acts::BinningOption bOption =
0165           b.boundaryType == Acts::AxisBoundaryType::Bound ? Acts::open
0166                                                           : Acts::closed;
0167       if (b.axisType == Acts::AxisType::Equidistant) {
0168         binUtility += BinUtility(b.bins(), b.edges.front(), b.edges.back(),
0169                                  bOption, b.binValue);
0170       } else {
0171         std::vector<float> edges;
0172         std::for_each(b.edges.begin(), b.edges.end(),
0173                       [&](ActsScalar edge) { edges.push_back(edge); });
0174         binUtility += BinUtility(edges, bOption, b.binValue);
0175       }
0176     }
0177     return binUtility;
0178   }
0179 
0180   /// The contained binnings
0181   std::vector<ProtoBinning> binning;
0182 
0183   // Screen output
0184   std::string toString() const {
0185     std::stringstream ss;
0186     ss << "BinningDescription: " << binning.size() << "D" << std::endl;
0187     for (const auto& b : binning) {
0188       ss << "  " << b.toString() << std::endl;
0189     }
0190     return ss.str();
0191   }
0192 };
0193 
0194 }  // namespace Acts::Experimental