|
|
|||
File indexing completed on 2026-08-16 08:16:52
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/Utilities/AxisDefinitions.hpp" 0012 #include "Acts/Utilities/IAxis.hpp" 0013 0014 #include <memory> 0015 #include <optional> 0016 #include <ostream> 0017 #include <string> 0018 #include <variant> 0019 #include <vector> 0020 0021 namespace Acts { 0022 0023 /// @brief Axis properties supplied by the consumer of an @c AxisSpec at build 0024 /// time 0025 /// 0026 /// Each property fills in the corresponding one of the spec if that is unset, 0027 /// and validates it otherwise. Spelled @c AxisSpec::Options at the use sites; 0028 /// it only lives at namespace scope so that it is complete where 0029 /// @c AxisSpec::buildAxis defaults it. 0030 struct AxisSpecOptions { 0031 /// Minimum edge of the axis 0032 std::optional<double> min = std::nullopt; 0033 /// Maximum edge of the axis 0034 std::optional<double> max = std::nullopt; 0035 /// Boundary type of the axis 0036 std::optional<AxisBoundaryType> boundaryType = std::nullopt; 0037 /// Direction of the axis 0038 std::optional<AxisDirection> direction = std::nullopt; 0039 }; 0040 0041 /// @brief Variant-like spec of an axis that builds @c IAxis objects 0042 /// 0043 /// Every property except the binning structure itself is optional. What the 0044 /// spec leaves open is supplied by the consumer as @c Options at build time, 0045 /// e.g. from the bounds of the surface the axis is attached to. This models 0046 /// proto material binning, where a configuration may fix the number of bins 0047 /// but not the range, or a range but not whether the axis wraps. 0048 /// 0049 /// Per property the rule is the same: it has to be given by exactly one side, 0050 /// or by both with the same value. Supplying a property that the spec already 0051 /// fixes therefore validates it instead of overriding it, and a property that 0052 /// neither side gives is an error. 0053 class AxisSpec { 0054 public: 0055 /// Axis properties supplied by the consumer at build time 0056 using Options = AxisSpecOptions; 0057 0058 /// Parameters for an equidistant axis 0059 struct EquidistantParams { 0060 /// Number of bins 0061 std::size_t nBins = 0; 0062 /// Minimum edge of the axis 0063 std::optional<double> min = std::nullopt; 0064 /// Maximum edge of the axis 0065 std::optional<double> max = std::nullopt; 0066 0067 /// Check if two parameter sets are equal, required for comparing the 0068 /// enclosing spec 0069 /// @param lhs first parameter set 0070 /// @param rhs second parameter set 0071 /// @return true if the parameter sets are equal 0072 friend bool operator==(const EquidistantParams& lhs, 0073 const EquidistantParams& rhs) = default; 0074 }; 0075 0076 /// Parameters for a variable axis with absolute bin edges 0077 struct VariableParams { 0078 /// Bin edges, strictly increasing 0079 std::vector<double> edges; 0080 0081 /// Check if two parameter sets are equal, required for comparing the 0082 /// enclosing spec 0083 /// @param lhs first parameter set 0084 /// @param rhs second parameter set 0085 /// @return true if the parameter sets are equal 0086 friend bool operator==(const VariableParams& lhs, 0087 const VariableParams& rhs) = default; 0088 }; 0089 0090 /// Parameters for a variable axis whose bin edges are relative and scaled 0091 /// onto the range supplied by the consumer 0092 struct DeferredVariableParams { 0093 /// Relative bin edges, strictly increasing, with first value 0 and last 0094 /// value 1 0095 std::vector<double> normalizedEdges; 0096 0097 /// Check if two parameter sets are equal, required for comparing the 0098 /// enclosing spec 0099 /// @param lhs first parameter set 0100 /// @param rhs second parameter set 0101 /// @return true if the parameter sets are equal 0102 friend bool operator==(const DeferredVariableParams& lhs, 0103 const DeferredVariableParams& rhs) = default; 0104 }; 0105 0106 private: 0107 /// Underlying variant type 0108 using Variant = 0109 std::variant<EquidistantParams, VariableParams, DeferredVariableParams>; 0110 0111 /// Construct from variant 0112 /// @param variant the alternative to hold 0113 /// @param boundaryType the optional axis boundary type 0114 /// @param direction the optional axis direction 0115 explicit AxisSpec(Variant variant, 0116 std::optional<AxisBoundaryType> boundaryType, 0117 std::optional<AxisDirection> direction); 0118 0119 public: 0120 /// Equidistant axis; every property but the number of bins may be left to 0121 /// the consumer 0122 /// @param nBins the number of bins 0123 /// @param min the optional minimum edge of the axis 0124 /// @param max the optional maximum edge of the axis 0125 /// @param boundaryType the optional boundary type of the axis 0126 /// @param direction the optional direction of the axis 0127 /// @throws std::invalid_argument if min >= max or nBins == 0 0128 /// @return the equidistant spec 0129 static AxisSpec Equidistant( 0130 std::size_t nBins, std::optional<double> min = std::nullopt, 0131 std::optional<double> max = std::nullopt, 0132 std::optional<AxisBoundaryType> boundaryType = std::nullopt, 0133 std::optional<AxisDirection> direction = std::nullopt); 0134 0135 /// Equidistant axis with only the number of bins fixed 0136 /// @param nBins the number of bins 0137 /// @param direction the optional direction of the axis 0138 /// @throws std::invalid_argument if nBins == 0 0139 /// @return the equidistant spec 0140 static AxisSpec DeferredEquidistant( 0141 std::size_t nBins, std::optional<AxisDirection> direction = std::nullopt); 0142 0143 /// Variable axis with absolute bin edges 0144 /// @param edges the bin edges, strictly increasing 0145 /// @param boundaryType the optional boundary type of the axis 0146 /// @param direction the optional direction of the axis 0147 /// @throws std::invalid_argument if fewer than two edges are given or the 0148 /// edges are not strictly increasing 0149 /// @return the variable spec 0150 static AxisSpec Variable( 0151 std::vector<double> edges, 0152 std::optional<AxisBoundaryType> boundaryType = std::nullopt, 0153 std::optional<AxisDirection> direction = std::nullopt); 0154 0155 /// Variable axis whose normalized edges are scaled onto the range supplied 0156 /// by the consumer 0157 /// @param normalizedEdges the relative bin edges, strictly increasing, with 0158 /// first value 0 and last value 1 0159 /// @param boundaryType the optional boundary type of the axis 0160 /// @param direction the optional direction of the axis 0161 /// @throws std::invalid_argument if fewer than two values are given, the 0162 /// values are not strictly increasing, or the first and last values 0163 /// are not exactly 0 and 1 0164 /// @return the deferred variable spec 0165 static AxisSpec DeferredVariable( 0166 std::vector<double> normalizedEdges, 0167 std::optional<AxisBoundaryType> boundaryType = std::nullopt, 0168 std::optional<AxisDirection> direction = std::nullopt); 0169 0170 /// Capture an existing axis as a fully specified spec 0171 /// @param axis the axis to decompose 0172 /// @return the equidistant or variable spec of the given axis, including 0173 /// its direction if set 0174 static AxisSpec FromAxis(const IAxis& axis); 0175 0176 /// Get a copy of this spec with the given direction attached 0177 /// @param direction the direction to attach 0178 /// @return the spec with the direction set 0179 AxisSpec withDirection(AxisDirection direction) const; 0180 0181 /// Get the counterpart that leaves every property to the consumer: an 0182 /// equidistant spec keeps only its number of bins, a variable one its edges 0183 /// normalized to [0, 1] 0184 /// @return the deferred spec 0185 AxisSpec toDeferred() const; 0186 0187 /// Check if the spec needs @c Options to build, i.e. leaves at least one 0188 /// property to the consumer 0189 /// @return true if the spec is deferred 0190 bool isDeferred() const; 0191 0192 /// Check if the spec produces an equidistant axis 0193 /// @return true for the equidistant alternative 0194 bool isEquidistant() const; 0195 0196 /// Check if the spec produces a variable axis 0197 /// @return true for the two variable alternatives 0198 bool isVariable() const; 0199 0200 /// Check if the spec holds normalized instead of absolute bin edges 0201 /// @return true for the deferred variable alternative 0202 bool isDeferredVariable() const; 0203 0204 /// Get the number of bins 0205 /// @return the number of bins, defined for all alternatives 0206 std::size_t nBins() const; 0207 0208 /// Get the boundary type of the axis 0209 /// @return the boundary type if the spec fixes it 0210 std::optional<AxisBoundaryType> boundaryType() const; 0211 0212 /// Get the direction of the axis 0213 /// @return the direction if the spec fixes it 0214 std::optional<AxisDirection> direction() const; 0215 0216 /// Get the spec as equidistant parameters 0217 /// @throws std::bad_variant_access if another alternative is held 0218 /// @return reference to the equidistant parameters 0219 const EquidistantParams& asEquidistant() const; 0220 0221 /// Get the spec as variable parameters 0222 /// @throws std::bad_variant_access if another alternative is held 0223 /// @return reference to the variable parameters 0224 const VariableParams& asVariable() const; 0225 0226 /// Get the spec as deferred variable parameters 0227 /// @throws std::bad_variant_access if another alternative is held 0228 /// @return reference to the deferred variable parameters 0229 const DeferredVariableParams& asDeferredVariable() const; 0230 0231 /// Build the axis, filling in the properties the spec leaves open 0232 /// and validating the ones it fixes 0233 /// @param options the properties supplied by the consumer 0234 /// @throws std::domain_error if a property is given by neither side 0235 /// @throws std::invalid_argument if a property is given by both sides with 0236 /// different values, or the resulting range is invalid 0237 /// @return the created axis 0238 std::unique_ptr<IAxis> buildAxis(const Options& options = {}) const; 0239 0240 /// Get a string representation of this spec 0241 /// @return the string representation 0242 std::string toString() const; 0243 0244 /// Check if two specs are equal 0245 /// @param lhs first spec 0246 /// @param rhs second spec 0247 /// @return true if alternative, parameters and direction are equal 0248 friend bool operator==(const AxisSpec& lhs, const AxisSpec& rhs) = default; 0249 0250 /// Output stream operator 0251 /// @param os output stream 0252 /// @param axisSpec the spec to be printed 0253 /// @return the output stream 0254 friend std::ostream& operator<<(std::ostream& os, const AxisSpec& axisSpec) { 0255 return os << axisSpec.toString(); 0256 } 0257 0258 private: 0259 Variant m_variant; 0260 std::optional<AxisBoundaryType> m_boundaryType; 0261 std::optional<AxisDirection> m_direction; 0262 }; 0263 0264 } // namespace Acts
| [ Source navigation ] | [ Diff markup ] | [ Identifier search ] | [ general search ] |
|
This page was automatically generated by the 2.3.7 LXR engine. The LXR team |
|