diff --git a/Core/include/Acts/Geometry/MaterialDesignatorBlueprintNode.hpp b/Core/include/Acts/Geometry/MaterialDesignatorBlueprintNode.hpp index ef1eca5e7e6..9bc0dedb7fe 100644 --- a/Core/include/Acts/Geometry/MaterialDesignatorBlueprintNode.hpp +++ b/Core/include/Acts/Geometry/MaterialDesignatorBlueprintNode.hpp @@ -56,7 +56,7 @@ class MaterialDesignatorBlueprintNode final : public BlueprintNode { /// It receives the populated portal shell from its only child and attaches /// material proxies by consulting the configuration stored in the node. /// @note Currently, this node will unconditionally attach - /// @ref Acts::ProtoGridSurfaceMaterial + /// @ref Acts::ProtoSurfaceMaterial /// /// @param options The global blueprint options /// @param gctx The geometry context (nominal usually) diff --git a/Core/include/Acts/Material/AccumulatedSurfaceMaterial.hpp b/Core/include/Acts/Material/AccumulatedSurfaceMaterial.hpp index 85b9310afd3..b8514a4e7dc 100644 --- a/Core/include/Acts/Material/AccumulatedSurfaceMaterial.hpp +++ b/Core/include/Acts/Material/AccumulatedSurfaceMaterial.hpp @@ -11,11 +11,13 @@ #include "Acts/Definitions/Algebra.hpp" #include "Acts/Material/AccumulatedMaterialSlab.hpp" #include "Acts/Material/MaterialSlab.hpp" -#include "Acts/Utilities/BinUtility.hpp" +#include "Acts/Utilities/ProtoAxis.hpp" +#include "Acts/Utilities/VectorHelpers.hpp" #include #include #include +#include #include namespace Acts { @@ -51,10 +53,13 @@ class AccumulatedSurfaceMaterial { /// - 0. : alongPre /// ===> 1 Dimensional array /// - /// @param binUtility defines the binning structure on the surface + /// @param directedProtoAxes defines the binning structure on the surface + /// @param globalToLocalTransform transform from global to local 3D frame /// @param splitFactor is the pre/post splitting directive - explicit AccumulatedSurfaceMaterial(const BinUtility& binUtility, - double splitFactor = 0.); + explicit AccumulatedSurfaceMaterial( + std::vector directedProtoAxes, + Transform3 globalToLocalTransform = Transform3::Identity(), + double splitFactor = 0.); /// Copy Constructor /// @@ -83,9 +88,13 @@ class AccumulatedSurfaceMaterial { /// Destructor ~AccumulatedSurfaceMaterial() = default; - /// Return the BinUtility - /// @return Reference to the bin utility used for material binning - const BinUtility& binUtility() const; + /// Return the DirectedProtoAxis descriptors + /// @return Reference to the directed proto axes used for material binning + const std::vector& directedProtoAxes() const; + + /// Return the transform from global to local 3D frame + /// @return Reference to global-to-local transform + const Transform3& globalToLocalTransform() const; /// Assign a material properties object /// @@ -154,8 +163,17 @@ class AccumulatedSurfaceMaterial { double splitFactor() const; private: - /// The helper for the bin finding - BinUtility m_binUtility{}; + /// Correct potentially underflow/overflow IAxis bins into matrix bins. + static std::size_t correctedBinIndex(const IAxis& axis, double value); + + /// Return material bins corresponding to a local 3D position. + std::array lookupBins(const Vector3& localPosition) const; + + /// The helper for axis-based bin finding + std::vector m_directedProtoAxes{}; + + /// Global to local transform for bin lookups. + Transform3 m_globalToLocalTransform = Transform3::Identity(); /// the split factor double m_splitFactor{0.}; @@ -164,8 +182,46 @@ class AccumulatedSurfaceMaterial { AccumulatedMatrix m_accumulatedMaterial; }; -inline const BinUtility& AccumulatedSurfaceMaterial::binUtility() const { - return m_binUtility; +inline const std::vector& +AccumulatedSurfaceMaterial::directedProtoAxes() const { + return m_directedProtoAxes; +} + +inline const Transform3& AccumulatedSurfaceMaterial::globalToLocalTransform() + const { + return m_globalToLocalTransform; +} + +inline std::size_t AccumulatedSurfaceMaterial::correctedBinIndex( + const IAxis& axis, double value) { + const std::size_t rawBin = axis.getBin(value); + const std::size_t nBins = axis.getNBins(); + if (nBins == 0u || rawBin == 0u) { + return 0u; + } + if (rawBin > nBins) { + return nBins - 1u; + } + return rawBin - 1u; +} + +inline std::array AccumulatedSurfaceMaterial::lookupBins( + const Vector3& localPosition) const { + if (m_directedProtoAxes.empty()) { + return {0u, 0u, 0u}; + } + std::array bins = {0u, 0u, 0u}; + bins[0] = correctedBinIndex( + m_directedProtoAxes[0u].getAxis(), + VectorHelpers::cast(localPosition, + m_directedProtoAxes[0u].getAxisDirection())); + if (m_directedProtoAxes.size() > 1u) { + bins[1] = correctedBinIndex( + m_directedProtoAxes[1u].getAxis(), + VectorHelpers::cast(localPosition, + m_directedProtoAxes[1u].getAxisDirection())); + } + return bins; } inline const AccumulatedSurfaceMaterial::AccumulatedMatrix& diff --git a/Core/include/Acts/Material/BinnedSurfaceMaterial.hpp b/Core/include/Acts/Material/BinnedSurfaceMaterial.hpp index 356a363d64a..634d9db8d0e 100644 --- a/Core/include/Acts/Material/BinnedSurfaceMaterial.hpp +++ b/Core/include/Acts/Material/BinnedSurfaceMaterial.hpp @@ -12,8 +12,14 @@ #include "Acts/Material/ISurfaceMaterial.hpp" #include "Acts/Material/MaterialSlab.hpp" #include "Acts/Utilities/BinUtility.hpp" +#include "Acts/Utilities/GridAccessHelpers.hpp" +#include "Acts/Utilities/ProtoAxis.hpp" +#include #include +#include +#include +#include namespace Acts { @@ -39,11 +45,26 @@ class BinnedSurfaceMaterial : public ISurfaceMaterial { /// @param fullProperties is the vector of properties as recorded (moved) /// @param splitFactor is the pre/post splitting directive /// @param mappingType is the type of surface mapping associated to the surface + [[deprecated( + "BinnedSurfaceMaterial BinUtility constructor is deprecated. " + "Use DirectedProtoAxis constructor instead.")]] BinnedSurfaceMaterial(const BinUtility& binUtility, MaterialSlabVector fullProperties, double splitFactor = 0., MappingType mappingType = MappingType::Default); + /// Explicit constructor with only full MaterialSlab, + /// for one-dimensional binning. + /// + /// @param directedProtoAxis defines axis direction and axis binning + /// @param fullProperties is the vector of properties as recorded (moved) + /// @param splitFactor is the pre/post splitting directive + /// @param mappingType is the type of surface mapping associated to the surface + BinnedSurfaceMaterial(DirectedProtoAxis directedProtoAxis, + MaterialSlabVector fullProperties, + double splitFactor = 0., + MappingType mappingType = MappingType::Default); + /// Explicit constructor with only full MaterialSlab, /// for two-dimensional binning. /// @@ -56,11 +77,26 @@ class BinnedSurfaceMaterial : public ISurfaceMaterial { /// @param fullProperties is the vector of properties as recorded (moved) /// @param splitFactor is the pre/post splitting directive /// @param mappingType is the type of surface mapping associated to the surface + [[deprecated( + "BinnedSurfaceMaterial BinUtility constructor is deprecated. " + "Use std::array constructor instead.")]] BinnedSurfaceMaterial(const BinUtility& binUtility, MaterialSlabMatrix fullProperties, double splitFactor = 0., MappingType mappingType = MappingType::Default); + /// Explicit constructor with only full MaterialSlab, + /// for two-dimensional binning. + /// + /// @param directedProtoAxes defines axis directions and axis binnings + /// @param fullProperties is the matrix of properties as recorded (moved) + /// @param splitFactor is the pre/post splitting directive + /// @param mappingType is the type of surface mapping associated to the surface + BinnedSurfaceMaterial(std::array directedProtoAxes, + MaterialSlabMatrix fullProperties, + double splitFactor = 0., + MappingType mappingType = MappingType::Default); + /// Copy Move Constructor /// /// @param bsm is the source object to be copied @@ -91,8 +127,15 @@ class BinnedSurfaceMaterial : public ISurfaceMaterial { BinnedSurfaceMaterial& scale(double factor) final; /// Return the BinUtility - /// @return Reference to the bin utility used for material binning - const BinUtility& binUtility() const; + /// @return BinUtility used for material binning (created on-the-fly) + [[deprecated( + "BinnedSurfaceMaterial::binUtility() is deprecated. " + "Use directedProtoAxes() instead.")]] + BinUtility binUtility() const; + + /// Return the DirectedProtoAxis descriptors + /// @return Reference to the directed proto axes used for material binning + const std::vector& directedProtoAxes() const; /// @brief Retrieve the entire material slab matrix /// @return Reference to the complete matrix of material slabs @@ -102,7 +145,10 @@ class BinnedSurfaceMaterial : public ISurfaceMaterial { const MaterialSlab& materialSlab(const Vector2& lp) const final; /// @copydoc ISurfaceMaterial::materialSlab(const Vector3&) const - const MaterialSlab& materialSlab(const Vector3& gp) const final; + /// + /// For this class the provided 3D position is expected to already be in the + /// local surface frame. + const MaterialSlab& materialSlab(const Vector3& lp3D) const final; using ISurfaceMaterial::materialSlab; @@ -112,15 +158,78 @@ class BinnedSurfaceMaterial : public ISurfaceMaterial { std::ostream& toStream(std::ostream& sl) const final; private: - /// The helper for the bin finding - BinUtility m_binUtility; + /// Convert legacy BinUtility setup to DirectedProtoAxis. + static std::vector convertBinUtility( + const BinUtility& binUtility); + + /// Correct potentially underflow/overflow IAxis bins into matrix bins. + static std::size_t correctedBinIndex(const IAxis& axis, double value); + + /// The helper for axis-based bin finding + std::vector m_directedProtoAxes; /// The five different MaterialSlab MaterialSlabMatrix m_fullMaterial; }; -inline const BinUtility& BinnedSurfaceMaterial::binUtility() const { - return m_binUtility; +inline BinUtility BinnedSurfaceMaterial::binUtility() const { + BinUtility converted; + for (const auto& directedProtoAxis : m_directedProtoAxes) { + converted += BinUtility(BinningData(directedProtoAxis)); + } + return converted; +} + +inline const std::vector& +BinnedSurfaceMaterial::directedProtoAxes() const { + return m_directedProtoAxes; +} + +inline std::vector BinnedSurfaceMaterial::convertBinUtility( + const BinUtility& binUtility) { + const auto& binningData = binUtility.binningData(); + if (binningData.empty() || binningData.size() > 2u) { + throw std::invalid_argument( + "BinnedSurfaceMaterial supports only 1D/2D binning."); + } + + std::vector directedProtoAxes; + directedProtoAxes.reserve(binningData.size()); + for (const auto& bData : binningData) { + const AxisBoundaryType boundaryType = bData.option == closed + ? AxisBoundaryType::Closed + : AxisBoundaryType::Bound; + if (bData.type == equidistant) { + directedProtoAxes.emplace_back( + bData.binvalue, boundaryType, static_cast(bData.min), + static_cast(bData.max), bData.bins()); + continue; + } + std::vector edges; + edges.reserve(bData.boundaries().size()); + for (const auto edge : bData.boundaries()) { + edges.push_back(static_cast(edge)); + } + directedProtoAxes.emplace_back(bData.binvalue, boundaryType, edges); + } + + return directedProtoAxes; +} + +inline std::size_t BinnedSurfaceMaterial::correctedBinIndex(const IAxis& axis, + double value) { + const std::size_t rawBin = axis.getBin(value); + const std::size_t nBins = axis.getNBins(); + if (nBins == 0u) { + return 0u; + } + if (rawBin == 0u) { + return 0u; + } + if (rawBin > nBins) { + return nBins - 1u; + } + return rawBin - 1u; } inline const MaterialSlabMatrix& BinnedSurfaceMaterial::fullMaterial() const { diff --git a/Core/include/Acts/Material/ProtoSurfaceMaterial.hpp b/Core/include/Acts/Material/ProtoSurfaceMaterial.hpp index 43fd60479f9..a1935698882 100644 --- a/Core/include/Acts/Material/ProtoSurfaceMaterial.hpp +++ b/Core/include/Acts/Material/ProtoSurfaceMaterial.hpp @@ -15,6 +15,7 @@ #include "Acts/Utilities/ProtoAxis.hpp" #include +#include #include namespace Acts { @@ -23,65 +24,75 @@ namespace Acts { /// @{ /// -/// @brief proxy to SurfaceMaterial hand over BinUtility or other suitable -/// binning description +/// @brief proxy to SurfaceMaterial carrying directed proto axis binning /// /// The ProtoSurfaceMaterial class acts as a proxy to the SurfaceMaterial /// to mark the layers and surfaces on which the material should be mapped on /// at construction time of the geometry and to hand over the granularity of -/// of the material map with the bin Utility. -template -class ProtoSurfaceMaterialT : public ISurfaceMaterial { +/// of the material map with directed proto axes. +class ProtoSurfaceMaterial : public ISurfaceMaterial { public: /// Constructor without binningType - homogeneous material - ProtoSurfaceMaterialT() = default; + ProtoSurfaceMaterial() = default; - /// Constructor with BinningType - /// @param binning a binning description for the material map binning + /// Constructor with directed proto axes + /// @param directedProtoAxes axis description for the material map binning /// @param mappingType is the type of surface mapping associated to the surface - explicit ProtoSurfaceMaterialT(const BinningType& binning, - MappingType mappingType = MappingType::Default) - : ISurfaceMaterial(1., mappingType), m_binning(binning) {} + explicit ProtoSurfaceMaterial( + std::vector directedProtoAxes, + MappingType mappingType = MappingType::Default) + : ISurfaceMaterial(1., mappingType), + m_directedProtoAxes(std::move(directedProtoAxes)) {} /// Copy constructor /// /// @param smproxy The source proxy - ProtoSurfaceMaterialT(const ProtoSurfaceMaterialT& smproxy) = - default; + ProtoSurfaceMaterial(const ProtoSurfaceMaterial& smproxy) = default; /// Copy move constructor /// /// @param smproxy The source proxy - ProtoSurfaceMaterialT(ProtoSurfaceMaterialT&& smproxy) noexcept = - default; + ProtoSurfaceMaterial(ProtoSurfaceMaterial&& smproxy) noexcept = default; /// Destructor - ~ProtoSurfaceMaterialT() override = default; + ~ProtoSurfaceMaterial() override = default; /// Assignment operator /// /// @param smproxy The source proxy /// @return Reference to this object - ProtoSurfaceMaterialT& operator=( - const ProtoSurfaceMaterialT& smproxy) = default; + ProtoSurfaceMaterial& operator=(const ProtoSurfaceMaterial& smproxy) = + default; /// Assignment move operator /// /// @param smproxy The source proxy /// @return Reference to this object - ProtoSurfaceMaterialT& operator=( - ProtoSurfaceMaterialT&& smproxy) noexcept = default; + ProtoSurfaceMaterial& operator=(ProtoSurfaceMaterial&& smproxy) noexcept = + default; /// Scale operation - dummy implementation /// /// @return Reference to this object - ProtoSurfaceMaterialT& scale(double /*factor*/) final { - return (*this); + ProtoSurfaceMaterial& scale(double /*factor*/) final { return (*this); } + + /// Return the directed proto axes + /// @return Reference to the binning axis descriptors + const std::vector& directedProtoAxes() const { + return m_directedProtoAxes; } - /// Return the BinUtility - /// @return Reference to the binning - const BinningType& binning() const { return (m_binning); } + /// Return a BinUtility representation of this proxy (on-the-fly) + [[deprecated( + "ProtoSurfaceMaterial::binning() is deprecated. " + "Use directedProtoAxes() instead.")]] + BinUtility binning() const { + BinUtility converted; + for (const auto& directedProtoAxis : m_directedProtoAxes) { + converted += BinUtility(BinningData(directedProtoAxis)); + } + return converted; + } /// Return method for full material description of the Surface - from local /// coordinates @@ -91,8 +102,8 @@ class ProtoSurfaceMaterialT : public ISurfaceMaterial { return (m_materialSlab); } - /// Return method for full material description of the Surface - from the - /// global coordinates + /// Return method for full material description of the Surface - from local + /// 3D coordinates /// /// @return will return dummy material const MaterialSlab& materialSlab(const Vector3& /*gp*/) const final { @@ -107,28 +118,18 @@ class ProtoSurfaceMaterialT : public ISurfaceMaterial { /// @return The output stream std::ostream& toStream(std::ostream& sl) const final { sl << "Acts::ProtoSurfaceMaterial : " << std::endl; - sl << m_binning << std::endl; + sl << m_directedProtoAxes << std::endl; return sl; } private: - /// A binning description - BinningType m_binning; + /// Directed axis descriptions. + std::vector m_directedProtoAxes; /// Dummy material properties MaterialSlab m_materialSlab = MaterialSlab::Nothing(); }; -/// @brief Type alias for a prototype surface material using BinUtility -/// A surface material implementation that uses BinUtility for binning -using ProtoSurfaceMaterial = ProtoSurfaceMaterialT; - -/// @brief Type alias for a prototype surface material using a grid of ProtoAxis -/// A surface material implementation that uses a vector of ProtoAxis for -/// grid-based binning -using ProtoGridSurfaceMaterial = - ProtoSurfaceMaterialT>; - /// @} } // namespace Acts diff --git a/Core/include/Acts/Utilities/ProtoAxisHelpers.hpp b/Core/include/Acts/Utilities/ProtoAxisHelpers.hpp deleted file mode 100644 index 7863a4ef864..00000000000 --- a/Core/include/Acts/Utilities/ProtoAxisHelpers.hpp +++ /dev/null @@ -1,128 +0,0 @@ -// This file is part of the ACTS project. -// -// Copyright (C) 2016 CERN for the benefit of the ACTS project -// -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at https://mozilla.org/MPL/2.0/. - -#pragma once - -#include "Acts/Definitions/Algebra.hpp" -#include "Acts/Utilities/BinningData.hpp" -#include "Acts/Utilities/ProtoAxis.hpp" - -#include -#include -#include - -namespace Acts::ProtoAxisHelpers { - -/// @brief Get the number of bins from a ProtoAxis -/// @param axis DirectedProtoAxis object -/// @return Number of bins in the axis -inline std::size_t binsOfProtoAxis(const Acts::DirectedProtoAxis& axis) { - return axis.getAxis().getNBins(); -} - -/// @brief Get the total number of bins from multiple ProtoAxes -/// @param axes Span of DirectedProtoAxis objects -/// @return Total number of bins across all axes -inline std::size_t totalBinsFromProtoAxes( - std::span axes) { - if (axes.empty() || axes.size() > 3) { - throw std::runtime_error( - "Unsupported number of axes, must be 1-3, instead got " + - std::to_string(axes.size()) + ")"); - } - return axes[0].getAxis().getNBins() * - (axes.size() > 1 ? axes[1].getAxis().getNBins() : 1) * - (axes.size() > 2 ? axes[2].getAxis().getNBins() : 1); -} - -/// @brief Get the number of bins from a specific ProtoAxis in a collection -/// @param axes DirectedProtoAxis span -/// @param ba Bin axis index -/// @return Number of bins in the specified axis -inline std::size_t binsFromProtoAxes( - std::span axes, std::size_t ba) { - if (axes.empty() || axes.size() > 3) { - throw std::runtime_error( - "Unsupported number of axes, must be 1-3, instead got " + - std::to_string(axes.size()) + ")"); - } - Acts::BinningData bd(axes[ba]); - return bd.bins(); -} - -/// @brief Get the bin index from a ProtoAxis using local coordinates -/// @param axis DirectedProtoAxis object -/// @param lp Local position vector -/// @return Bin index corresponding to the local position -inline std::size_t binFromProtoAxis(const Acts::DirectedProtoAxis& axis, - const Acts::Vector2& lp) { - Acts::BinningData bd(axis); - return bd.searchLocal(lp); -} - -/// @brief Get the bin index from a ProtoAxis using global coordinates -/// @param axis DirectedProtoAxis object -/// @param gp Global position vector -/// @return Bin index corresponding to the global position -inline std::size_t binFromProtoAxis(const Acts::DirectedProtoAxis& axis, - const Acts::Vector3& gp) { - Acts::BinningData bd(axis); - return bd.searchGlobal(gp); -} - -/// @brief Get the bin triple from multiple ProtoAxes using global coordinates -/// @param axes Span of DirectedProtoAxis objects -/// @param gp Global position vector -/// @return Array of bin indices corresponding to the global position for each axis -inline std::array binTripleFromProtoAxes( - std::span axes, const Acts::Vector3& gp) { - const Acts::Vector3& bPosition = gp; - std::array bTriple = {0, 0, 0}; - if (axes.empty() || axes.size() > 3) { - throw std::runtime_error( - "Unsupported number of axes, must be 1-3, instead got " + - std::to_string(axes.size()) + ")"); - } - if (axes.size() == 1) { - Acts::BinningData bd0(axes[0]); - bTriple[0] = bd0.searchGlobal(bPosition); - } - if (axes.size() == 2) { - Acts::BinningData bd1(axes[1]); - bTriple[1] = bd1.searchGlobal(bPosition); - } - if (axes.size() == 3) { - Acts::BinningData bd2(axes[2]); - bTriple[2] = bd2.searchGlobal(bPosition); - } - return bTriple; -} - -/// @brief Get the maximum bin index from a specific ProtoAxis in a collection -/// @param axes DirectedProtoAxis span -/// @param ba Bin axis index -/// @return Maximum bin index in the specified axis -inline std::size_t maxBin(std::span axes, - std::size_t ba = 0) { - if (axes.empty() || axes.size() > 3) { - throw std::runtime_error( - "Unsupported number of axes, must be 1-3, instead got " + - std::to_string(axes.size()) + ")"); - } - std::vector binningDataVec; - binningDataVec.reserve(axes.size()); - for (const auto& axis : axes) { - binningDataVec.emplace_back(axis); - } - if (ba >= binningDataVec.size()) { - return 0; - } - return (binningDataVec.at(ba).bins() - 1); -} - -} // namespace Acts::ProtoAxisHelpers diff --git a/Core/src/Geometry/MaterialDesignator.hpp b/Core/src/Geometry/MaterialDesignator.hpp index 0eec6ce75df..78e864db005 100644 --- a/Core/src/Geometry/MaterialDesignator.hpp +++ b/Core/src/Geometry/MaterialDesignator.hpp @@ -82,7 +82,7 @@ class ProtoDesignator { << loc1 << " to face " << face); portal->surface().assignSurfaceMaterial( - std::make_shared(std::vector{loc0, loc1})); + std::make_shared(std::vector{loc0, loc1})); } } diff --git a/Core/src/Material/AccumulatedSurfaceMaterial.cpp b/Core/src/Material/AccumulatedSurfaceMaterial.cpp index 9fb08edc903..2d067aba32a 100644 --- a/Core/src/Material/AccumulatedSurfaceMaterial.cpp +++ b/Core/src/Material/AccumulatedSurfaceMaterial.cpp @@ -10,8 +10,8 @@ #include "Acts/Material/BinnedSurfaceMaterial.hpp" #include "Acts/Material/HomogeneousSurfaceMaterial.hpp" -#include "Acts/Utilities/ProtoAxisHelpers.hpp" +#include #include // Default Constructor - for homogeneous material @@ -23,10 +23,21 @@ Acts::AccumulatedSurfaceMaterial::AccumulatedSurfaceMaterial(double splitFactor) // Binned Material constructor with split factor Acts::AccumulatedSurfaceMaterial::AccumulatedSurfaceMaterial( - const BinUtility& binUtility, double splitFactor) - : m_binUtility(binUtility), m_splitFactor(splitFactor) { - std::size_t bins0 = m_binUtility.bins(0); - std::size_t bins1 = m_binUtility.bins(1); + std::vector directedProtoAxes, + Transform3 globalToLocalTransform, double splitFactor) + : m_directedProtoAxes(std::move(directedProtoAxes)), + m_globalToLocalTransform(std::move(globalToLocalTransform)), + m_splitFactor(splitFactor) { + if (m_directedProtoAxes.size() > 2u) { + throw std::invalid_argument( + "AccumulatedSurfaceMaterial supports only 0D/1D/2D binning."); + } + std::size_t bins0 = m_directedProtoAxes.empty() + ? 1u + : m_directedProtoAxes[0u].getAxis().getNBins(); + std::size_t bins1 = m_directedProtoAxes.size() > 1u + ? m_directedProtoAxes[1u].getAxis().getNBins() + : 1u; AccumulatedVector accVec(bins0, AccumulatedMaterialSlab()); m_accumulatedMaterial = AccumulatedMatrix(bins1, accVec); } @@ -34,38 +45,37 @@ Acts::AccumulatedSurfaceMaterial::AccumulatedSurfaceMaterial( // Assign a material properties object std::array Acts::AccumulatedSurfaceMaterial::accumulate( const Vector2& lp, const MaterialSlab& mp, double pathCorrection) { - if (m_binUtility.dimensions() == 0) { + if (m_directedProtoAxes.empty()) { m_accumulatedMaterial[0][0].accumulate(mp, pathCorrection); return {0, 0, 0}; } - std::size_t bin0 = m_binUtility.bin(lp, 0); - std::size_t bin1 = m_binUtility.bin(lp, 1); - m_accumulatedMaterial[bin1][bin0].accumulate(mp, pathCorrection); - return {bin0, bin1, 0}; + std::array bins = lookupBins(Vector3(lp[0], lp[1], 0.)); + m_accumulatedMaterial[bins[1]][bins[0]].accumulate(mp, pathCorrection); + return bins; } // Assign a material properties object std::array Acts::AccumulatedSurfaceMaterial::accumulate( const Vector3& gp, const MaterialSlab& mp, double pathCorrection) { - if (m_binUtility.dimensions() == 0) { + if (m_directedProtoAxes.empty()) { m_accumulatedMaterial[0][0].accumulate(mp, pathCorrection); return {0, 0, 0}; } - std::array bTriple = m_binUtility.binTriple(gp); - m_accumulatedMaterial[bTriple[1]][bTriple[0]].accumulate(mp, pathCorrection); - return bTriple; + std::array bins = lookupBins(m_globalToLocalTransform * gp); + m_accumulatedMaterial[bins[1]][bins[0]].accumulate(mp, pathCorrection); + return bins; } // Void average for vacuum assignment void Acts::AccumulatedSurfaceMaterial::trackVariance(const Vector3& gp, MaterialSlab slabReference, bool emptyHit) { - if (m_binUtility.dimensions() == 0) { + if (m_directedProtoAxes.empty()) { m_accumulatedMaterial[0][0].trackVariance(slabReference, emptyHit); return; } - std::array bTriple = m_binUtility.binTriple(gp); - std::vector> trackBins = {bTriple}; + std::array bins = lookupBins(m_globalToLocalTransform * gp); + std::vector> trackBins = {bins}; trackVariance(trackBins, slabReference); } @@ -74,7 +84,7 @@ void Acts::AccumulatedSurfaceMaterial::trackVariance( const std::vector>& trackBins, MaterialSlab slabReference, bool emptyHit) { // the homogeneous material case - if (m_binUtility.dimensions() == 0) { + if (m_directedProtoAxes.empty()) { m_accumulatedMaterial[0][0].trackVariance(slabReference, emptyHit); return; } @@ -96,13 +106,13 @@ void Acts::AccumulatedSurfaceMaterial::trackVariance( // Void average for vacuum assignment void Acts::AccumulatedSurfaceMaterial::trackAverage(const Vector3& gp, bool emptyHit) { - if (m_binUtility.dimensions() == 0) { + if (m_directedProtoAxes.empty()) { m_accumulatedMaterial[0][0].trackAverage(emptyHit); return; } - std::array bTriple = m_binUtility.binTriple(gp); - std::vector> trackBins = {bTriple}; + std::array bins = lookupBins(m_globalToLocalTransform * gp); + std::vector> trackBins = {bins}; trackAverage(trackBins, emptyHit); } @@ -110,7 +120,7 @@ void Acts::AccumulatedSurfaceMaterial::trackAverage(const Vector3& gp, void Acts::AccumulatedSurfaceMaterial::trackAverage( const std::vector>& trackBins, bool emptyHit) { // the homogeneous material case - if (m_binUtility.dimensions() == 0) { + if (m_directedProtoAxes.empty()) { m_accumulatedMaterial[0][0].trackAverage(emptyHit); return; } @@ -133,22 +143,33 @@ void Acts::AccumulatedSurfaceMaterial::trackAverage( /// Total average creates SurfaceMaterial std::unique_ptr Acts::AccumulatedSurfaceMaterial::totalAverage() { - if (m_binUtility.bins() == 1) { + const std::size_t bins0 = m_accumulatedMaterial[0u].size(); + const std::size_t bins1 = m_accumulatedMaterial.size(); + if (bins0 * bins1 == 1u) { // Return HomogeneousSurfaceMaterial return std::make_unique( m_accumulatedMaterial[0][0].totalAverage().first, m_splitFactor); } + + if (m_directedProtoAxes.size() == 1u) { + MaterialSlabVector mpVector(bins0, MaterialSlab::Nothing()); + for (std::size_t ib0 = 0; ib0 < bins0; ++ib0) { + mpVector[ib0] = m_accumulatedMaterial[0u][ib0].totalAverage().first; + } + return std::make_unique( + m_directedProtoAxes[0u], std::move(mpVector), m_splitFactor); + } + // Create the properties matrix MaterialSlabMatrix mpMatrix( - m_binUtility.bins(1), - MaterialSlabVector(m_binUtility.bins(0), MaterialSlab::Nothing())); - // Loop over and fill - for (std::size_t ib1 = 0; ib1 < m_binUtility.bins(1); ++ib1) { - for (std::size_t ib0 = 0; ib0 < m_binUtility.bins(0); ++ib0) { + bins1, MaterialSlabVector(bins0, MaterialSlab::Nothing())); + for (std::size_t ib1 = 0; ib1 < bins1; ++ib1) { + for (std::size_t ib0 = 0; ib0 < bins0; ++ib0) { mpMatrix[ib1][ib0] = m_accumulatedMaterial[ib1][ib0].totalAverage().first; } } - // Now return the BinnedSurfaceMaterial return std::make_unique( - m_binUtility, std::move(mpMatrix), m_splitFactor); + std::array{m_directedProtoAxes[0u], + m_directedProtoAxes[1u]}, + std::move(mpMatrix), m_splitFactor); } diff --git a/Core/src/Material/BinnedSurfaceMaterial.cpp b/Core/src/Material/BinnedSurfaceMaterial.cpp index aae46bd02d7..7e9a21682ef 100644 --- a/Core/src/Material/BinnedSurfaceMaterial.cpp +++ b/Core/src/Material/BinnedSurfaceMaterial.cpp @@ -10,23 +10,43 @@ #include "Acts/Material/MaterialSlab.hpp" +#include #include +#include #include #include Acts::BinnedSurfaceMaterial::BinnedSurfaceMaterial( const BinUtility& binUtility, MaterialSlabVector fullProperties, - double splitFactor, Acts::MappingType mappingType) - : ISurfaceMaterial(splitFactor, mappingType), m_binUtility(binUtility) { + double splitFactor, MappingType mappingType) + : ISurfaceMaterial(splitFactor, mappingType), + m_directedProtoAxes(convertBinUtility(binUtility)) { // fill the material with deep copy m_fullMaterial.push_back(std::move(fullProperties)); } Acts::BinnedSurfaceMaterial::BinnedSurfaceMaterial( const BinUtility& binUtility, MaterialSlabMatrix fullProperties, - double splitFactor, Acts::MappingType mappingType) + double splitFactor, MappingType mappingType) + : ISurfaceMaterial(splitFactor, mappingType), + m_directedProtoAxes(convertBinUtility(binUtility)), + m_fullMaterial(std::move(fullProperties)) {} + +Acts::BinnedSurfaceMaterial::BinnedSurfaceMaterial( + DirectedProtoAxis directedProtoAxis, MaterialSlabVector fullProperties, + double splitFactor, MappingType mappingType) + : ISurfaceMaterial(splitFactor, mappingType), + m_directedProtoAxes{std::move(directedProtoAxis)} { + m_fullMaterial.push_back(std::move(fullProperties)); +} + +Acts::BinnedSurfaceMaterial::BinnedSurfaceMaterial( + std::array directedProtoAxes, + MaterialSlabMatrix fullProperties, double splitFactor, + MappingType mappingType) : ISurfaceMaterial(splitFactor, mappingType), - m_binUtility(binUtility), + m_directedProtoAxes{std::move(directedProtoAxes[0u]), + std::move(directedProtoAxes[1u])}, m_fullMaterial(std::move(fullProperties)) {} Acts::BinnedSurfaceMaterial& Acts::BinnedSurfaceMaterial::scale(double factor) { @@ -40,24 +60,71 @@ Acts::BinnedSurfaceMaterial& Acts::BinnedSurfaceMaterial::scale(double factor) { const Acts::MaterialSlab& Acts::BinnedSurfaceMaterial::materialSlab( const Vector2& lp) const { - // the first bin - std::size_t ibin0 = m_binUtility.bin(lp, 0); - std::size_t ibin1 = m_binUtility.max(1) != 0u ? m_binUtility.bin(lp, 1) : 0; + if (m_directedProtoAxes.empty()) { + throw std::logic_error( + "BinnedSurfaceMaterial has no DirectedProtoAxis configured."); + } + const Vector3 localPosition(lp[0], lp[1], 0.); + std::size_t ibin0 = 0u; + std::size_t ibin1 = 0u; + if (m_directedProtoAxes.size() == 1u) { + std::array casted{}; + const std::array castDirs{ + m_directedProtoAxes[0u].getAxisDirection()}; + GridAccessHelpers::fillCasts(localPosition, castDirs, casted, + std::make_index_sequence<1u>{}); + ibin0 = correctedBinIndex(m_directedProtoAxes[0u].getAxis(), casted[0u]); + } else { + std::array casted{}; + const std::array castDirs{ + m_directedProtoAxes[0u].getAxisDirection(), + m_directedProtoAxes[1u].getAxisDirection()}; + GridAccessHelpers::fillCasts(localPosition, castDirs, casted, + std::make_index_sequence<2u>{}); + ibin0 = correctedBinIndex(m_directedProtoAxes[0u].getAxis(), casted[0u]); + ibin1 = correctedBinIndex(m_directedProtoAxes[1u].getAxis(), casted[1u]); + } return m_fullMaterial[ibin1][ibin0]; } const Acts::MaterialSlab& Acts::BinnedSurfaceMaterial::materialSlab( - const Acts::Vector3& gp) const { - // the first bin - std::size_t ibin0 = m_binUtility.bin(gp, 0); - std::size_t ibin1 = m_binUtility.max(1) != 0u ? m_binUtility.bin(gp, 1) : 0; + const Acts::Vector3& lp3D) const { + if (m_directedProtoAxes.empty()) { + throw std::logic_error( + "BinnedSurfaceMaterial has no DirectedProtoAxis configured."); + } + const Vector3& localPosition = lp3D; + std::size_t ibin0 = 0u; + std::size_t ibin1 = 0u; + if (m_directedProtoAxes.size() == 1u) { + std::array casted{}; + const std::array castDirs{ + m_directedProtoAxes[0u].getAxisDirection()}; + GridAccessHelpers::fillCasts(localPosition, castDirs, casted, + std::make_index_sequence<1u>{}); + ibin0 = correctedBinIndex(m_directedProtoAxes[0u].getAxis(), casted[0u]); + } else { + std::array casted{}; + const std::array castDirs{ + m_directedProtoAxes[0u].getAxisDirection(), + m_directedProtoAxes[1u].getAxisDirection()}; + GridAccessHelpers::fillCasts(localPosition, castDirs, casted, + std::make_index_sequence<2u>{}); + ibin0 = correctedBinIndex(m_directedProtoAxes[0u].getAxis(), casted[0u]); + ibin1 = correctedBinIndex(m_directedProtoAxes[1u].getAxis(), casted[1u]); + } return m_fullMaterial[ibin1][ibin0]; } std::ostream& Acts::BinnedSurfaceMaterial::toStream(std::ostream& sl) const { + const std::size_t bins0 = + !m_fullMaterial.empty() ? m_fullMaterial[0u].size() : 0u; + const std::size_t bins1 = m_fullMaterial.size(); sl << "Acts::BinnedSurfaceMaterial : " << std::endl; - sl << " - Number of Material bins [0,1] : " << m_binUtility.max(0) + 1 - << " / " << m_binUtility.max(1) + 1 << std::endl; + sl << " - Number of Material bins [0,1] : " << bins0 << " / " << bins1 + << std::endl; + sl << " - Number of DirectedProtoAxis : " << m_directedProtoAxes.size() + << std::endl; sl << " - Parse full update material : " << std::endl; // // output the full material unsigned int imat1 = 0; @@ -70,6 +137,6 @@ std::ostream& Acts::BinnedSurfaceMaterial::toStream(std::ostream& sl) const { } ++imat1; } - sl << " - BinUtility: " << m_binUtility << std::endl; + sl << " - DirectedProtoAxes: " << m_directedProtoAxes << std::endl; return sl; } diff --git a/Core/src/Material/BinnedSurfaceMaterialAccumulator.cpp b/Core/src/Material/BinnedSurfaceMaterialAccumulator.cpp index 096421bffcd..ccb7d29a42a 100644 --- a/Core/src/Material/BinnedSurfaceMaterialAccumulator.cpp +++ b/Core/src/Material/BinnedSurfaceMaterialAccumulator.cpp @@ -12,8 +12,6 @@ #include "Acts/Material/BinnedSurfaceMaterial.hpp" #include "Acts/Material/ProtoSurfaceMaterial.hpp" #include "Acts/Surfaces/Surface.hpp" -#include "Acts/Utilities/BinAdjustment.hpp" -#include "Acts/Utilities/BinUtility.hpp" Acts::BinnedSurfaceMaterialAccumulator::BinnedSurfaceMaterialAccumulator( const Config& cfg, std::unique_ptr mlogger) @@ -21,7 +19,7 @@ Acts::BinnedSurfaceMaterialAccumulator::BinnedSurfaceMaterialAccumulator( std::unique_ptr Acts::BinnedSurfaceMaterialAccumulator::createState( - const GeometryContext& gctx) const { + const GeometryContext& /*gctx*/) const { auto state = std::make_unique(); /// Create the surface accumulation @@ -38,43 +36,21 @@ Acts::BinnedSurfaceMaterialAccumulator::createState( // First attempt from ProtoSurfaceMaterial auto psm = dynamic_cast(surfaceMaterial); if (psm != nullptr) { - auto binUtility = psm->binning(); - // Screen output for Binned Surface material - ACTS_DEBUG(" - (proto) binning from ProtoSurfaceMateria is " - << binUtility); - // Now adjust to surface type - binUtility = adjustBinUtility(binUtility, *surface, gctx); - // Screen output for Binned Surface material - ACTS_DEBUG(" - adjusted binning is " << binUtility); - state->accumulatedMaterial[geoID] = - AccumulatedSurfaceMaterial(binUtility); - // Material accumulation is created for this - continue; - } - // Second attempt from ProtoGridSurfaceMaterial - auto psgm = dynamic_cast(surfaceMaterial); - if (psgm != nullptr) { - BinUtility binUtility(psgm->binning()); - // Screen output for Binned Surface material - ACTS_DEBUG(" - (proto) binning from ProtoGridSurfaceMaterial is " - << binUtility); - // Now adjust to surface type - binUtility = adjustBinUtility(binUtility, *surface, gctx); - // Screen output for Binned Surface material - ACTS_DEBUG(" - adjusted binning is " << binUtility); + // Screen output for proto material + ACTS_DEBUG(" - (proto) binning from ProtoSurfaceMaterial is " + << psm->directedProtoAxes()); state->accumulatedMaterial[geoID] = - AccumulatedSurfaceMaterial(binUtility); + AccumulatedSurfaceMaterial(psm->directedProtoAxes()); // Material accumulation is created for this continue; } // Third attempt: binned material auto bmp = dynamic_cast(surfaceMaterial); if (bmp != nullptr) { - // Screen output for Binned Surface material ACTS_DEBUG(" - binning from BinnedSurfaceMaterial is " - << bmp->binUtility()); + << bmp->directedProtoAxes()); state->accumulatedMaterial[geoID] = - AccumulatedSurfaceMaterial(bmp->binUtility()); + AccumulatedSurfaceMaterial(bmp->directedProtoAxes()); // Material accumulation is created for this continue; } diff --git a/Core/src/Material/SurfaceMaterialMapper.cpp b/Core/src/Material/SurfaceMaterialMapper.cpp index 3469c4a7f29..144de7c2559 100644 --- a/Core/src/Material/SurfaceMaterialMapper.cpp +++ b/Core/src/Material/SurfaceMaterialMapper.cpp @@ -23,8 +23,6 @@ #include "Acts/Propagator/SurfaceCollector.hpp" #include "Acts/Propagator/VolumeCollector.hpp" #include "Acts/Surfaces/SurfaceArray.hpp" -#include "Acts/Utilities/BinAdjustment.hpp" -#include "Acts/Utilities/BinUtility.hpp" #include "Acts/Utilities/Result.hpp" #include @@ -127,28 +125,19 @@ void SurfaceMaterialMapper::checkAndInsert(State& mState, // proper surface material auto psm = dynamic_cast(surfaceMaterial); - // Get the bin utility: try proxy material first - const BinUtility* bu = (psm != nullptr) ? (&psm->binning()) : nullptr; - if (bu != nullptr) { - // Screen output for Binned Surface material - ACTS_DEBUG(" - (proto) binning is " << *bu); - // Now update - BinUtility buAdjusted = adjustBinUtility(*bu, surface, mState.geoContext); - // Screen output for Binned Surface material - ACTS_DEBUG(" - adjusted binning is " << buAdjusted); + if (psm != nullptr) { + ACTS_DEBUG(" - (proto) binning is " << psm->directedProtoAxes()); mState.accumulatedMaterial[geoID] = - AccumulatedSurfaceMaterial(buAdjusted); + AccumulatedSurfaceMaterial(psm->directedProtoAxes()); return; } // Second attempt: binned material auto bmp = dynamic_cast(surfaceMaterial); - bu = (bmp != nullptr) ? (&bmp->binUtility()) : nullptr; - // Create a binned type of material - if (bu != nullptr) { - // Screen output for Binned Surface material - ACTS_DEBUG(" - binning is " << *bu); - mState.accumulatedMaterial[geoID] = AccumulatedSurfaceMaterial(*bu); + if (bmp != nullptr) { + ACTS_DEBUG(" - binning is " << bmp->directedProtoAxes()); + mState.accumulatedMaterial[geoID] = + AccumulatedSurfaceMaterial(bmp->directedProtoAxes()); } else { // Create a homogeneous type of material ACTS_DEBUG(" - this is homogeneous material."); diff --git a/Examples/Algorithms/MaterialMapping/include/ActsExamples/MaterialMapping/MappingMaterialDecorator.hpp b/Examples/Algorithms/MaterialMapping/include/ActsExamples/MaterialMapping/MappingMaterialDecorator.hpp index af49ac3d696..5a59a99f6f5 100644 --- a/Examples/Algorithms/MaterialMapping/include/ActsExamples/MaterialMapping/MappingMaterialDecorator.hpp +++ b/Examples/Algorithms/MaterialMapping/include/ActsExamples/MaterialMapping/MappingMaterialDecorator.hpp @@ -26,6 +26,7 @@ #include #include #include +#include // Convenience shorthand @@ -259,7 +260,18 @@ class MappingMaterialDecorator : public IMaterialDecorator { Acts::open, Acts::AxisDirection::AxisY); } } - return std::make_shared(bUtility); + std::vector directedProtoAxes; + directedProtoAxes.reserve(bUtility.binningData().size()); + for (const auto& bData : bUtility.binningData()) { + const auto boundaryType = bData.option == Acts::closed + ? Acts::AxisBoundaryType::Closed + : Acts::AxisBoundaryType::Bound; + directedProtoAxes.emplace_back( + bData.binvalue, boundaryType, static_cast(bData.min), + static_cast(bData.max), bData.bins()); + } + return std::make_shared( + std::move(directedProtoAxes)); } /// Readonly access to the BinningMap diff --git a/Examples/Detectors/GenericDetector/src/GenericDetectorBuilder.cpp b/Examples/Detectors/GenericDetector/src/GenericDetectorBuilder.cpp index a538c5a0de4..49689ee4e95 100644 --- a/Examples/Detectors/GenericDetector/src/GenericDetectorBuilder.cpp +++ b/Examples/Detectors/GenericDetector/src/GenericDetectorBuilder.cpp @@ -168,24 +168,25 @@ GenericDetectorBuilder::GenericDetectorBuilder( : m_cfg(cfg), m_logger(std::move(logger)) { // Prepare the proto material - in case it's designed to do so // - cylindrical - Acts::BinUtility pCylinderUtility(10, -1, 1, Acts::closed, - Acts::AxisDirection::AxisPhi); - pCylinderUtility += - Acts::BinUtility(10, -1, 1, Acts::open, Acts::AxisDirection::AxisZ); + std::vector pCylinderAxes = { + {Acts::AxisDirection::AxisPhi, Acts::AxisBoundaryType::Closed, -1., 1., + 10u}, + {Acts::AxisDirection::AxisZ, Acts::AxisBoundaryType::Bound, -1., 1., + 10u}}; auto pCylinderMaterial = - std::make_shared(pCylinderUtility); + std::make_shared(pCylinderAxes); // - disc - Acts::BinUtility pDiscUtility(10, 0, 1, Acts::open, - Acts::AxisDirection::AxisR); - pDiscUtility += - Acts::BinUtility(10, -1, 1, Acts::closed, Acts::AxisDirection::AxisPhi); + std::vector pDiscAxes = { + {Acts::AxisDirection::AxisR, Acts::AxisBoundaryType::Bound, 0., 1., 10u}, + {Acts::AxisDirection::AxisPhi, Acts::AxisBoundaryType::Closed, -1., 1., + 10u}}; auto pDiscMaterial = - std::make_shared(pDiscUtility); + std::make_shared(pDiscAxes); // - plane - Acts::BinUtility pPlaneUtility(1, -1, 1, Acts::open, - Acts::AxisDirection::AxisX); + std::vector pPlaneAxes = { + {Acts::AxisDirection::AxisX, Acts::AxisBoundaryType::Bound, -1., 1., 1u}}; auto pPlaneMaterial = - std::make_shared(pPlaneUtility); + std::make_shared(pPlaneAxes); /// /// BeamPipe material diff --git a/Examples/Scripts/Python/geometry.py b/Examples/Scripts/Python/geometry.py index c7dc75725f2..ff6dea3a8da 100755 --- a/Examples/Scripts/Python/geometry.py +++ b/Examples/Scripts/Python/geometry.py @@ -95,7 +95,7 @@ def runGeometry( if "__main__" == __name__: # detector = acts.examples.GenericDetector() - detector = getOpenDataDetector() + detector = getOpenDataDetector(logLevel=acts.logging.VERBOSE) trackingGeometry = detector.trackingGeometry() decorators = detector.contextDecorators() diff --git a/Plugins/DD4hep/include/ActsPlugins/DD4hep/DD4hepMaterialHelpers.hpp b/Plugins/DD4hep/include/ActsPlugins/DD4hep/DD4hepMaterialHelpers.hpp index 5be56259d2a..089755d4340 100644 --- a/Plugins/DD4hep/include/ActsPlugins/DD4hep/DD4hepMaterialHelpers.hpp +++ b/Plugins/DD4hep/include/ActsPlugins/DD4hep/DD4hepMaterialHelpers.hpp @@ -9,8 +9,7 @@ #pragma once #include "Acts/Material/ProtoSurfaceMaterial.hpp" -#include "Acts/Utilities/BinningData.hpp" -#include "Acts/Utilities/BinningType.hpp" +#include "Acts/Utilities/AxisDefinitions.hpp" #include "Acts/Utilities/Logger.hpp" #include @@ -64,7 +63,7 @@ void addDiscLayerProtoMaterial( /// @param logger a @c Logger for output void addLayerProtoMaterial( const dd4hep::rec::VariantParameters& params, Acts::Layer& layer, - const std::vector >& + const std::vector >& binning, const Acts::Logger& logger = Acts::getDummyLogger()); @@ -79,7 +78,7 @@ void addLayerProtoMaterial( /// @return Shared pointer to ProtoSurfaceMaterial created from DD4hep parameters std::shared_ptr createProtoMaterial( const dd4hep::rec::VariantParameters& params, const std::string& valueTag, - const std::vector >& + const std::vector >& binning, const Acts::Logger& logger = Acts::getDummyLogger()); diff --git a/Plugins/DD4hep/src/ConvertDD4hepDetector.cpp b/Plugins/DD4hep/src/ConvertDD4hepDetector.cpp index 70d6727c959..1a7df11a63b 100644 --- a/Plugins/DD4hep/src/ConvertDD4hepDetector.cpp +++ b/Plugins/DD4hep/src/ConvertDD4hepDetector.cpp @@ -242,15 +242,19 @@ std::shared_ptr ActsPlugins::volumeBuilder_dd4hep( auto& params = getParams(volumeDetElement); if (hasParam("boundary_material_negative", volumeDetElement)) { ACTS_VERBOSE("--> negative"); - cvbConfig.boundaryMaterial[2] = createProtoMaterial( - params, "boundary_material_negative", - {{"binPhi", closed}, {"binR", open}}, logger); + cvbConfig.boundaryMaterial[2] = + createProtoMaterial(params, "boundary_material_negative", + {{"binPhi", AxisBoundaryType::Closed}, + {"binR", AxisBoundaryType::Bound}}, + logger); } if (hasParam("boundary_material_positive", volumeDetElement)) { ACTS_VERBOSE("--> positive"); - cvbConfig.boundaryMaterial[3] = createProtoMaterial( - params, "boundary_material_positive", - {{"binPhi", closed}, {"binR", open}}, logger); + cvbConfig.boundaryMaterial[3] = + createProtoMaterial(params, "boundary_material_positive", + {{"binPhi", AxisBoundaryType::Closed}, + {"binR", AxisBoundaryType::Bound}}, + logger); } } } else { @@ -273,15 +277,19 @@ std::shared_ptr ActsPlugins::volumeBuilder_dd4hep( auto& params = getParams(volumeDetElement); if (params.contains("boundary_material_negative")) { ACTS_VERBOSE("--> negative"); - cvbConfig.boundaryMaterial[4] = createProtoMaterial( - params, "boundary_material_negative", - {{"binPhi", closed}, {"binR", open}}, logger); + cvbConfig.boundaryMaterial[4] = + createProtoMaterial(params, "boundary_material_negative", + {{"binPhi", AxisBoundaryType::Closed}, + {"binR", AxisBoundaryType::Bound}}, + logger); } if (params.contains("boundary_material_positive")) { ACTS_VERBOSE("--> positive"); - cvbConfig.boundaryMaterial[5] = createProtoMaterial( - params, "boundary_material_positive", - {{"binPhi", closed}, {"binR", open}}, logger); + cvbConfig.boundaryMaterial[5] = + createProtoMaterial(params, "boundary_material_positive", + {{"binPhi", AxisBoundaryType::Closed}, + {"binR", AxisBoundaryType::Bound}}, + logger); } } } @@ -306,15 +314,19 @@ std::shared_ptr ActsPlugins::volumeBuilder_dd4hep( auto& params = getParams(volumeDetElement); if (params.contains("boundary_material_negative")) { ACTS_VERBOSE("--> negative"); - cvbConfig.boundaryMaterial[3] = createProtoMaterial( - params, "boundary_material_negative", - {{"binPhi", closed}, {"binR", open}}, logger); + cvbConfig.boundaryMaterial[3] = + createProtoMaterial(params, "boundary_material_negative", + {{"binPhi", AxisBoundaryType::Closed}, + {"binR", AxisBoundaryType::Bound}}, + logger); } if (params.contains("boundary_material_positive")) { ACTS_VERBOSE("--> positive"); - cvbConfig.boundaryMaterial[4] = createProtoMaterial( - params, "boundary_material_positive", - {{"binPhi", closed}, {"binR", open}}, logger); + cvbConfig.boundaryMaterial[4] = + createProtoMaterial(params, "boundary_material_positive", + {{"binPhi", AxisBoundaryType::Closed}, + {"binR", AxisBoundaryType::Bound}}, + logger); } } } else { @@ -335,13 +347,17 @@ std::shared_ptr ActsPlugins::volumeBuilder_dd4hep( ACTS_VERBOSE("--> inner"); cvbConfig.boundaryMaterial[0] = createProtoMaterial(params, "boundary_material_inner", - {{"binPhi", closed}, {"binZ", open}}, logger); + {{"binPhi", AxisBoundaryType::Closed}, + {"binZ", AxisBoundaryType::Bound}}, + logger); } if (params.contains("boundary_material_outer")) { ACTS_VERBOSE("--> outer"); cvbConfig.boundaryMaterial[1] = createProtoMaterial(params, "boundary_material_outer", - {{"binPhi", closed}, {"binZ", open}}, logger); + {{"binPhi", AxisBoundaryType::Closed}, + {"binZ", AxisBoundaryType::Bound}}, + logger); } } } @@ -418,9 +434,11 @@ std::shared_ptr ActsPlugins::volumeBuilder_dd4hep( if (getParamOr("layer_material", subDetector, false)) { // get the possible material of the surrounding volume ACTS_VERBOSE("--> adding layer material at 'representing'"); - plMaterial = createProtoMaterial( - getParams(subDetector), "layer_material_representing", - {{"binPhi", closed}, {"binZ", open}}, logger); + plMaterial = createProtoMaterial(getParams(subDetector), + "layer_material_representing", + {{"binPhi", AxisBoundaryType::Closed}, + {"binZ", AxisBoundaryType::Bound}}, + logger); } // configure the passive layer builder @@ -453,13 +471,17 @@ std::shared_ptr ActsPlugins::volumeBuilder_dd4hep( ACTS_VERBOSE("--> inner"); cvbConfig.boundaryMaterial[0] = createProtoMaterial(params, "boundary_material_inner", - {{"binPhi", closed}, {"binZ", open}}, logger); + {{"binPhi", AxisBoundaryType::Closed}, + {"binZ", AxisBoundaryType::Bound}}, + logger); } if (hasParam("boundary_material_outer", subDetector)) { ACTS_VERBOSE("--> outer"); cvbConfig.boundaryMaterial[1] = createProtoMaterial(params, "boundary_material_outer", - {{"binPhi", closed}, {"binZ", open}}, logger); + {{"binPhi", AxisBoundaryType::Closed}, + {"binZ", AxisBoundaryType::Bound}}, + logger); } } diff --git a/Plugins/DD4hep/src/DD4hepBinningHelpers.cpp b/Plugins/DD4hep/src/DD4hepBinningHelpers.cpp index 9f09fc2b2c7..6673e45166c 100644 --- a/Plugins/DD4hep/src/DD4hepBinningHelpers.cpp +++ b/Plugins/DD4hep/src/DD4hepBinningHelpers.cpp @@ -19,7 +19,6 @@ DD4hepBinningHelpers::convertBinning(const dd4hep::DetElement &dd4hepElement, const std::string &bname) { // Return proto binning vector std::vector> protoBinnings; - for (const auto &[ab, axisDir] : allowedBinnings) { auto type = getParamOr(bname + "_" + ab + "_type", dd4hepElement, ""); @@ -45,7 +44,7 @@ DD4hepBinningHelpers::convertBinning(const dd4hep::DetElement &dd4hepElement, double minDefault = axisDir == AxisDirection::AxisPhi ? -std::numbers::pi : 0.; double maxDefault = - axisDir == AxisDirection::AxisPhi ? std::numbers::pi : 0.; + axisDir == AxisDirection::AxisPhi ? std::numbers::pi : 1.; auto min = getParamOr(bname + "_" + ab + "_min", dd4hepElement, minDefault); auto max = getParamOr(bname + "_" + ab + "_max", diff --git a/Plugins/DD4hep/src/DD4hepMaterialHelpers.cpp b/Plugins/DD4hep/src/DD4hepMaterialHelpers.cpp index 456e0f1dc2e..5cb115ecce3 100644 --- a/Plugins/DD4hep/src/DD4hepMaterialHelpers.cpp +++ b/Plugins/DD4hep/src/DD4hepMaterialHelpers.cpp @@ -11,8 +11,7 @@ #include "Acts/Geometry/ApproachDescriptor.hpp" #include "Acts/Geometry/Layer.hpp" #include "Acts/Surfaces/Surface.hpp" -#include "Acts/Utilities/BinUtility.hpp" -#include "Acts/Utilities/BinningType.hpp" +#include "Acts/Utilities/ProtoAxis.hpp" #include "ActsPlugins/DD4hep/DD4hepConversionHelpers.hpp" #include @@ -26,35 +25,27 @@ using namespace Acts; std::shared_ptr ActsPlugins::createProtoMaterial( const dd4hep::rec::VariantParameters& params, const std::string& valueTag, - const std::vector >& binning, + const std::vector >& binning, const Logger& logger) { using namespace std::string_literals; - // Create the bin utility - BinUtility bu; + std::vector directedProtoAxes; + directedProtoAxes.reserve(binning.size()); // Loop over the bins for (auto& bin : binning) { AxisDirection bval = axisDirectionFromName(bin.first); - BinningOption bopt = bin.second; - double min = 0.; - double max = 0.; - if (bopt == closed) { - min = -std::numbers::pi; - max = std::numbers::pi; - } + AxisBoundaryType bType = bin.second; int bins = params.get(valueTag + "_"s + bin.first); ACTS_VERBOSE(" - material binning for " << bin.first << " on " << valueTag << ": " << bins); - if (bins >= 1) { - bu += BinUtility(bins, min, max, bopt, bval); - } + directedProtoAxes.emplace_back(bval, bType, bins); } - return std::make_shared(bu); + return std::make_shared(std::move(directedProtoAxes)); } void ActsPlugins::addLayerProtoMaterial( const dd4hep::rec::VariantParameters& params, Layer& layer, - const std::vector >& binning, + const std::vector >& binning, const Logger& logger) { ACTS_VERBOSE("addLayerProtoMaterial"); // Start with the representing surface @@ -103,7 +94,9 @@ void ActsPlugins::addCylinderLayerProtoMaterial(dd4hep::DetElement detElement, } if (getParamOr("layer_material", detElement, false)) { addLayerProtoMaterial(getParams(detElement), cylinderLayer, - {{"binPhi", closed}, {"binZ", open}}, logger); + {{"binPhi", AxisBoundaryType::Closed}, + {"binZ", AxisBoundaryType::Bound}}, + logger); } } @@ -120,6 +113,8 @@ void ActsPlugins::addDiscLayerProtoMaterial(dd4hep::DetElement detElement, } if (getParamOr("layer_material", detElement, false)) { addLayerProtoMaterial(getParams(detElement), discLayer, - {{"binPhi", closed}, {"binR", open}}, logger); + {{"binPhi", AxisBoundaryType::Closed}, + {"binR", AxisBoundaryType::Bound}}, + logger); } } diff --git a/Plugins/Detray/include/ActsPlugins/Detray/DetrayPayloadConverter.hpp b/Plugins/Detray/include/ActsPlugins/Detray/DetrayPayloadConverter.hpp index f5da69c88c5..abf95379ab9 100644 --- a/Plugins/Detray/include/ActsPlugins/Detray/DetrayPayloadConverter.hpp +++ b/Plugins/Detray/include/ActsPlugins/Detray/DetrayPayloadConverter.hpp @@ -104,20 +104,11 @@ class DetrayPayloadConverter { static std::optional convertBinnedSurfaceMaterial( const Acts::BinnedSurfaceMaterial& material); - /// Convert proto surface material with bin utility + /// Convert proto surface material /// @param material Proto surface material /// @return Detray surface material payload - static std::optional - convertProtoSurfaceMaterialBinUtility( - const Acts::ProtoSurfaceMaterialT& material); - - /// Convert proto surface material with proto axes - /// @param material Proto surface material - /// @return Detray surface material payload - static std::optional - convertProtoSurfaceMaterialProtoAxes( - const Acts::ProtoSurfaceMaterialT>& - material); + static std::optional convertProtoSurfaceMaterial( + const Acts::ProtoSurfaceMaterial& material); /// Convert surface array navigation policy /// @param policy Surface array navigation policy @@ -220,8 +211,7 @@ class DetrayPayloadConverter { std::optional()> convertSurfaceMaterial{ convertHomogeneousSurfaceMaterial, convertBinnedSurfaceMaterial, - convertGridSurfaceMaterial, convertProtoSurfaceMaterialProtoAxes, - convertProtoSurfaceMaterialBinUtility}; + convertGridSurfaceMaterial, convertProtoSurfaceMaterial}; }; /// Convert surface bounds to detray mask payload diff --git a/Plugins/Detray/src/DetrayMaterial.cpp b/Plugins/Detray/src/DetrayMaterial.cpp index 7b2963aca28..5f1c3f6463d 100644 --- a/Plugins/Detray/src/DetrayMaterial.cpp +++ b/Plugins/Detray/src/DetrayMaterial.cpp @@ -27,6 +27,16 @@ namespace ActsPlugins { using DetraySurfaceMaterial = DetrayPayloadConverter::DetraySurfaceMaterial; using DetraySurfaceGrid = DetrayPayloadConverter::DetraySurfaceGrid; +namespace { +BinUtility toBinUtility(const BinnedSurfaceMaterial& material) { + BinUtility converted; + for (const auto& axis : material.directedProtoAxes()) { + converted += BinUtility(BinningData(axis)); + } + return converted; +} +} // namespace + std::optional DetrayPayloadConverter::convertBinnedSurfaceMaterial( const BinnedSurfaceMaterial& material) { @@ -35,7 +45,7 @@ DetrayPayloadConverter::convertBinnedSurfaceMaterial( // Detray expects 2-dimensional grid, currently supported are // x-y, r-phi, phi-z auto [bUtility, swapped] = - DetrayConversionUtils::convertBinUtilityTo2D(material.binUtility()); + DetrayConversionUtils::convertBinUtilityTo2D(toBinUtility(material)); AxisDirection bVal0 = bUtility.binningData()[0u].binvalue; AxisDirection bVal1 = bUtility.binningData()[1u].binvalue; @@ -99,14 +109,8 @@ DetrayPayloadConverter::convertHomogeneousSurfaceMaterial( } std::optional -DetrayPayloadConverter::convertProtoSurfaceMaterialBinUtility( - const ProtoSurfaceMaterialT& /*material*/) { - return std::nullopt; -} - -std::optional -DetrayPayloadConverter::convertProtoSurfaceMaterialProtoAxes( - const ProtoSurfaceMaterialT>& /*material*/) { +DetrayPayloadConverter::convertProtoSurfaceMaterial( + const ProtoSurfaceMaterial& /*material*/) { return std::nullopt; } diff --git a/Plugins/Detray/src/DetrayMaterialConverter.cpp b/Plugins/Detray/src/DetrayMaterialConverter.cpp index e4b2a1b1db7..51d3b218795 100644 --- a/Plugins/Detray/src/DetrayMaterialConverter.cpp +++ b/Plugins/Detray/src/DetrayMaterialConverter.cpp @@ -36,6 +36,14 @@ struct MaterialSurfaceSelector { } }; +BinUtility toBinUtility(const BinnedSurfaceMaterial& material) { + BinUtility converted; + for (const auto& axis : material.directedProtoAxes()) { + converted += BinUtility(BinningData(axis)); + } + return converted; +} + } // namespace detray::io::detector_homogeneous_material_payload @@ -125,7 +133,7 @@ ActsPlugins::DetrayMaterialConverter::convertGridSurfaceMaterial( // Detray expects 2-dimensional grid, currently supported are // x-y, r-phi, phi-z auto [bUtility, swapped] = DetrayConversionUtils::convertBinUtilityTo2D( - binnedMaterial->binUtility()); + toBinUtility(*binnedMaterial)); AxisDirection bVal0 = bUtility.binningData()[0u].binvalue; AxisDirection bVal1 = bUtility.binningData()[1u].binvalue; @@ -175,10 +183,10 @@ ActsPlugins::DetrayMaterialConverter::convertGridSurfaceMaterial( } if (dynamic_cast(&material) != nullptr || - dynamic_cast(&material) != nullptr) { + dynamic_cast(&material) != nullptr) { ACTS_WARNING( "DetrayMaterialConverter: ProtoSurfaceMaterial and " - "ProtoGridSurfaceMaterial are not being translated, consider to switch " + "ProtoSurfaceMaterial are not being translated, consider to switch " "material conversion off."); return materialGrid; } diff --git a/Plugins/Json/include/ActsPlugins/Json/GeometryJsonKeys.hpp b/Plugins/Json/include/ActsPlugins/Json/GeometryJsonKeys.hpp index cffa1ec3555..908d8b398dc 100644 --- a/Plugins/Json/include/ActsPlugins/Json/GeometryJsonKeys.hpp +++ b/Plugins/Json/include/ActsPlugins/Json/GeometryJsonKeys.hpp @@ -24,6 +24,8 @@ struct jsonKey { std::string namekey = "NAME"; /// The bin key std::string binkey = "binUtility"; + /// The directed proto axes key + std::string directedaxeskey = "directedProtoAxes"; /// The material key std::string materialkey = "material"; /// The local to global transformation key diff --git a/Plugins/Json/include/ActsPlugins/Json/UtilitiesJsonConverter.hpp b/Plugins/Json/include/ActsPlugins/Json/UtilitiesJsonConverter.hpp index 8f56f92f9f4..1b2c41ce615 100644 --- a/Plugins/Json/include/ActsPlugins/Json/UtilitiesJsonConverter.hpp +++ b/Plugins/Json/include/ActsPlugins/Json/UtilitiesJsonConverter.hpp @@ -11,6 +11,7 @@ #include "Acts/Utilities/BinUtility.hpp" #include "Acts/Utilities/BinningData.hpp" #include "Acts/Utilities/BinningType.hpp" +#include "Acts/Utilities/ProtoAxis.hpp" #include "Acts/Utilities/RangeXD.hpp" #include "ActsPlugins/Json/ActsJson.hpp" @@ -42,6 +43,26 @@ void to_json(nlohmann::json& j, const BinUtility& bu); /// @param bu BinUtility to populate void from_json(const nlohmann::json& j, BinUtility& bu); +/// Convert ProtoAxis to JSON +/// @param j JSON object to write to +/// @param pa ProtoAxis to convert +void to_json(nlohmann::json& j, const ProtoAxis& pa); + +/// Convert JSON to ProtoAxis +/// @param j JSON object to convert from +/// @param pa ProtoAxis to populate +void from_json(const nlohmann::json& j, ProtoAxis& pa); + +/// Convert DirectedProtoAxis to JSON +/// @param j JSON object to write to +/// @param dpa DirectedProtoAxis to convert +void to_json(nlohmann::json& j, const DirectedProtoAxis& dpa); + +/// Convert JSON to DirectedProtoAxis +/// @param j JSON object to convert from +/// @param dpa DirectedProtoAxis to populate +void from_json(const nlohmann::json& j, DirectedProtoAxis& dpa); + /// Convert Range1D to JSON /// @param j JSON object to write to /// @param r Range1D to convert diff --git a/Plugins/Json/src/MaterialJsonConverter.cpp b/Plugins/Json/src/MaterialJsonConverter.cpp index 8988d30b6aa..da48b429e80 100644 --- a/Plugins/Json/src/MaterialJsonConverter.cpp +++ b/Plugins/Json/src/MaterialJsonConverter.cpp @@ -31,6 +31,7 @@ #include "ActsPlugins/Json/UtilitiesJsonConverter.hpp" #include +#include #include #include #include @@ -281,6 +282,96 @@ Acts::ISurfaceMaterial* indexedMaterialFromJson(nlohmann::json& jMaterial) { return nullptr; } +Acts::BinUtility directedAxesToBinUtility( + const std::vector& directedProtoAxes) { + Acts::BinUtility converted; + for (const auto& directedProtoAxis : directedProtoAxes) { + converted += Acts::BinUtility(Acts::BinningData(directedProtoAxis)); + } + return converted; +} + +std::vector legacyBinUtilityJsonToDirectedAxes( + const nlohmann::json& jLegacyBinUtility) { + std::vector directedProtoAxes; + if (!jLegacyBinUtility.contains("binningdata")) { + return directedProtoAxes; + } + + auto parseDirection = [](const nlohmann::json& jValue) { + if (jValue.is_string()) { + const auto value = jValue.get(); + if (value == "binX") { + return Acts::AxisDirection::AxisX; + } + if (value == "binY") { + return Acts::AxisDirection::AxisY; + } + if (value == "binZ") { + return Acts::AxisDirection::AxisZ; + } + if (value == "binR") { + return Acts::AxisDirection::AxisR; + } + if (value == "binPhi") { + return Acts::AxisDirection::AxisPhi; + } + if (value == "binRPhi") { + return Acts::AxisDirection::AxisRPhi; + } + if (value == "binH") { + return Acts::AxisDirection::AxisTheta; + } + if (value == "binEta") { + return Acts::AxisDirection::AxisEta; + } + if (value == "binMag") { + return Acts::AxisDirection::AxisMag; + } + } + return jValue.get(); + }; + + for (const auto& jAxis : jLegacyBinUtility.at("binningdata")) { + const auto direction = parseDirection(jAxis.at("value")); + const auto option = jAxis.at("option").get(); + const auto boundaryType = option == "closed" + ? Acts::AxisBoundaryType::Closed + : Acts::AxisBoundaryType::Bound; + const auto axisType = jAxis.at("type").get(); + if (axisType == "arbitrary" && jAxis.contains("boundaries")) { + directedProtoAxes.emplace_back( + direction, boundaryType, + jAxis.at("boundaries").get>()); + continue; + } + // Get min/max and if 0 then create auto-range axis + double min = jAxis.at("min").get(); + double max = jAxis.at("max").get(); + if (min == 0. && max == 0.) { + directedProtoAxes.emplace_back(direction, boundaryType, + jAxis.at("bins").get()); + } else { + directedProtoAxes.emplace_back( + direction, boundaryType, jAxis.at("min").get(), + jAxis.at("max").get(), jAxis.at("bins").get()); + } + } + return directedProtoAxes; +} + +std::size_t directedAxesTotalBins( + const std::vector& directedProtoAxes) { + if (directedProtoAxes.empty()) { + return 0u; + } + std::size_t totalBins = 1u; + for (const auto& axis : directedProtoAxes) { + totalBins *= axis.getAxis().getNBins(); + } + return totalBins; +} + } // namespace void Acts::to_json(nlohmann::json& j, const Material& t) { @@ -333,8 +424,6 @@ void Acts::from_json(const nlohmann::json& j, MaterialSlabMatrix& t) { void Acts::to_json(nlohmann::json& j, const surfaceMaterialPointer& material) { nlohmann::json jMaterial; - // A bin utility needs to be written - const Acts::BinUtility* bUtility = nullptr; // First: Check if we have a proto material auto psMaterial = dynamic_cast(material); @@ -346,18 +435,14 @@ void Acts::to_json(nlohmann::json& j, const surfaceMaterialPointer& material) { jMaterial[Acts::jsonKey().maptype] = mapType; // by default the protoMaterial is not used for mapping jMaterial[Acts::jsonKey().mapkey] = false; - // write the bin utility - bUtility = &(psMaterial->binning()); + const auto& directedProtoAxes = psMaterial->directedProtoAxes(); + jMaterial[Acts::jsonKey().directedaxeskey] = directedProtoAxes; // Check in the number of bin is different from 1 - auto& binningData = bUtility->binningData(); - for (std::size_t ibin = 0; ibin < binningData.size(); ++ibin) { - if (binningData[ibin].bins() > 1) { + for (const auto& axis : directedProtoAxes) { + if (axis.getAxis().getNBins() > 1u) { jMaterial[Acts::jsonKey().mapkey] = true; - break; } } - nlohmann::json jBin(*bUtility); - jMaterial[Acts::jsonKey().binkey] = jBin; j[Acts::jsonKey().materialkey] = jMaterial; return; } @@ -393,7 +478,8 @@ void Acts::to_json(nlohmann::json& j, const surfaceMaterialPointer& material) { jMaterial[Acts::jsonKey().maptype] = mapType; // Material has been mapped jMaterial[Acts::jsonKey().mapkey] = true; - bUtility = &(bsMaterial->binUtility()); + jMaterial[Acts::jsonKey().directedaxeskey] = + bsMaterial->directedProtoAxes(); // convert the data // get the material matrix nlohmann::json mmat = nlohmann::json::array(); @@ -406,9 +492,6 @@ void Acts::to_json(nlohmann::json& j, const surfaceMaterialPointer& material) { mmat.push_back(std::move(mvec)); } jMaterial[Acts::jsonKey().datakey] = std::move(mmat); - // write the bin utility - nlohmann::json jBin(*bUtility); - jMaterial[Acts::jsonKey().binkey] = jBin; j[Acts::jsonKey().materialkey] = jMaterial; return; } @@ -473,28 +556,54 @@ void Acts::from_json(const nlohmann::json& j, return; } - // The bin utility and material - Acts::BinUtility bUtility; Acts::MaterialSlabMatrix mpMatrix; Acts::MappingType mapType = Acts::MappingType::Default; + std::vector directedProtoAxes; for (auto& [key, value] : jMaterial.items()) { - if (key == Acts::jsonKey().binkey && !value.empty()) { - from_json(value, bUtility); - } if (key == Acts::jsonKey().datakey && !value.empty()) { from_json(value, mpMatrix); } if (key == Acts::jsonKey().maptype && !value.empty()) { from_json(value, mapType); } + if (key == Acts::jsonKey().directedaxeskey && !value.empty()) { + directedProtoAxes.clear(); + directedProtoAxes.reserve(value.size()); + for (const auto& jAxis : value) { + Acts::DirectedProtoAxis axis(Acts::AxisDirection::AxisX, + Acts::AxisBoundaryType::Bound, 1u); + from_json(jAxis, axis); + directedProtoAxes.push_back(std::move(axis)); + } + } + // Legacy fallback: old schema stores a full BinUtility JSON object. + // Parse the legacy axis description directly into DirectedProtoAxis. + if (key == Acts::jsonKey().binkey && !value.empty() && + directedProtoAxes.empty()) { + directedProtoAxes = legacyBinUtilityJsonToDirectedAxes(value); + } } // Return the appropriate typr of material if (mpMatrix.empty()) { - material = new Acts::ProtoSurfaceMaterial(bUtility, mapType); - } else if (bUtility.bins() == 1) { + material = + new Acts::ProtoSurfaceMaterial(std::move(directedProtoAxes), mapType); + } else if (directedProtoAxes.size() > 2u) { + throw std::invalid_argument( + "Surface material JSON supports at most 2 directed proto axes."); + } else if (directedAxesTotalBins(directedProtoAxes) <= 1u) { material = new Acts::HomogeneousSurfaceMaterial(mpMatrix[0][0], 1, mapType); } else { - material = new Acts::BinnedSurfaceMaterial(bUtility, mpMatrix, 1, mapType); + if (directedProtoAxes.size() == 1u) { + material = + new Acts::BinnedSurfaceMaterial(std::move(directedProtoAxes[0u]), + std::move(mpMatrix[0u]), 1, mapType); + } else { + material = new Acts::BinnedSurfaceMaterial( + std::array{ + std::move(directedProtoAxes[0u]), + std::move(directedProtoAxes[1u])}, + std::move(mpMatrix), 1, mapType); + } } } @@ -686,7 +795,8 @@ nlohmann::json Acts::MaterialJsonConverter::toJsonDetray( // Get the bin utility (make a copy as we may modify it) // Detray expects 2-dimensional grid, currently supported are // x-y, r-phi, phi-z - BinUtility bUtility = binnedMaterial->binUtility(); + BinUtility bUtility = + directedAxesToBinUtility(binnedMaterial->directedProtoAxes()); // Turn the bin value into a 2D grid if (bUtility.dimensions() == 1u) { if (bUtility.binningData()[0u].binvalue == AxisDirection::AxisR) { diff --git a/Plugins/Json/src/MaterialMapJsonConverter.cpp b/Plugins/Json/src/MaterialMapJsonConverter.cpp index 151282a0c50..398ce7ab5d6 100644 --- a/Plugins/Json/src/MaterialMapJsonConverter.cpp +++ b/Plugins/Json/src/MaterialMapJsonConverter.cpp @@ -91,7 +91,7 @@ Acts::SurfaceAndMaterialWithContext defaultSurfaceMaterial( if (surface->surfaceMaterialSharedPtr() != nullptr) { return {surface, surface->surfaceMaterialSharedPtr(), context}; } - Acts::BinUtility bUtility; + std::vector directedProtoAxes; // Check which type of bounds is associated to the surface const Acts::SurfaceBounds& surfaceBounds = surface->bounds(); const Acts::RadialBounds* radialBounds = @@ -106,68 +106,73 @@ Acts::SurfaceAndMaterialWithContext defaultSurfaceMaterial( dynamic_cast(&surfaceBounds); if (radialBounds != nullptr) { - bUtility += Acts::BinUtility( - 1, + directedProtoAxes.emplace_back( + Acts::AxisDirection::AxisPhi, + (radialBounds->get(Acts::RadialBounds::eHalfPhiSector) - + std::numbers::pi) < Acts::s_epsilon + ? Acts::AxisBoundaryType::Closed + : Acts::AxisBoundaryType::Bound, radialBounds->get(Acts::RadialBounds::eAveragePhi) - radialBounds->get(Acts::RadialBounds::eHalfPhiSector), radialBounds->get(Acts::RadialBounds::eAveragePhi) + radialBounds->get(Acts::RadialBounds::eHalfPhiSector), - (radialBounds->get(Acts::RadialBounds::eHalfPhiSector) - - std::numbers::pi) < Acts::s_epsilon - ? Acts::closed - : Acts::open, - Acts::AxisDirection::AxisPhi); - bUtility += Acts::BinUtility(1, radialBounds->rMin(), radialBounds->rMax(), - Acts::open, Acts::AxisDirection::AxisR); + 1); + directedProtoAxes.emplace_back( + Acts::AxisDirection::AxisR, Acts::AxisBoundaryType::Bound, + radialBounds->rMin(), radialBounds->rMax(), 1); } if (cylinderBounds != nullptr) { - bUtility += Acts::BinUtility( - 1, + directedProtoAxes.emplace_back( + Acts::AxisDirection::AxisPhi, + (cylinderBounds->get(Acts::CylinderBounds::eHalfPhiSector) - + std::numbers::pi) < Acts::s_epsilon + ? Acts::AxisBoundaryType::Closed + : Acts::AxisBoundaryType::Bound, cylinderBounds->get(Acts::CylinderBounds::eAveragePhi) - cylinderBounds->get(Acts::CylinderBounds::eHalfPhiSector), cylinderBounds->get(Acts::CylinderBounds::eAveragePhi) + cylinderBounds->get(Acts::CylinderBounds::eHalfPhiSector), - (cylinderBounds->get(Acts::CylinderBounds::eHalfPhiSector) - - std::numbers::pi) < Acts::s_epsilon - ? Acts::closed - : Acts::open, - Acts::AxisDirection::AxisPhi); - bUtility += Acts::BinUtility( - 1, -1 * cylinderBounds->get(Acts::CylinderBounds::eHalfLengthZ), - cylinderBounds->get(Acts::CylinderBounds::eHalfLengthZ), Acts::open, - Acts::AxisDirection::AxisZ); + 1); + directedProtoAxes.emplace_back( + Acts::AxisDirection::AxisZ, Acts::AxisBoundaryType::Bound, + -1 * cylinderBounds->get(Acts::CylinderBounds::eHalfLengthZ), + cylinderBounds->get(Acts::CylinderBounds::eHalfLengthZ), 1); } if (annulusBounds != nullptr) { - bUtility += - Acts::BinUtility(1, annulusBounds->get(Acts::AnnulusBounds::eMinPhiRel), - annulusBounds->get(Acts::AnnulusBounds::eMaxPhiRel), - Acts::open, Acts::AxisDirection::AxisPhi); - bUtility += Acts::BinUtility(1, static_cast(annulusBounds->rMin()), - static_cast(annulusBounds->rMax()), - Acts::open, Acts::AxisDirection::AxisR); + directedProtoAxes.emplace_back( + Acts::AxisDirection::AxisPhi, Acts::AxisBoundaryType::Bound, + annulusBounds->get(Acts::AnnulusBounds::eMinPhiRel), + annulusBounds->get(Acts::AnnulusBounds::eMaxPhiRel), 1); + directedProtoAxes.emplace_back( + Acts::AxisDirection::AxisR, Acts::AxisBoundaryType::Bound, + static_cast(annulusBounds->rMin()), + static_cast(annulusBounds->rMax()), 1); } if (rectangleBounds != nullptr) { - bUtility += - Acts::BinUtility(1, rectangleBounds->get(Acts::RectangleBounds::eMinX), - rectangleBounds->get(Acts::RectangleBounds::eMaxX), - Acts::open, Acts::AxisDirection::AxisX); - bUtility += - Acts::BinUtility(1, rectangleBounds->get(Acts::RectangleBounds::eMinY), - rectangleBounds->get(Acts::RectangleBounds::eMaxY), - Acts::open, Acts::AxisDirection::AxisY); + directedProtoAxes.emplace_back( + Acts::AxisDirection::AxisX, Acts::AxisBoundaryType::Bound, + rectangleBounds->get(Acts::RectangleBounds::eMinX), + rectangleBounds->get(Acts::RectangleBounds::eMaxX), 1); + directedProtoAxes.emplace_back( + Acts::AxisDirection::AxisY, Acts::AxisBoundaryType::Bound, + rectangleBounds->get(Acts::RectangleBounds::eMinY), + rectangleBounds->get(Acts::RectangleBounds::eMaxY), 1); } if (trapezoidBounds != nullptr) { double halfLengthX = std::max(trapezoidBounds->get(Acts::TrapezoidBounds::eHalfLengthXnegY), trapezoidBounds->get(Acts::TrapezoidBounds::eHalfLengthXposY)); - bUtility += Acts::BinUtility(1, -1 * halfLengthX, halfLengthX, Acts::open, - Acts::AxisDirection::AxisX); - bUtility += Acts::BinUtility( - 1, -1 * trapezoidBounds->get(Acts::TrapezoidBounds::eHalfLengthY), - trapezoidBounds->get(Acts::TrapezoidBounds::eHalfLengthY), Acts::open, - Acts::AxisDirection::AxisY); + directedProtoAxes.emplace_back(Acts::AxisDirection::AxisX, + Acts::AxisBoundaryType::Bound, + -1 * halfLengthX, halfLengthX, 1); + directedProtoAxes.emplace_back( + Acts::AxisDirection::AxisY, Acts::AxisBoundaryType::Bound, + -1 * trapezoidBounds->get(Acts::TrapezoidBounds::eHalfLengthY), + trapezoidBounds->get(Acts::TrapezoidBounds::eHalfLengthY), 1); } - return {surface, std::make_shared(bUtility), + return {surface, + std::make_shared( + std::move(directedProtoAxes)), context}; } diff --git a/Plugins/Json/src/UtilitiesJsonConverter.cpp b/Plugins/Json/src/UtilitiesJsonConverter.cpp index f1cdc1ab331..98f8d72e025 100644 --- a/Plugins/Json/src/UtilitiesJsonConverter.cpp +++ b/Plugins/Json/src/UtilitiesJsonConverter.cpp @@ -12,13 +12,49 @@ #include "Acts/Utilities/BinningData.hpp" #include "Acts/Utilities/BinningType.hpp" #include "ActsPlugins/Json/AlgebraJsonConverter.hpp" +#include "ActsPlugins/Json/GridJsonConverter.hpp" #include #include +#include #include #include #include +namespace { + +Acts::ProtoAxis protoAxisFromJsonImpl(const nlohmann::json& j) { + const auto axisBoundaryType = + j.at("axis").at("boundary_type").get(); + const auto axisType = j.at("axis").at("type").get(); + if (axisType == Acts::AxisType::Equidistant) { + const auto nbins = j.at("axis").at("bins").get(); + if (nbins == 0u) { + throw std::invalid_argument("Number of bins must be positive"); + } + if (j.at("autorange").get()) { + return Acts::ProtoAxis(axisBoundaryType, nbins); + } + const auto min = j.at("axis").at("range").at(0).get(); + const auto max = j.at("axis").at("range").at(1).get(); + if (min >= max) { + throw std::invalid_argument("Invalid range: min must be less than max"); + } + return Acts::ProtoAxis(axisBoundaryType, min, max, nbins); + } + const auto binEdges = + j.at("axis").at("boundaries").get>(); + if (binEdges.size() < 2u) { + throw std::invalid_argument("At least two bin edges required"); + } + if (!std::ranges::is_sorted(binEdges)) { + throw std::invalid_argument("Bin edges must be sorted in ascending order"); + } + return Acts::ProtoAxis(axisBoundaryType, binEdges); +} + +} // namespace + void Acts::to_json(nlohmann::json& j, const Acts::BinningData& bd) { // Common to all bin utilities j["min"] = bd.min; @@ -132,3 +168,51 @@ void Acts::from_json(const nlohmann::json& j, Acts::BinUtility& bu) { bu += Acts::BinUtility(bd); } } + +void Acts::to_json(nlohmann::json& j, const Acts::ProtoAxis& pa) { + j["axis"] = AxisJsonConverter::toJson(pa.getAxis()); + j["autorange"] = pa.isAutorange(); +} + +void Acts::from_json(const nlohmann::json& j, Acts::ProtoAxis& pa) { + pa = protoAxisFromJsonImpl(j); +} + +void Acts::to_json(nlohmann::json& j, const Acts::DirectedProtoAxis& dpa) { + j["axis"] = AxisJsonConverter::toJson(dpa.getAxis()); + j["autorange"] = dpa.isAutorange(); + j["direction"] = dpa.getAxisDirection(); +} + +void Acts::from_json(const nlohmann::json& j, Acts::DirectedProtoAxis& dpa) { + const auto direction = j.at("direction").get(); + const auto axisBoundaryType = + j.at("axis").at("boundary_type").get(); + const auto axisType = j.at("axis").at("type").get(); + if (axisType == Acts::AxisType::Equidistant) { + const auto nbins = j.at("axis").at("bins").get(); + if (nbins == 0u) { + throw std::invalid_argument("Number of bins must be positive"); + } + if (j.at("autorange").get()) { + dpa = Acts::DirectedProtoAxis(direction, axisBoundaryType, nbins); + return; + } + const auto min = j.at("axis").at("range").at(0).get(); + const auto max = j.at("axis").at("range").at(1).get(); + if (min >= max) { + throw std::invalid_argument("Invalid range: min must be less than max"); + } + dpa = Acts::DirectedProtoAxis(direction, axisBoundaryType, min, max, nbins); + return; + } + const auto binEdges = + j.at("axis").at("boundaries").get>(); + if (binEdges.size() < 2u) { + throw std::invalid_argument("At least two bin edges required"); + } + if (!std::ranges::is_sorted(binEdges)) { + throw std::invalid_argument("Bin edges must be sorted in ascending order"); + } + dpa = Acts::DirectedProtoAxis(direction, axisBoundaryType, binEdges); +} diff --git a/Plugins/Root/include/ActsPlugins/Root/RootMaterialMapIo.hpp b/Plugins/Root/include/ActsPlugins/Root/RootMaterialMapIo.hpp index ec2f8498089..4a579fe1073 100644 --- a/Plugins/Root/include/ActsPlugins/Root/RootMaterialMapIo.hpp +++ b/Plugins/Root/include/ActsPlugins/Root/RootMaterialMapIo.hpp @@ -55,8 +55,11 @@ class RootMaterialMapIo { std::string nBinsHistName = "n"; /// The axis direction histogram name: AxisZ, AxisR, AxisPhi, etc. std::string axisDirHistName = "v"; + /// The axis boundary type histogram name (read in only) + /// Legacy name, to be replaced by axisBoundaryTypeHistName + std::string axisOptionHistName = "o"; /// The axis boundary type hist name - std::string axisBoundaryTypeHistName = "o"; + std::string axisBoundaryTypeHistName = "b"; /// The range histogram name: min value std::string minRangeHistName = "min"; /// The range histogram name: max value diff --git a/Plugins/Root/src/RootMaterialMapIo.cpp b/Plugins/Root/src/RootMaterialMapIo.cpp index ae995a07e75..a7e7da81314 100644 --- a/Plugins/Root/src/RootMaterialMapIo.cpp +++ b/Plugins/Root/src/RootMaterialMapIo.cpp @@ -17,6 +17,8 @@ #include "Acts/Surfaces/Surface.hpp" #include "Acts/Utilities/Enumerate.hpp" +#include + #include #include #include @@ -75,21 +77,22 @@ void ActsPlugins::RootMaterialMapIo::write( // Boundary condistions // Get the binning data - auto& binningData = bsMaterial->binUtility().binningData(); + auto protoAxes = bsMaterial->directedProtoAxes(); + // 1-D or 2-D maps - auto bins = static_cast(binningData.size()); + auto bins = static_cast(protoAxes.size()); auto fBins = static_cast(bins); // The bin number information TH1F n(m_cfg.nBinsHistName.c_str(), "bins; bin", bins, -0.5, fBins - 0.5); // The binning value information - TH1F v(m_cfg.axisDirHistName.c_str(), "binning values; bin", bins, -0.5, + TH1F v(m_cfg.axisDirHistName.c_str(), "axus direction; bin", bins, -0.5, fBins - 0.5); // The binning option information - TH1F o(m_cfg.axisBoundaryTypeHistName.c_str(), "binning options; bin", bins, - -0.5, fBins - 0.5); + TH1F b(m_cfg.axisBoundaryTypeHistName.c_str(), "axis boundary type; bin", + bins, -0.5, fBins - 0.5); // The binning option information - range min TH1F rmin(m_cfg.minRangeHistName.c_str(), "min; bin", bins, -0.5, @@ -100,18 +103,21 @@ void ActsPlugins::RootMaterialMapIo::write( fBins - 0.5); // Now fill the histogram content - for (auto [b, bData] : enumerate(binningData)) { + for (auto [bi, pAxis] : enumerate(protoAxes)) { + const auto& axis = pAxis.getAxis(); // Fill: nbins, value, option, min, max - n.SetBinContent(static_cast(b) + 1, static_cast(bData.bins())); - v.SetBinContent(static_cast(b) + 1, - static_cast(bData.binvalue)); - o.SetBinContent(static_cast(b) + 1, static_cast(bData.option)); - rmin.SetBinContent(static_cast(b) + 1, bData.min); - rmax.SetBinContent(static_cast(b) + 1, bData.max); + n.SetBinContent(static_cast(bi) + 1, + static_cast(axis.getNBins())); + v.SetBinContent(static_cast(bi) + 1, + static_cast(pAxis.getAxisDirection())); + b.SetBinContent(static_cast(bi) + 1, + static_cast(axis.getBoundaryType())); + rmin.SetBinContent(static_cast(bi) + 1, axis.getMin()); + rmax.SetBinContent(static_cast(bi) + 1, axis.getMax()); } n.Write(); v.Write(); - o.Write(); + b.Write(); rmin.Write(); rmax.Write(); @@ -190,8 +196,11 @@ void ActsPlugins::RootMaterialMapIo::fillMaterialSlab( void ActsPlugins::RootMaterialMapIo::fillBinnedSurfaceMaterial( const BinnedSurfaceMaterial& bsMaterial) { - auto bins0 = static_cast(bsMaterial.binUtility().bins(0)); - auto bins1 = static_cast(bsMaterial.binUtility().bins(1)); + const auto& dProtoAxes = bsMaterial.directedProtoAxes(); + auto bins0 = static_cast(dProtoAxes[0].getAxis().getNBins()); + auto bins1 = dProtoAxes.size() > 1 + ? static_cast(dProtoAxes[1].getAxis().getNBins()) + : 1; auto fBins0 = static_cast(bins0); auto fBins1 = static_cast(bins1); @@ -236,8 +245,11 @@ void ActsPlugins::RootMaterialMapIo::fillBinnedSurfaceMaterial( void ActsPlugins::RootMaterialMapIo::fillBinnedSurfaceMaterial( MaterialTreePayload& payload, const BinnedSurfaceMaterial& bsMaterial) { - std::size_t bins0 = bsMaterial.binUtility().bins(0); - std::size_t bins1 = bsMaterial.binUtility().bins(1); + const auto& dProtoAxes = bsMaterial.directedProtoAxes(); + auto bins0 = static_cast(dProtoAxes[0].getAxis().getNBins()); + auto bins1 = dProtoAxes.size() > 1 + ? static_cast(dProtoAxes[1].getAxis().getNBins()) + : 1; TH2I idx(m_cfg.indexHistName.c_str(), "indices; bin0; bin1", static_cast(bins0), -0.5, static_cast(bins0) - 0.5, @@ -360,17 +372,27 @@ ActsPlugins::RootMaterialMapIo::readTextureSurfaceMaterial( // Construct the common names & get the common histograms std::string nName = tdName + "/" + m_cfg.nBinsHistName; std::string vName = tdName + "/" + m_cfg.axisDirHistName; - std::string oName = tdName + "/" + m_cfg.axisBoundaryTypeHistName; + std::string bName = tdName + "/" + m_cfg.axisBoundaryTypeHistName; std::string minName = tdName + "/" + m_cfg.minRangeHistName; std::string maxName = tdName + "/" + m_cfg.maxRangeHistName; // Get the histograms - auto n = dynamic_cast(rFile.Get(nName.c_str())); - auto v = dynamic_cast(rFile.Get(vName.c_str())); - auto o = dynamic_cast(rFile.Get(oName.c_str())); - auto minh = dynamic_cast(rFile.Get(minName.c_str())); - auto maxh = dynamic_cast(rFile.Get(maxName.c_str())); + bool legacyDetected = false; + TH1F* n = dynamic_cast(rFile.Get(nName.c_str())); + TH1F* v = dynamic_cast(rFile.Get(vName.c_str())); + TH1F* b = dynamic_cast(rFile.Get(bName.c_str())); + if (b == nullptr) { + bName = tdName + "/" + m_cfg.axisOptionHistName; + ACTS_INFO( + "Legacy histogram detected for boundary type, please consider " + "updating."); + b = dynamic_cast(rFile.Get(bName.c_str())); + legacyDetected = true; + } - std::vector hists{n, v, o, minh, maxh}; + TH1F* minh = dynamic_cast(rFile.Get(minName.c_str())); + TH1F* maxh = dynamic_cast(rFile.Get(maxName.c_str())); + + std::vector hists{n, v, b, minh, maxh}; if (std::ranges::any_of(hists, [](const auto* hist) { return hist == nullptr; })) { ACTS_ERROR( @@ -381,16 +403,30 @@ ActsPlugins::RootMaterialMapIo::readTextureSurfaceMaterial( } // Now reconstruct the bin utilities - BinUtility bUtility; + std::vector dProtoAxes; for (int ib = 1; ib < n->GetNbinsX() + 1; ++ib) { - auto nbins = static_cast(n->GetBinContent(ib)); - auto val = static_cast(v->GetBinContent(ib)); - auto opt = static_cast(o->GetBinContent(ib)); - auto rmin = static_cast(minh->GetBinContent(ib)); - auto rmax = static_cast(maxh->GetBinContent(ib)); - bUtility += BinUtility(nbins, rmin, rmax, opt, val); + std::size_t nBins = static_cast(n->GetBinContent(ib)); + AxisDirection aDir = static_cast(v->GetBinContent(ib)); + AxisBoundaryType bType = AxisBoundaryType::Bound; + if (legacyDetected) { + int opt = static_cast(b->GetBinContent(ib)); + if (opt == 0) { + bType = AxisBoundaryType::Closed; + } else if (opt == 1) { + bType = AxisBoundaryType::Bound; + } else { + throw std::runtime_error( + "Invalid axis boundary type option read from legacy histogram: " + + std::to_string(opt)); + } + } else { + bType = static_cast(b->GetBinContent(ib)); + } + double rmin = minh->GetBinContent(ib); + double rmax = maxh->GetBinContent(ib); + dProtoAxes.emplace_back(DirectedProtoAxis(aDir, bType, rmin, rmax, nBins)); } - ACTS_VERBOSE("Created " << bUtility); + ACTS_VERBOSE("Created " << dProtoAxes.size() << " directed proto axes"); /// Draw from histogram only source if (indexedMaterialTree == nullptr) { @@ -438,8 +474,14 @@ ActsPlugins::RootMaterialMapIo::readTextureSurfaceMaterial( } } } // Construct the binned material with the right bin utility - texturedSurfaceMaterial = std::make_shared( - bUtility, std::move(materialMatrix)); + if (dProtoAxes.size() == 1u) { + texturedSurfaceMaterial = std::make_shared( + dProtoAxes[0u], materialMatrix[0u]); + } else { + texturedSurfaceMaterial = std::make_shared( + std::array{dProtoAxes[0u], dProtoAxes[1u]}, + std::move(materialMatrix)); + } } } else { // Construct the names for histogram type storage @@ -467,8 +509,14 @@ ActsPlugins::RootMaterialMapIo::readTextureSurfaceMaterial( MaterialSlab(material, m_indexedMaterialTreePayload.ht); } } // Construct the binned material with the right bin utility - texturedSurfaceMaterial = std::make_shared( - bUtility, std::move(materialMatrix)); + if (dProtoAxes.size() == 1u) { + texturedSurfaceMaterial = std::make_shared( + dProtoAxes[0u], materialMatrix[0u]); + } else { + texturedSurfaceMaterial = std::make_shared( + std::array{dProtoAxes[0u], dProtoAxes[1u]}, + std::move(materialMatrix)); + } } } diff --git a/Python/Core/src/Material.cpp b/Python/Core/src/Material.cpp index f95e6a1a0ae..db46ddd1428 100644 --- a/Python/Core/src/Material.cpp +++ b/Python/Core/src/Material.cpp @@ -52,10 +52,6 @@ void addMaterial(py::module_& m) { m, "ISurfaceMaterial") .def("toString", &ISurfaceMaterial::toString); - py::class_>( - m, "ProtoGridSurfaceMaterial"); - py::class_>(m, "ProtoSurfaceMaterial"); diff --git a/Tests/UnitTests/Core/Geometry/BlueprintTests.cpp b/Tests/UnitTests/Core/Geometry/BlueprintTests.cpp index fe6958cc1ad..228e4977b75 100644 --- a/Tests/UnitTests/Core/Geometry/BlueprintTests.cpp +++ b/Tests/UnitTests/Core/Geometry/BlueprintTests.cpp @@ -649,21 +649,23 @@ BOOST_AUTO_TEST_CASE(MaterialTesting) { .surface() .surfaceMaterial(); BOOST_REQUIRE_NE(negDisc, nullptr); - const auto& negDiscMat = - dynamic_cast(*negDisc); + const auto& negDiscMat = dynamic_cast(*negDisc); // Check positive disc material const auto* posDisc = child.portals() .at(static_cast(PositiveDisc)) .surface() .surfaceMaterial(); BOOST_REQUIRE_NE(posDisc, nullptr); - const auto& posDiscMat = - dynamic_cast(*posDisc); + const auto& posDiscMat = dynamic_cast(*posDisc); - BOOST_CHECK_EQUAL(negDiscMat.binning().at(0).getAxis().getNBins(), 5); - BOOST_CHECK_EQUAL(negDiscMat.binning().at(1).getAxis().getNBins(), 10); - BOOST_CHECK_EQUAL(posDiscMat.binning().at(0).getAxis().getNBins(), 15); - BOOST_CHECK_EQUAL(posDiscMat.binning().at(1).getAxis().getNBins(), 20); + BOOST_CHECK_EQUAL(negDiscMat.directedProtoAxes().at(0).getAxis().getNBins(), + 5); + BOOST_CHECK_EQUAL(negDiscMat.directedProtoAxes().at(1).getAxis().getNBins(), + 10); + BOOST_CHECK_EQUAL(posDiscMat.directedProtoAxes().at(0).getAxis().getNBins(), + 15); + BOOST_CHECK_EQUAL(posDiscMat.directedProtoAxes().at(1).getAxis().getNBins(), + 20); // Check outer cylinder material const auto* outerCyl = child.portals() @@ -672,9 +674,11 @@ BOOST_AUTO_TEST_CASE(MaterialTesting) { .surfaceMaterial(); BOOST_REQUIRE_NE(outerCyl, nullptr); const auto& outerCylMat = - dynamic_cast(*outerCyl); - BOOST_CHECK_EQUAL(outerCylMat.binning().at(0).getAxis().getNBins(), 25); - BOOST_CHECK_EQUAL(outerCylMat.binning().at(1).getAxis().getNBins(), 30); + dynamic_cast(*outerCyl); + BOOST_CHECK_EQUAL(outerCylMat.directedProtoAxes().at(0).getAxis().getNBins(), + 25); + BOOST_CHECK_EQUAL(outerCylMat.directedProtoAxes().at(1).getAxis().getNBins(), + 30); // Check that other faces have no material for (std::size_t i = 0; i < child.portals().size(); i++) { @@ -823,45 +827,46 @@ BOOST_AUTO_TEST_CASE(MaterialCuboid) { BOOST_REQUIRE_NE(material, nullptr); const auto& gridMaterial = - dynamic_cast(*material); + dynamic_cast(*material); // Check binning based on face CuboidVolumeBounds::Face face = static_cast(i); switch (face) { case NegativeXFace: - BOOST_CHECK_EQUAL(gridMaterial.binning().at(0).getAxis().getNBins(), 5); - BOOST_CHECK_EQUAL(gridMaterial.binning().at(1).getAxis().getNBins(), - 10); + BOOST_CHECK_EQUAL( + gridMaterial.directedProtoAxes().at(0).getAxis().getNBins(), 5); + BOOST_CHECK_EQUAL( + gridMaterial.directedProtoAxes().at(1).getAxis().getNBins(), 10); break; case PositiveXFace: - BOOST_CHECK_EQUAL(gridMaterial.binning().at(0).getAxis().getNBins(), - 15); - BOOST_CHECK_EQUAL(gridMaterial.binning().at(1).getAxis().getNBins(), - 20); + BOOST_CHECK_EQUAL( + gridMaterial.directedProtoAxes().at(0).getAxis().getNBins(), 15); + BOOST_CHECK_EQUAL( + gridMaterial.directedProtoAxes().at(1).getAxis().getNBins(), 20); break; case NegativeYFace: - BOOST_CHECK_EQUAL(gridMaterial.binning().at(0).getAxis().getNBins(), - 25); - BOOST_CHECK_EQUAL(gridMaterial.binning().at(1).getAxis().getNBins(), - 30); + BOOST_CHECK_EQUAL( + gridMaterial.directedProtoAxes().at(0).getAxis().getNBins(), 25); + BOOST_CHECK_EQUAL( + gridMaterial.directedProtoAxes().at(1).getAxis().getNBins(), 30); break; case PositiveYFace: - BOOST_CHECK_EQUAL(gridMaterial.binning().at(0).getAxis().getNBins(), - 35); - BOOST_CHECK_EQUAL(gridMaterial.binning().at(1).getAxis().getNBins(), - 40); + BOOST_CHECK_EQUAL( + gridMaterial.directedProtoAxes().at(0).getAxis().getNBins(), 35); + BOOST_CHECK_EQUAL( + gridMaterial.directedProtoAxes().at(1).getAxis().getNBins(), 40); break; case NegativeZFace: - BOOST_CHECK_EQUAL(gridMaterial.binning().at(0).getAxis().getNBins(), - 45); - BOOST_CHECK_EQUAL(gridMaterial.binning().at(1).getAxis().getNBins(), - 50); + BOOST_CHECK_EQUAL( + gridMaterial.directedProtoAxes().at(0).getAxis().getNBins(), 45); + BOOST_CHECK_EQUAL( + gridMaterial.directedProtoAxes().at(1).getAxis().getNBins(), 50); break; case PositiveZFace: - BOOST_CHECK_EQUAL(gridMaterial.binning().at(0).getAxis().getNBins(), - 55); - BOOST_CHECK_EQUAL(gridMaterial.binning().at(1).getAxis().getNBins(), - 60); + BOOST_CHECK_EQUAL( + gridMaterial.directedProtoAxes().at(0).getAxis().getNBins(), 55); + BOOST_CHECK_EQUAL( + gridMaterial.directedProtoAxes().at(1).getAxis().getNBins(), 60); break; } } diff --git a/Tests/UnitTests/Core/Material/AccumulatedSurfaceMaterialTests.cpp b/Tests/UnitTests/Core/Material/AccumulatedSurfaceMaterialTests.cpp index 4e94f0f92e3..c93d3b6d3b7 100644 --- a/Tests/UnitTests/Core/Material/AccumulatedSurfaceMaterialTests.cpp +++ b/Tests/UnitTests/Core/Material/AccumulatedSurfaceMaterialTests.cpp @@ -13,8 +13,7 @@ #include "Acts/Material/AccumulatedSurfaceMaterial.hpp" #include "Acts/Material/Material.hpp" #include "Acts/Material/MaterialSlab.hpp" -#include "Acts/Utilities/BinUtility.hpp" -#include "Acts/Utilities/BinningType.hpp" +#include "Acts/Utilities/ProtoAxis.hpp" #include #include @@ -39,17 +38,21 @@ BOOST_AUTO_TEST_CASE(AccumulatedSurfaceMaterial_construction_test) { // Test: // BinsSurfaceMaterial accumulation - 1D - BinUtility binUtility1D(10, -5., 5., open, AxisDirection::AxisX); - AccumulatedSurfaceMaterial material1D{binUtility1D}; + DirectedProtoAxis xAxis1D(AxisDirection::AxisX, AxisBoundaryType::Bound, -5., + 5., 10u); + AccumulatedSurfaceMaterial material1D{{xAxis1D}, Transform3::Identity()}; auto accMat1D = material1D.accumulatedMaterial(); BOOST_CHECK_EQUAL(accMat1D.size(), 1u); BOOST_CHECK_EQUAL(accMat1D[0].size(), 10u); // Test: // BinsSurfaceMaterial accumulation - 2D - BinUtility binUtility2D(10, -5., 5., open, AxisDirection::AxisX); - binUtility2D += BinUtility(20, -10., 10., open, AxisDirection::AxisY); - AccumulatedSurfaceMaterial material2D{binUtility2D}; + DirectedProtoAxis xAxis2D(AxisDirection::AxisX, AxisBoundaryType::Bound, -5., + 5., 10u); + DirectedProtoAxis yAxis2D(AxisDirection::AxisY, AxisBoundaryType::Bound, -10., + 10., 20u); + AccumulatedSurfaceMaterial material2D{{xAxis2D, yAxis2D}, + Transform3::Identity()}; auto accMat2D = material2D.accumulatedMaterial(); BOOST_CHECK_EQUAL(accMat2D.size(), 20u); for (std::size_t ib = 0; ib < accMat2D.size(); ++ib) { @@ -95,9 +98,12 @@ BOOST_AUTO_TEST_CASE(AccumulatedSurfaceMaterial_fill_convert_1D) { MaterialSlab four(mat, 4.); // BinsSurfaceMaterial accumulation - 2D - BinUtility binUtility2D(2, -1., 1., open, AxisDirection::AxisX); - binUtility2D += BinUtility(2, -1., 1., open, AxisDirection::AxisY); - AccumulatedSurfaceMaterial material2D{binUtility2D}; + DirectedProtoAxis xAxis2D(AxisDirection::AxisX, AxisBoundaryType::Bound, -1., + 1., 2u); + DirectedProtoAxis yAxis2D(AxisDirection::AxisY, AxisBoundaryType::Bound, -1., + 1., 2u); + AccumulatedSurfaceMaterial material2D{{xAxis2D, yAxis2D}, + Transform3::Identity()}; const std::vector> bin; // assign in the different bins diff --git a/Tests/UnitTests/Core/Material/BinnedSurfaceMaterialAccumulatorTests.cpp b/Tests/UnitTests/Core/Material/BinnedSurfaceMaterialAccumulatorTests.cpp index 3dac67fae23..2d6aee39108 100644 --- a/Tests/UnitTests/Core/Material/BinnedSurfaceMaterialAccumulatorTests.cpp +++ b/Tests/UnitTests/Core/Material/BinnedSurfaceMaterialAccumulatorTests.cpp @@ -17,8 +17,8 @@ #include "Acts/Material/ProtoSurfaceMaterial.hpp" #include "Acts/Surfaces/CylinderSurface.hpp" #include "Acts/Surfaces/Surface.hpp" -#include "Acts/Utilities/BinUtility.hpp" #include "Acts/Utilities/Logger.hpp" +#include "Acts/Utilities/ProtoAxis.hpp" #include #include @@ -84,17 +84,19 @@ BOOST_AUTO_TEST_CASE(AccumulationTest) { std::make_shared(mp, 1.)); // Second surface is binned Phi / Z - BinUtility sb1(4, -std::numbers::pi, std::numbers::pi, closed, - AxisDirection::AxisPhi); - sb1 += BinUtility(2, -100., 100., open, AxisDirection::AxisZ); - surfaces[1u]->assignSurfaceMaterial( - std::make_shared(sb1)); + DirectedProtoAxis phiAxis(AxisDirection::AxisPhi, AxisBoundaryType::Closed, + -std::numbers::pi, std::numbers::pi, 4u); + DirectedProtoAxis zAxis(AxisDirection::AxisZ, AxisBoundaryType::Bound, -100., + 100., 2u); + surfaces[1u]->assignSurfaceMaterial(std::make_shared( + std::vector{phiAxis, zAxis})); // Third is binned std::vector mps = {mp, mp, mp}; - BinUtility sb2(3, -100., 100., open, AxisDirection::AxisZ); + DirectedProtoAxis zAxis2(AxisDirection::AxisZ, AxisBoundaryType::Bound, -100., + 100., 3u); surfaces[2u]->assignSurfaceMaterial( - std::make_shared(sb2, mps)); + std::make_shared(zAxis2, mps)); BinnedSurfaceMaterialAccumulator::Config bsmaConfig; bsmaConfig.materialSurfaces = {surfaces[0].get(), surfaces[1].get(), diff --git a/Tests/UnitTests/Core/Material/BinnedSurfaceMaterialTests.cpp b/Tests/UnitTests/Core/Material/BinnedSurfaceMaterialTests.cpp index 437cb654ee6..ea6e6f896e6 100644 --- a/Tests/UnitTests/Core/Material/BinnedSurfaceMaterialTests.cpp +++ b/Tests/UnitTests/Core/Material/BinnedSurfaceMaterialTests.cpp @@ -11,9 +11,8 @@ #include "Acts/Material/BinnedSurfaceMaterial.hpp" #include "Acts/Material/Material.hpp" #include "Acts/Material/MaterialSlab.hpp" -#include "Acts/Utilities/BinUtility.hpp" -#include "Acts/Utilities/BinningType.hpp" +#include #include #include @@ -25,8 +24,10 @@ BOOST_AUTO_TEST_SUITE(MaterialSuite) /// Test the constructors BOOST_AUTO_TEST_CASE(BinnedSurfaceMaterial_construction_test) { - BinUtility xyBinning(2, -1., 1., open, AxisDirection::AxisX); - xyBinning += BinUtility(3, -3., 3., open, AxisDirection::AxisY); + DirectedProtoAxis xAxis(AxisDirection::AxisX, AxisBoundaryType::Bound, -1., + 1., 2u); + DirectedProtoAxis yAxis(AxisDirection::AxisY, AxisBoundaryType::Bound, -3., + 3., 3u); // Constructor a few material properties MaterialSlab a00(Material::fromMolarDensity(1., 2., 3., 4., 5.), 6.); @@ -46,7 +47,8 @@ BOOST_AUTO_TEST_CASE(BinnedSurfaceMaterial_construction_test) { std::move(l2)}; // Create the material - BinnedSurfaceMaterial bsm(xyBinning, std::move(m)); + BinnedSurfaceMaterial bsm(std::array{xAxis, yAxis}, + std::move(m)); // Copy the material BinnedSurfaceMaterial bsmCopy(bsm); diff --git a/Tests/UnitTests/Core/Material/ProtoSurfaceMaterialTests.cpp b/Tests/UnitTests/Core/Material/ProtoSurfaceMaterialTests.cpp index 64c2b8f2765..207d2b7fb71 100644 --- a/Tests/UnitTests/Core/Material/ProtoSurfaceMaterialTests.cpp +++ b/Tests/UnitTests/Core/Material/ProtoSurfaceMaterialTests.cpp @@ -9,8 +9,6 @@ #include #include "Acts/Material/ProtoSurfaceMaterial.hpp" -#include "Acts/Utilities/BinUtility.hpp" -#include "Acts/Utilities/BinningType.hpp" #include @@ -22,11 +20,13 @@ BOOST_AUTO_TEST_SUITE(MaterialSuite) /// Test the constructors BOOST_AUTO_TEST_CASE(ProtoSurfaceMaterial_construction_test) { - BinUtility smpBU(10, -10., 10., open, AxisDirection::AxisX); - smpBU += BinUtility(10, -10., 10., open, AxisDirection::AxisY); + DirectedProtoAxis xAxis(AxisDirection::AxisX, AxisBoundaryType::Bound, -10., + 10., 10u); + DirectedProtoAxis yAxis(AxisDirection::AxisY, AxisBoundaryType::Bound, -10., + 10., 10u); // Constructor from arguments - ProtoSurfaceMaterial smp(smpBU); + ProtoSurfaceMaterial smp({xAxis, yAxis}); // Copy constructor ProtoSurfaceMaterial smpCopy(smp); // Copy move constructor diff --git a/Tests/UnitTests/Plugins/Detray/DetrayMaterialConversionTests.cpp b/Tests/UnitTests/Plugins/Detray/DetrayMaterialConversionTests.cpp index 92e365ff174..d290d0b22e2 100644 --- a/Tests/UnitTests/Plugins/Detray/DetrayMaterialConversionTests.cpp +++ b/Tests/UnitTests/Plugins/Detray/DetrayMaterialConversionTests.cpp @@ -16,9 +16,12 @@ #include "Acts/Surfaces/RectangleBounds.hpp" #include "Acts/Surfaces/Surface.hpp" #include "Acts/Utilities/Logger.hpp" +#include "Acts/Utilities/ProtoAxis.hpp" #include "ActsPlugins/Detray/DetrayPayloadConverter.hpp" #include "ActsTests/CommonHelpers/FloatComparisons.hpp" +#include + #include auto logger = Acts::getDefaultLogger("Test", Acts::Logging::INFO); @@ -150,15 +153,15 @@ unpackGrid(const DetrayPayloadConverter::DetraySurfaceMaterial& material) { BOOST_AUTO_TEST_CASE(DetrayBinnedMaterialConversionX) { // Create a binned material in 4 bins in x direction - Acts::BinUtility binUtility(4u, -2., 2., Acts::BinningOption::open, - Acts::AxisDirection::AxisX); + Acts::DirectedProtoAxis xAxis(Acts::AxisDirection::AxisX, + Acts::AxisBoundaryType::Bound, -2., 2., 4u); std::vector materialSlabs = { materialSlab12345, materialSlab678910, materialSlab54321, materialSlab109876}; - auto binnedMaterial = Acts::BinnedSurfaceMaterial( - binUtility, {materialSlabs}, 0., Acts::MappingType::Default); + auto binnedMaterial = Acts::BinnedSurfaceMaterial(xAxis, materialSlabs, 0., + Acts::MappingType::Default); detray::io::grid_payload @@ -212,15 +215,15 @@ BOOST_AUTO_TEST_CASE(DetrayBinnedMaterialConversionX) { BOOST_AUTO_TEST_CASE(DetrayBinnedMaterialConversionY) { // Create a binned material in 4 bins in y direction - Acts::BinUtility binUtility(4u, -2., 2., Acts::BinningOption::open, - Acts::AxisDirection::AxisY); + Acts::DirectedProtoAxis yAxis(Acts::AxisDirection::AxisY, + Acts::AxisBoundaryType::Bound, -2., 2., 4u); std::vector materialSlabs = { materialSlab12345, materialSlab678910, materialSlab54321, materialSlab109876}; - auto binnedMaterial = Acts::BinnedSurfaceMaterial( - binUtility, {materialSlabs}, 0., Acts::MappingType::Default); + auto binnedMaterial = Acts::BinnedSurfaceMaterial(yAxis, materialSlabs, 0., + Acts::MappingType::Default); detray::io::grid_payload @@ -274,19 +277,19 @@ BOOST_AUTO_TEST_CASE(DetrayBinnedMaterialConversionY) { BOOST_AUTO_TEST_CASE(DetrayBinnedMaterialConversionXY) { // Create a binned material in 2 x2 bins in x-y direction - Acts::BinUtility binUtility(2u, -1., 1., Acts::BinningOption::open, - Acts::AxisDirection::AxisX); - binUtility += Acts::BinUtility(2u, -2., 2., Acts::BinningOption::open, - Acts::AxisDirection::AxisY); + Acts::DirectedProtoAxis xAxis(Acts::AxisDirection::AxisX, + Acts::AxisBoundaryType::Bound, -1., 1., 2u); + Acts::DirectedProtoAxis yAxis(Acts::AxisDirection::AxisY, + Acts::AxisBoundaryType::Bound, -2., 2., 2u); std::vector materialSlabs0 = {materialSlab12345, materialSlab678910}; std::vector materialSlabs1 = {materialSlab54321, materialSlab109876}; - auto binnedMaterial = - Acts::BinnedSurfaceMaterial(binUtility, {materialSlabs0, materialSlabs1}, - 0., Acts::MappingType::Default); + auto binnedMaterial = Acts::BinnedSurfaceMaterial( + std::array{xAxis, yAxis}, + {materialSlabs0, materialSlabs1}, 0., Acts::MappingType::Default); detray::io::grid_payload @@ -332,16 +335,16 @@ BOOST_AUTO_TEST_CASE(DetrayBinnedMaterialConversionXY) { BOOST_AUTO_TEST_CASE(DetrayBinnedMaterialConversionR) { // Create a binned material in 4 bins (irregularly) in r direction - std::vector binEdges = {0., 5., 10., 15., 20.}; - Acts::BinUtility binUtility(binEdges, Acts::BinningOption::open, - Acts::AxisDirection::AxisR); + std::vector binEdges = {0., 5., 10., 15., 20.}; + Acts::DirectedProtoAxis rAxis(Acts::AxisDirection::AxisR, + Acts::AxisBoundaryType::Bound, binEdges); std::vector materialSlabs = { materialSlab12345, materialSlab678910, materialSlab54321, materialSlab109876}; - auto binnedMaterial = Acts::BinnedSurfaceMaterial( - binUtility, {materialSlabs}, 0., Acts::MappingType::Default); + auto binnedMaterial = Acts::BinnedSurfaceMaterial(rAxis, materialSlabs, 0., + Acts::MappingType::Default); detray::io::grid_payload payload = @@ -373,21 +376,21 @@ BOOST_AUTO_TEST_CASE(DetrayBinnedMaterialConversionR) { BOOST_AUTO_TEST_CASE(DetrayBinnedMaterialConversionRPhi) { // Create a binned material in 2 bins - irregularly in r, 2 bins in phi - std::vector binEdges = {0., 5., 20.}; - Acts::BinUtility binUtility(binEdges, Acts::BinningOption::open, - Acts::AxisDirection::AxisR); - binUtility += Acts::BinUtility(2u, -std::numbers::pi, std::numbers::pi, - Acts::BinningOption::closed, - Acts::AxisDirection::AxisPhi); + std::vector binEdges = {0., 5., 20.}; + Acts::DirectedProtoAxis rAxis(Acts::AxisDirection::AxisR, + Acts::AxisBoundaryType::Bound, binEdges); + Acts::DirectedProtoAxis phiAxis(Acts::AxisDirection::AxisPhi, + Acts::AxisBoundaryType::Closed, + -std::numbers::pi, std::numbers::pi, 2u); std::vector materialSlabs0 = {materialSlab12345, materialSlab678910}; std::vector materialSlabs1 = {materialSlab54321, materialSlab109876}; - auto binnedMaterial = - Acts::BinnedSurfaceMaterial(binUtility, {materialSlabs0, materialSlabs1}, - 0., Acts::MappingType::Default); + auto binnedMaterial = Acts::BinnedSurfaceMaterial( + std::array{rAxis, phiAxis}, + {materialSlabs0, materialSlabs1}, 0., Acts::MappingType::Default); detray::io::grid_payload @@ -414,16 +417,16 @@ BOOST_AUTO_TEST_CASE(DetrayBinnedMaterialConversionRPhi) { BOOST_AUTO_TEST_CASE(DetrayBinnedMaterialConversionZ) { // Create a binned material in 4 bins in x direction - std::vector binEdges = {-20, 0, 25, 50, 100}; - Acts::BinUtility binUtility(binEdges, Acts::BinningOption::open, - Acts::AxisDirection::AxisZ); + std::vector binEdges = {-20., 0., 25., 50., 100.}; + Acts::DirectedProtoAxis zAxis(Acts::AxisDirection::AxisZ, + Acts::AxisBoundaryType::Bound, binEdges); std::vector materialSlabs = { materialSlab12345, materialSlab678910, materialSlab54321, materialSlab109876}; - auto binnedMaterial = Acts::BinnedSurfaceMaterial( - binUtility, {materialSlabs}, 0., Acts::MappingType::Default); + auto binnedMaterial = Acts::BinnedSurfaceMaterial(zAxis, materialSlabs, 0., + Acts::MappingType::Default); detray::io::grid_payload @@ -456,20 +459,20 @@ BOOST_AUTO_TEST_CASE(DetrayBinnedMaterialConversionZ) { BOOST_AUTO_TEST_CASE(DetrayBinnedMaterialConversionZPhi) { // Create a binned material in 2 x2 bins in x-y direction - Acts::BinUtility binUtility(2u, -1., 1., Acts::BinningOption::open, - Acts::AxisDirection::AxisZ); - binUtility += Acts::BinUtility(2u, -std::numbers::pi, std::numbers::pi, - Acts::BinningOption::closed, - Acts::AxisDirection::AxisPhi); + Acts::DirectedProtoAxis zAxis(Acts::AxisDirection::AxisZ, + Acts::AxisBoundaryType::Bound, -1., 1., 2u); + Acts::DirectedProtoAxis phiAxis(Acts::AxisDirection::AxisPhi, + Acts::AxisBoundaryType::Closed, + -std::numbers::pi, std::numbers::pi, 2u); std::vector materialSlabs0 = {materialSlab12345, materialSlab678910}; std::vector materialSlabs1 = {materialSlab54321, materialSlab109876}; - auto binnedMaterial = - Acts::BinnedSurfaceMaterial(binUtility, {materialSlabs0, materialSlabs1}, - 0., Acts::MappingType::Default); + auto binnedMaterial = Acts::BinnedSurfaceMaterial( + std::array{zAxis, phiAxis}, + {materialSlabs0, materialSlabs1}, 0., Acts::MappingType::Default); detray::io::grid_payload @@ -490,19 +493,19 @@ BOOST_AUTO_TEST_CASE(DetrayBinnedMaterialConversionZPhi) { BOOST_AUTO_TEST_CASE(DetrayBinnedMaterialConversionInvalid) { // Create a binned material in 4 bins in x direction - Acts::BinUtility binUtility(2u, -1., 1., Acts::BinningOption::open, - Acts::AxisDirection::AxisR); - binUtility += Acts::BinUtility(2u, -2., 2., Acts::BinningOption::open, - Acts::AxisDirection::AxisEta); + Acts::DirectedProtoAxis rAxis(Acts::AxisDirection::AxisR, + Acts::AxisBoundaryType::Bound, -1., 1., 2u); + Acts::DirectedProtoAxis etaAxis(Acts::AxisDirection::AxisEta, + Acts::AxisBoundaryType::Bound, -2., 2., 2u); std::vector materialSlabs0 = {materialSlab12345, materialSlab678910}; std::vector materialSlabs1 = {materialSlab54321, materialSlab109876}; - auto binnedMaterial = - Acts::BinnedSurfaceMaterial(binUtility, {materialSlabs0, materialSlabs1}, - 0., Acts::MappingType::Default); + auto binnedMaterial = Acts::BinnedSurfaceMaterial( + std::array{rAxis, etaAxis}, + {materialSlabs0, materialSlabs1}, 0., Acts::MappingType::Default); BOOST_CHECK_THROW( DetrayPayloadConverter::convertBinnedSurfaceMaterial(binnedMaterial), diff --git a/Tests/UnitTests/Plugins/Json/MaterialJsonConverterTests.cpp b/Tests/UnitTests/Plugins/Json/MaterialJsonConverterTests.cpp index 56dac5f8168..be3493ab1f5 100644 --- a/Tests/UnitTests/Plugins/Json/MaterialJsonConverterTests.cpp +++ b/Tests/UnitTests/Plugins/Json/MaterialJsonConverterTests.cpp @@ -8,11 +8,14 @@ #include +#include "Acts/Material/BinnedSurfaceMaterial.hpp" #include "Acts/Material/GridSurfaceMaterial.hpp" #include "Acts/Material/Material.hpp" #include "Acts/Material/MaterialSlab.hpp" +#include "Acts/Material/ProtoSurfaceMaterial.hpp" #include "Acts/Utilities/GridAccessHelpers.hpp" #include "Acts/Utilities/GridAxisGenerators.hpp" +#include "ActsPlugins/Json/GeometryJsonKeys.hpp" #include "ActsPlugins/Json/MaterialJsonConverter.hpp" #include "ActsTests/CommonHelpers/FloatComparisons.hpp" @@ -157,6 +160,66 @@ BOOST_AUTO_TEST_CASE(IndexedSurfaceMaterial2DTests) { BOOST_REQUIRE(ismRead != nullptr); } +BOOST_AUTO_TEST_CASE(BinnedSurfaceMaterialDirectedAxesSchemaTests) { + DirectedProtoAxis xAxis(AxisDirection::AxisX, AxisBoundaryType::Bound, -1., + 1., 2u); + MaterialSlab slabA(Material::fromMolarDensity(1., 2., 3., 4., 5.), 0.1f); + MaterialSlab slabB(Material::fromMolarDensity(2., 3., 4., 5., 6.), 0.2f); + BinnedSurfaceMaterial bsm(xAxis, std::vector{slabA, slabB}); + + const ISurfaceMaterial* materialPtr = &bsm; + nlohmann::json jMaterial = materialPtr; + BOOST_REQUIRE(jMaterial.contains(jsonKey().materialkey)); + + const auto& jPayload = jMaterial.at(jsonKey().materialkey); + BOOST_CHECK(jPayload.contains(jsonKey().directedaxeskey)); + BOOST_CHECK(!jPayload.contains(jsonKey().binkey)); + + const ISurfaceMaterial* decoded = nullptr; + from_json(jMaterial, decoded); + BOOST_REQUIRE(decoded != nullptr); + const auto* decodedBinned = + dynamic_cast(decoded); + BOOST_REQUIRE(decodedBinned != nullptr); + BOOST_CHECK_EQUAL(decodedBinned->directedProtoAxes().size(), 1u); + BOOST_CHECK_EQUAL(decodedBinned->directedProtoAxes()[0u].getAxis().getNBins(), + 2u); +} + +BOOST_AUTO_TEST_CASE(LegacyBinUtilitySurfaceMaterialReadTests) { + MaterialSlab slab(Material::fromMolarDensity(1., 2., 3., 4., 5.), 0.5f); + nlohmann::json jSlab = slab; + + nlohmann::json jLegacy; + jLegacy[jsonKey().materialkey] = { + {jsonKey().typekey, "binned"}, + {jsonKey().mapkey, true}, + {jsonKey().maptype, "Default"}, + {jsonKey().binkey, + {{"binningdata", + {{{"min", -1.0}, + {"max", 1.0}, + {"option", "open"}, + {"value", "binX"}, + {"type", "equidistant"}, + {"bins", 2}}}}}}, + {jsonKey().datakey, + nlohmann::json::array({nlohmann::json::array({jSlab, jSlab})})}}; + + const ISurfaceMaterial* decoded = nullptr; + from_json(jLegacy, decoded); + BOOST_REQUIRE(decoded != nullptr); + const auto* decodedBinned = + dynamic_cast(decoded); + BOOST_REQUIRE(decodedBinned != nullptr); + BOOST_CHECK_EQUAL(decodedBinned->directedProtoAxes().size(), 1u); + BOOST_CHECK_EQUAL( + decodedBinned->directedProtoAxes()[0u].getAxis().getBoundaryType(), + AxisBoundaryType::Bound); + BOOST_CHECK_EQUAL(decodedBinned->directedProtoAxes()[0u].getAxis().getNBins(), + 2u); +} + BOOST_AUTO_TEST_SUITE_END() } // namespace ActsTests diff --git a/Tests/UnitTests/Plugins/Json/MaterialMapJsonConverterTests.cpp b/Tests/UnitTests/Plugins/Json/MaterialMapJsonConverterTests.cpp index 3145595544e..31e71d53a2c 100644 --- a/Tests/UnitTests/Plugins/Json/MaterialMapJsonConverterTests.cpp +++ b/Tests/UnitTests/Plugins/Json/MaterialMapJsonConverterTests.cpp @@ -51,9 +51,12 @@ BOOST_AUTO_TEST_CASE(RoundtripFromFile) { auto materialMap = converter.jsonToMaterialMaps(refJson); nlohmann::json encodedJson = converter.materialMapsToJson(materialMap, &decorator); - - // verify identical encoded JSON values - BOOST_CHECK_EQUAL(refJson, encodedJson); + // The reference file uses the legacy schema. Verify we can read it and that + // the new schema is stable under another encode/decode cycle. + auto materialMapSecond = converter.jsonToMaterialMaps(encodedJson); + nlohmann::json encodedJsonSecond = + converter.materialMapsToJson(materialMapSecond, &decorator); + BOOST_CHECK_EQUAL(encodedJson, encodedJsonSecond); } BOOST_AUTO_TEST_SUITE_END() diff --git a/Tests/UnitTests/Plugins/Json/UtilitiesJsonConverterTests.cpp b/Tests/UnitTests/Plugins/Json/UtilitiesJsonConverterTests.cpp index 14e74f8e37e..c34b472bbb1 100644 --- a/Tests/UnitTests/Plugins/Json/UtilitiesJsonConverterTests.cpp +++ b/Tests/UnitTests/Plugins/Json/UtilitiesJsonConverterTests.cpp @@ -11,6 +11,7 @@ #include "Acts/Definitions/Algebra.hpp" #include "Acts/Utilities/BinUtility.hpp" #include "Acts/Utilities/BinningType.hpp" +#include "Acts/Utilities/ProtoAxis.hpp" #include "ActsPlugins/Json/UtilitiesJsonConverter.hpp" #include "ActsTests/CommonHelpers/FloatComparisons.hpp" @@ -138,6 +139,47 @@ BOOST_AUTO_TEST_CASE(Range1DRoundTrip) { CHECK_CLOSE_ABS(rIn.max(), 100., 10e-5); } +BOOST_AUTO_TEST_CASE(ProtoAxisRoundTripTests) { + ProtoAxis protoEq(AxisBoundaryType::Bound, -5., 5., 10u); + nlohmann::json jProtoEq = protoEq; + ProtoAxis protoEqRead(AxisBoundaryType::Bound, 1u); + from_json(jProtoEq, protoEqRead); + BOOST_CHECK_EQUAL(protoEqRead.getAxis(), protoEq.getAxis()); + BOOST_CHECK_EQUAL(protoEqRead.isAutorange(), protoEq.isAutorange()); + + ProtoAxis protoVar(AxisBoundaryType::Closed, + std::vector{-2., -1., 3.}); + nlohmann::json jProtoVar = protoVar; + ProtoAxis protoVarRead(AxisBoundaryType::Bound, 1u); + from_json(jProtoVar, protoVarRead); + BOOST_CHECK_EQUAL(protoVarRead.getAxis(), protoVar.getAxis()); + BOOST_CHECK_EQUAL(protoVarRead.isAutorange(), protoVar.isAutorange()); +} + +BOOST_AUTO_TEST_CASE(DirectedProtoAxisRoundTripTests) { + DirectedProtoAxis dProtoEq(AxisDirection::AxisPhi, AxisBoundaryType::Closed, + -std::numbers::pi, std::numbers::pi, 8u); + nlohmann::json jdProtoEq = dProtoEq; + DirectedProtoAxis dProtoEqRead(AxisDirection::AxisX, AxisBoundaryType::Bound, + 1u); + from_json(jdProtoEq, dProtoEqRead); + BOOST_CHECK_EQUAL(dProtoEqRead.getAxisDirection(), + dProtoEq.getAxisDirection()); + BOOST_CHECK_EQUAL(dProtoEqRead.getAxis(), dProtoEq.getAxis()); + BOOST_CHECK_EQUAL(dProtoEqRead.isAutorange(), dProtoEq.isAutorange()); + + DirectedProtoAxis dProtoVar(AxisDirection::AxisR, AxisBoundaryType::Bound, + std::vector{0., 1., 4., 9.}); + nlohmann::json jdProtoVar = dProtoVar; + DirectedProtoAxis dProtoVarRead(AxisDirection::AxisX, AxisBoundaryType::Bound, + 1u); + from_json(jdProtoVar, dProtoVarRead); + BOOST_CHECK_EQUAL(dProtoVarRead.getAxisDirection(), + dProtoVar.getAxisDirection()); + BOOST_CHECK_EQUAL(dProtoVarRead.getAxis(), dProtoVar.getAxis()); + BOOST_CHECK_EQUAL(dProtoVarRead.isAutorange(), dProtoVar.isAutorange()); +} + BOOST_AUTO_TEST_SUITE_END() } // namespace ActsTests diff --git a/Tests/UnitTests/Plugins/Root/RootMaterialMapIoTests.cpp b/Tests/UnitTests/Plugins/Root/RootMaterialMapIoTests.cpp index 0285d6b537c..c7d9790d668 100644 --- a/Tests/UnitTests/Plugins/Root/RootMaterialMapIoTests.cpp +++ b/Tests/UnitTests/Plugins/Root/RootMaterialMapIoTests.cpp @@ -14,10 +14,11 @@ #include "Acts/Material/Material.hpp" #include "Acts/Material/MaterialSlab.hpp" #include "Acts/Surfaces/PlaneSurface.hpp" -#include "Acts/Utilities/BinUtility.hpp" +#include "Acts/Utilities/ProtoAxis.hpp" #include "ActsPlugins/Root/RootMaterialMapIo.hpp" #include "ActsTests/CommonHelpers/FloatComparisons.hpp" +#include #include #include #include @@ -55,13 +56,15 @@ std::vector createBinnedSurfaceMaterial() { for (std::size_t i = 0; i < nMaterials; ++i) { // construct the material properties from arguments - BinUtility xyBinning(100, -1., 1., open, AxisDirection::AxisX); - xyBinning += BinUtility(50, -3., 3., open, AxisDirection::AxisY); + DirectedProtoAxis xAxis(AxisDirection::AxisX, AxisBoundaryType::Bound, -1., + 1., 100u); + DirectedProtoAxis yAxis(AxisDirection::AxisY, AxisBoundaryType::Bound, -3., + 3., 50u); std::vector> materialMatrix; - for (std::size_t j = 0; j < xyBinning.bins(1); ++j) { + for (std::size_t j = 0; j < yAxis.getAxis().getNBins(); ++j) { std::vector materialRow; - for (std::size_t k = 0; k < xyBinning.bins(0); ++k) { + for (std::size_t k = 0; k < xAxis.getAxis().getNBins(); ++k) { // Create a material slab with some arbitrary properties Material mat = Material::fromMolarDensity( i + j * 1. + k * 0.5, i + j * 2 + k * 0.5, i + j * 3. + k * 0.5, @@ -71,8 +74,8 @@ std::vector createBinnedSurfaceMaterial() { } materialMatrix.push_back(materialRow); } - auto binnedMaterial = - std::make_shared(xyBinning, materialMatrix); + auto binnedMaterial = std::make_shared( + std::array{xAxis, yAxis}, materialMatrix); auto geoID = GeometryIdentifier().withVolume(2).withSensitive(i + 1); binnedMaterials.push_back({geoID, binnedMaterial}); } @@ -172,10 +175,18 @@ BOOST_AUTO_TEST_CASE(RootMaterialMapIoBinnedReadWrite) { BOOST_REQUIRE(binnedMaterial != nullptr); // Check the binning - BOOST_CHECK_EQUAL(binnedMaterial->binUtility().bins(0), - binnedReferenceMaterial->binUtility().bins(0)); - BOOST_CHECK_EQUAL(binnedMaterial->binUtility().bins(1), - binnedReferenceMaterial->binUtility().bins(1)); + BOOST_CHECK_EQUAL( + binnedMaterial->directedProtoAxes().at(0).getAxis().getNBins(), + binnedReferenceMaterial->directedProtoAxes() + .at(0) + .getAxis() + .getNBins()); + BOOST_CHECK_EQUAL( + binnedMaterial->directedProtoAxes().at(1).getAxis().getNBins(), + binnedReferenceMaterial->directedProtoAxes() + .at(1) + .getAxis() + .getNBins()); // Compare the material matrix const auto& materialMatrix = binnedMaterial->fullMaterial(); @@ -237,10 +248,18 @@ BOOST_AUTO_TEST_CASE(RootMaterialMapIoBinnedReadWrite) { dynamic_cast(readMaterial.get()); BOOST_REQUIRE(binnedMaterial != nullptr); // Check the binning - BOOST_CHECK_EQUAL(binnedMaterial->binUtility().bins(0), - binnedReferenceMaterial->binUtility().bins(0)); - BOOST_CHECK_EQUAL(binnedMaterial->binUtility().bins(1), - binnedReferenceMaterial->binUtility().bins(1)); + BOOST_CHECK_EQUAL( + binnedMaterial->directedProtoAxes().at(0).getAxis().getNBins(), + binnedReferenceMaterial->directedProtoAxes() + .at(0) + .getAxis() + .getNBins()); + BOOST_CHECK_EQUAL( + binnedMaterial->directedProtoAxes().at(1).getAxis().getNBins(), + binnedReferenceMaterial->directedProtoAxes() + .at(1) + .getAxis() + .getNBins()); // Compare the material matrix const auto& materialMatrix = binnedMaterial->fullMaterial(); const auto& referenceMaterialMatrix =