Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:10:46

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