Skip to content

Commit

Permalink
Merge branch 'main' into refactor-fuse-actor-and-aborter
Browse files Browse the repository at this point in the history
  • Loading branch information
andiwand authored Sep 11, 2024
2 parents a5c3a59 + ae0c21d commit b030ece
Show file tree
Hide file tree
Showing 39 changed files with 259 additions and 292 deletions.
7 changes: 4 additions & 3 deletions Core/include/Acts/Detector/detail/IndexedGridFiller.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
#include "Acts/Utilities/Delegate.hpp"
#include "Acts/Utilities/Enumerate.hpp"
#include "Acts/Utilities/GridAccessHelpers.hpp"
#include "Acts/Utilities/Helpers.hpp"
#include "Acts/Utilities/IAxis.hpp"
#include "Acts/Utilities/Logger.hpp"

Expand Down Expand Up @@ -193,7 +194,7 @@ struct IndexedGridFiller {
// Loop over the surfaces to be filled
for (auto [io, o] : enumerate(iObjects)) {
// Exclude indices that should be handled differently
if (std::find(aToAll.begin(), aToAll.end(), io) != aToAll.end()) {
if (rangeContainsValue(aToAll, io)) {
continue;
}
// Get the reference positions
Expand All @@ -216,7 +217,7 @@ struct IndexedGridFiller {
// Now fill the surface indices
for (const auto& li : lIndices) {
auto& bContent = iGrid.grid.atLocalBins(li);
if (std::find(bContent.begin(), bContent.end(), io) == bContent.end()) {
if (!rangeContainsValue(bContent, io)) {
bContent.push_back(io);
}
}
Expand All @@ -238,7 +239,7 @@ struct IndexedGridFiller {
for (std::size_t gi = 0; gi < iGrid.grid.size(true); ++gi) {
auto& bContent = iGrid.grid.at(gi);
for (const auto& io : idcs) {
if (std::find(bContent.begin(), bContent.end(), io) == bContent.end()) {
if (!rangeContainsValue(bContent, io)) {
bContent.push_back(io);
}
}
Expand Down
4 changes: 2 additions & 2 deletions Core/include/Acts/EventData/MultiTrajectoryHelpers.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
#include "Acts/Geometry/Layer.hpp"
#include "Acts/Geometry/TrackingVolume.hpp"
#include "Acts/Surfaces/Surface.hpp"
#include "Acts/Utilities/Helpers.hpp"

#include <functional>
#include <unordered_map>
Expand Down Expand Up @@ -102,8 +103,7 @@ VolumeTrajectoryStateContainer trajectoryState(
const auto& volume = geoID.volume();
const auto& layer = geoID.layer();
// Check if the track info for this sub-detector is requested
auto it = std::find(volumeIds.begin(), volumeIds.end(), volume);
if (it == volumeIds.end()) {
if (!rangeContainsValue(volumeIds, volume)) {
return true;
}
// The trajectory state for this volume
Expand Down
70 changes: 38 additions & 32 deletions Core/include/Acts/Geometry/GeometryHierarchyMap.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -64,13 +64,13 @@ class GeometryHierarchyMap {
/// Combined geometry identifier and value element. Only used for input.
using InputElement = typename std::pair<GeometryIdentifier, value_t>;
using Iterator = typename std::vector<value_t>::const_iterator;
using Size = typename std::vector<value_t>::size_type;
using Value = value_t;

/// Construct the container from the given elements.
///
/// @param elements input elements (must be unique with respect to identifier)
GeometryHierarchyMap(std::vector<InputElement> elements);

/// Construct the container from an initializer list.
///
/// @param elements input initializer list
Expand All @@ -86,21 +86,25 @@ class GeometryHierarchyMap {

/// Return an iterator pointing to the beginning of the stored values.
Iterator begin() const { return m_values.begin(); }

/// Return an iterator pointing to the end of the stored values.
Iterator end() const { return m_values.end(); }

/// Check if any elements are stored.
bool empty() const { return m_values.empty(); }

/// Return the number of stored elements.
Size size() const { return m_values.size(); }
std::size_t size() const { return m_values.size(); }

/// Access the geometry identifier for the i-th element with bounds check.
///
/// @throws std::out_of_range for invalid indices
GeometryIdentifier idAt(Size index) const { return m_ids.at(index); }
GeometryIdentifier idAt(std::size_t index) const { return m_ids.at(index); }

/// Access the value of the i-th element in the container with bounds check.
///
/// @throws std::out_of_range for invalid indices
const Value& valueAt(Size index) const { return m_values.at(index); }
const Value& valueAt(std::size_t index) const { return m_values.at(index); }

/// Find the most specific value for a given geometry identifier.
///
Expand All @@ -111,7 +115,7 @@ class GeometryHierarchyMap {
/// @param id geometry identifier for which information is requested
/// @retval iterator to an existing value
/// @retval `.end()` iterator if no matching element exists
Iterator find(GeometryIdentifier id) const;
Iterator find(const GeometryIdentifier& id) const;

private:
// NOTE this class assumes that it knows the ordering of the levels within
Expand Down Expand Up @@ -171,34 +175,35 @@ class GeometryHierarchyMap {
// no valid levels; all bits are zero.
return Identifier{0u};
}

/// Construct a mask where only the highest level is set.
static constexpr Identifier makeHighestLevelMask() {
return makeLeadingLevelsMask(GeometryIdentifier(0u).setVolume(1u));
}

/// Compare the two identifiers only within the masked bits.
static constexpr bool equalWithinMask(Identifier lhs, Identifier rhs,
Identifier mask) {
return (lhs & mask) == (rhs & mask);
}

/// Ensure identifier ordering and uniqueness.
template <typename iterator_t>
static void sortAndCheckDuplicates(iterator_t beg, iterator_t end);
static void sortAndCheckDuplicates(std::vector<InputElement>& elements);

/// Fill the container from the input elements.
///
/// This assumes that the elements are ordered and unique with respect to
/// their identifiers.
template <typename iterator_t>
void fill(iterator_t beg, iterator_t end);
void fill(const std::vector<InputElement>& elements);
};

// implementations

template <typename value_t>
inline GeometryHierarchyMap<value_t>::GeometryHierarchyMap(
std::vector<InputElement> elements) {
sortAndCheckDuplicates(elements.begin(), elements.end());
fill(elements.begin(), elements.end());
sortAndCheckDuplicates(elements);
fill(elements);
}

template <typename value_t>
Expand All @@ -208,43 +213,44 @@ inline GeometryHierarchyMap<value_t>::GeometryHierarchyMap(
std::vector<InputElement>(elements.begin(), elements.end())) {}

template <typename value_t>
template <typename iterator_t>
inline void GeometryHierarchyMap<value_t>::sortAndCheckDuplicates(
iterator_t beg, iterator_t end) {
std::vector<InputElement>& elements) {
// ensure elements are sorted by identifier
std::sort(beg, end, [=](const auto& lhs, const auto& rhs) {
std::ranges::sort(elements, [=](const auto& lhs, const auto& rhs) {
return lhs.first < rhs.first;
});
// check that all elements have unique identifier
auto dup = std::adjacent_find(beg, end, [](const auto& lhs, const auto& rhs) {
return lhs.first == rhs.first;
});
if (dup != end) {

// Check that all elements have unique identifier
auto dup = std::ranges::adjacent_find(
elements,
[](const auto& lhs, const auto& rhs) { return lhs.first == rhs.first; });

if (dup != elements.end()) {
throw std::invalid_argument("Input elements contain duplicates");
}
}

template <typename value_t>
template <typename iterator_t>
inline void GeometryHierarchyMap<value_t>::fill(iterator_t beg,
iterator_t end) {
const auto n = std::distance(beg, end);
inline void GeometryHierarchyMap<value_t>::fill(
const std::vector<InputElement>& elements) {
m_ids.clear();
m_ids.reserve(n);
m_masks.clear();
m_masks.reserve(n);
m_values.clear();
m_values.reserve(n);
for (; beg != end; ++beg) {
m_ids.push_back(beg->first.value());
m_masks.push_back(makeLeadingLevelsMask(beg->first.value()));
m_values.push_back(std::move(beg->second));

m_ids.reserve(elements.size());
m_masks.reserve(elements.size());
m_values.reserve(elements.size());

for (const auto& element : elements) {
m_ids.push_back(element.first.value());
m_masks.push_back(makeLeadingLevelsMask(element.first.value()));
m_values.push_back(std::move(element.second));
}
}

template <typename value_t>
inline auto GeometryHierarchyMap<value_t>::find(GeometryIdentifier id) const
-> Iterator {
inline auto GeometryHierarchyMap<value_t>::find(
const GeometryIdentifier& id) const -> Iterator {
assert((m_ids.size() == m_values.size()) &&
"Inconsistent container state: #ids != # values");
assert((m_masks.size() == m_values.size()) &&
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ namespace Acts {
/// ioninisation, bremsstrahlung, pair production and photonuclear interaction
/// in the propagation and the jacobian. These effects will only occur if the
/// propagation is in a TrackingVolume with attached material.
struct EigenStepperDenseEnvironmentExtension {
struct EigenStepperDenseExtension {
using Scalar = ActsScalar;
/// @brief Vector3 replacement for the custom scalar type
using ThisVector3 = Eigen::Matrix<Scalar, 3, 1>;
Expand Down
5 changes: 3 additions & 2 deletions Core/include/Acts/TrackFitting/GaussianSumFitter.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
#include "Acts/Surfaces/BoundaryTolerance.hpp"
#include "Acts/TrackFitting/GsfOptions.hpp"
#include "Acts/TrackFitting/detail/GsfActor.hpp"
#include "Acts/Utilities/Helpers.hpp"
#include "Acts/Utilities/Logger.hpp"
#include "Acts/Utilities/TrackHelpers.hpp"

Expand Down Expand Up @@ -425,8 +426,8 @@ struct GaussianSumFitter {

for (auto state : fwdGsfResult.fittedStates->reverseTrackStateRange(
fwdGsfResult.currentTip)) {
const bool found = std::find(foundBwd.begin(), foundBwd.end(),
&state.referenceSurface()) != foundBwd.end();
const bool found =
rangeContainsValue(foundBwd, &state.referenceSurface());
if (!found && state.typeFlags().test(MeasurementFlag)) {
state.typeFlags().set(OutlierFlag);
state.typeFlags().reset(MeasurementFlag);
Expand Down
5 changes: 2 additions & 3 deletions Core/include/Acts/TrackFitting/detail/GsfActor.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
#include "Acts/TrackFitting/detail/GsfComponentMerging.hpp"
#include "Acts/TrackFitting/detail/GsfUtils.hpp"
#include "Acts/TrackFitting/detail/KalmanUpdateHelpers.hpp"
#include "Acts/Utilities/Helpers.hpp"
#include "Acts/Utilities/Zip.hpp"

#include <ios>
Expand Down Expand Up @@ -195,9 +196,7 @@ struct GsfActor {

// Early return if we already were on this surface TODO why is this
// necessary
const bool visited =
std::find(result.visitedSurfaces.begin(), result.visitedSurfaces.end(),
&surface) != result.visitedSurfaces.end();
const bool visited = rangeContainsValue(result.visitedSurfaces, &surface);

if (visited) {
ACTS_VERBOSE("Already visited surface, return");
Expand Down
7 changes: 3 additions & 4 deletions Core/include/Acts/Utilities/BinnedArrayXD.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
#pragma once
#include "Acts/Utilities/BinUtility.hpp"
#include "Acts/Utilities/BinnedArray.hpp"
#include "Acts/Utilities/Helpers.hpp"

#include <array>
#include <iostream>
Expand Down Expand Up @@ -74,8 +75,7 @@ class BinnedArrayXD : public BinnedArray<T> {
/// fill the data
m_objectGrid[bins[2]][bins[1]][bins[0]] = tap.first;
/// fill the unique m_arrayObjects
if (std::find(m_arrayObjects.begin(), m_arrayObjects.end(),
tap.first) == m_arrayObjects.end()) {
if (!rangeContainsValue(m_arrayObjects, tap.first)) {
m_arrayObjects.push_back(tap.first);
}
}
Expand Down Expand Up @@ -103,8 +103,7 @@ class BinnedArrayXD : public BinnedArray<T> {
for (auto& o0 : o1) {
if (o0) {
/// fill the unique m_arrayObjects
if (std::find(m_arrayObjects.begin(), m_arrayObjects.end(), o0) ==
m_arrayObjects.end()) {
if (!rangeContainsValue(m_arrayObjects, o0)) {
m_arrayObjects.push_back(o0);
}
}
Expand Down
70 changes: 38 additions & 32 deletions Core/include/Acts/Utilities/Helpers.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#include "Acts/Definitions/Algebra.hpp"

#include <algorithm>
#include <array>
#include <iostream>
#include <limits>
#include <memory>
Expand Down Expand Up @@ -71,22 +72,24 @@ std::vector<const T*> unpack_shared_const_vector(
return rawPtrs;
}

/// This can be abandoned with C++20 to use the std::to_array method
/// @brief Converts a vector to a fixed-size array with truncating or padding.
///
/// @note only the first kDIM elements will obviously be filled, if the
/// vector tends to be longer, it is truncated
/// This function copies elements from the input vector into a fixed-size array.
/// If the vector contains more than `kDIM` elements, the array is truncated to
/// fit. If the vector contains fewer elements than `kDIM`, the remaining array
/// elements are value-initialized (default-initialized, i.e., filled with zero
/// or default values).
///
/// @param vecvals the vector of bound values to be converted
/// @return an array with the filled values
template <std::size_t kDIM, typename value_type>
std::array<value_type, kDIM> to_array(const std::vector<value_type>& vecvals) {
std::array<value_type, kDIM> rarray = {};
for (const auto [iv, v] : enumerate(vecvals)) {
if (iv < kDIM) {
rarray[iv] = v;
}
}
return rarray;
/// @tparam kDIM The size of the resulting array.
/// @tparam value_t The type of elements in the vector and the array.
/// @param vecvals The input vector to be converted to an array.
///
/// @return An array containing the first `kDIM` elements of the vector.
template <std::size_t kDIM, typename value_t>
std::array<value_t, kDIM> toArray(const std::vector<value_t>& vecvals) {
std::array<value_t, kDIM> arr = {};
std::copy_n(vecvals.begin(), std::min(vecvals.size(), kDIM), arr.begin());
return arr;
}

/// @brief Dispatch a call based on a runtime value on a function taking the
Expand Down Expand Up @@ -164,21 +167,7 @@ T clampValue(U value) {
static_cast<U>(std::numeric_limits<T>::max()));
}

/// Return min/max from a (optionally) sorted series, obsolete with C++20
/// (ranges)
///
/// @tparam T a numeric series
///
/// @param tseries is the number series
///
/// @return [ min, max ] in an array of length 2
template <typename T>
std::array<typename T::value_type, 2u> min_max(const T& tseries) {
return {*std::min_element(tseries.begin(), tseries.end()),
*std::max_element(tseries.begin(), tseries.end())};
}

/// Return range and medium of a sorted numeric series
/// Return range and medium of an unsorted numeric series
///
/// @tparam T a numeric series
///
Expand All @@ -187,9 +176,9 @@ std::array<typename T::value_type, 2u> min_max(const T& tseries) {
/// @return [ range, medium ] in an tuple
template <typename T>
std::tuple<typename T::value_type, ActsScalar> range_medium(const T& tseries) {
auto [min, max] = min_max(tseries);
typename T::value_type range = (max - min);
ActsScalar medium = static_cast<ActsScalar>((max + min) * 0.5);
auto [minIt, maxIt] = std::ranges::minmax_element(tseries);
typename T::value_type range = (*maxIt - *minIt);
ActsScalar medium = static_cast<ActsScalar>((*maxIt + *minIt) * 0.5);
return std::tie(range, medium);
}

Expand All @@ -198,4 +187,21 @@ constexpr std::underlying_type_t<enum_t> toUnderlying(enum_t value) {
return static_cast<std::underlying_type_t<enum_t>>(value);
}

/// This can be replaced with C++23 to use the std::ranges::contains method
///
/// This function searches through the given range for a specified value
/// and returns `true` if the value is found, or `false` otherwise.
///
/// @tparam R The type of the range (e.g., vector, list, array).
/// @tparam T The type of the value to search for within the range.
///
/// @param range The range to search within. This can be any range-compatible container.
/// @param value The value to search for in the range.
///
/// @return `true` if the value is found within the range, `false` otherwise.
template <typename R, typename T>
bool rangeContainsValue(const R& range, const T& value) {
return std::ranges::find(range, value) != std::ranges::end(range);
}

} // namespace Acts
Loading

0 comments on commit b030ece

Please sign in to comment.