Skip to content

Commit

Permalink
feat!: Generic grid bin finder (acts-project#2838)
Browse files Browse the repository at this point in the history
This will complete the adaptation of the grid to an N-dimentional case. The user is now able to iterate on any axis as they like without the need to rotate their geometry. 

Next step is to see how the seed finding routine can be adapted to be more general

This PR is also a bug-fix since in the past we had:
```cpp
template <typename external_spacepoint_t>
boost::container::small_vector<std::size_t, 9>
Acts::BinFinder<external_spacepoint_t>::findBins(
    std::size_t phiBin, std::size_t zBin,
    const Acts::SpacePointGrid<external_spacepoint_t>* binnedSP) const {
  // if zBinNeighbors is not defined, get the indices using
  // neighborHoodIndices
  if (m_zBinNeighbors->empty()) {
    return binnedSP->neighborHoodIndices({phiBin, zBin}).collect();
  }
  // if the zBinNeighbors is defined, get the indices from there
  std::array<std::pair<int, int>, 2> sizePerAxis;
  sizePerAxis.at(0) = std::make_pair(-m_numPhiNeighbors, m_numPhiNeighbors);
  sizePerAxis.at(1) = (*m_zBinNeighbors)[zBin - 1];
  return binnedSP->neighborHoodIndices({phiBin, zBin}, sizePerAxis).collect();
}
```

In the case `m_zBinNeighbors` is empty, the code is instructed to search neighbours in the range `{-1, 1}` FOR EVERY AXIS (this is what `binnedSP->neighborHoodIndices({phiBin, zBin}).collect();` does), thus overwriting the value set by the user for `m_numPhiNeighbors`. 

Now, the axes are treated independently

This requires: acts-project#2835
  • Loading branch information
CarloVarni authored and LaraCalic committed Feb 10, 2024
1 parent af1b730 commit 354d0f6
Show file tree
Hide file tree
Showing 16 changed files with 685 additions and 161 deletions.
51 changes: 0 additions & 51 deletions Core/include/Acts/Seeding/BinFinder.hpp

This file was deleted.

29 changes: 0 additions & 29 deletions Core/include/Acts/Seeding/BinFinder.ipp

This file was deleted.

34 changes: 15 additions & 19 deletions Core/include/Acts/Seeding/BinnedSPGroup.hpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// This file is part of the Acts project.
//
// Copyright (C) 2023 CERN for the benefit of the Acts project
// Copyright (C) 2024 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
Expand All @@ -9,11 +9,11 @@
#pragma once

#include "Acts/Geometry/Extent.hpp"
#include "Acts/Seeding/BinFinder.hpp"
#include "Acts/Seeding/InternalSeed.hpp"
#include "Acts/Seeding/Seed.hpp"
#include "Acts/Seeding/SeedFinderConfig.hpp"
#include "Acts/Seeding/SpacePointGrid.hpp"
#include "Acts/Utilities/GridBinFinder.hpp"
#include "Acts/Utilities/GridIterator.hpp"
#include "Acts/Utilities/Holders.hpp"

Expand All @@ -27,7 +27,7 @@ template <typename external_spacepoint_t>
class BinnedSPGroup;

/// @c BinnedSPGroupIterator Allows to iterate over all groups of bins
/// a provided BinFinder can generate for each bin of a provided SPGrid
/// a provided GridBinFinder can generate for each bin of a provided SPGrid

/// SpacePointGrid is a very specific structure.
/// We know it is 2D and what it contains
Expand Down Expand Up @@ -79,7 +79,7 @@ class BinnedSPGroupIterator {
};

/// @c BinnedSPGroup Provides access to begin and end BinnedSPGroupIterator
/// for given BinFinders and SpacePointGrid.
/// for given GridBinFinders and SpacePointGrid.
/// Fulfills the range_expression interface.
template <typename external_spacepoint_t>
class BinnedSPGroup {
Expand All @@ -93,16 +93,14 @@ class BinnedSPGroup {
BinnedSPGroup() = delete;

template <typename spacepoint_iterator_t, typename callable_t>
BinnedSPGroup(
spacepoint_iterator_t spBegin, spacepoint_iterator_t spEnd,
callable_t&& toGlobal,
std::shared_ptr<const Acts::BinFinder<external_spacepoint_t>>
botBinFinder,
std::shared_ptr<const Acts::BinFinder<external_spacepoint_t>> tBinFinder,
std::unique_ptr<SpacePointGrid<external_spacepoint_t>> grid,
Acts::Extent& rRangeSPExtent,
const SeedFinderConfig<external_spacepoint_t>& _config,
const SeedFinderOptions& _options);
BinnedSPGroup(spacepoint_iterator_t spBegin, spacepoint_iterator_t spEnd,
callable_t&& toGlobal,
std::shared_ptr<const Acts::GridBinFinder<2ul>> botBinFinder,
std::shared_ptr<const Acts::GridBinFinder<2ul>> tBinFinder,
std::unique_ptr<SpacePointGrid<external_spacepoint_t>> grid,
Acts::Extent& rRangeSPExtent,
const SeedFinderConfig<external_spacepoint_t>& _config,
const SeedFinderOptions& _options);

BinnedSPGroup(const BinnedSPGroup&) = delete;
BinnedSPGroup& operator=(const BinnedSPGroup&) = delete;
Expand All @@ -125,12 +123,10 @@ class BinnedSPGroup {
// grid with ownership of all InternalSpacePoint
std::unique_ptr<Acts::SpacePointGrid<external_spacepoint_t>> m_grid{nullptr};

// BinFinder must return std::vector<Acts::Seeding::Bin> with content of
// GridBinFinder must return std::vector<Acts::Seeding::Bin> with content of
// each bin sorted in r (ascending)
std::shared_ptr<const BinFinder<external_spacepoint_t>> m_topBinFinder{
nullptr};
std::shared_ptr<const BinFinder<external_spacepoint_t>> m_bottomBinFinder{
nullptr};
std::shared_ptr<const Acts::GridBinFinder<2ul>> m_topBinFinder{nullptr};
std::shared_ptr<const Acts::GridBinFinder<2ul>> m_bottomBinFinder{nullptr};

// Order of z bins to loop over when searching for SPs
std::array<std::vector<std::size_t>, 2> m_bins{};
Expand Down
30 changes: 13 additions & 17 deletions Core/include/Acts/Seeding/BinnedSPGroup.ipp
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// This file is part of the Acts project.
//
// Copyright (C) 2023 CERN for the benefit of the Acts project
// Copyright (C) 2024 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
Expand Down Expand Up @@ -55,13 +55,10 @@ Acts::BinnedSPGroupIterator<external_spacepoint_t>::operator*() const {
m_group->m_grid->globalBinFromLocalBins(localPosition);

boost::container::small_vector<std::size_t, 9> bottoms =
m_group->m_bottomBinFinder->findBins(localPosition[INDEX::PHI],
localPosition[INDEX::Z],
m_group->m_grid.get());
m_group->m_bottomBinFinder->findBins(localPosition,
*m_group->m_grid.get());
boost::container::small_vector<std::size_t, 9> tops =
m_group->m_topBinFinder->findBins(localPosition[INDEX::PHI],
localPosition[INDEX::Z],
m_group->m_grid.get());
m_group->m_topBinFinder->findBins(localPosition, *m_group->m_grid.get());

// GCC12+ in Release throws an overread warning here due to the move.
// This is from inside boost code, so best we can do is to suppress it.
Expand Down Expand Up @@ -95,12 +92,15 @@ template <typename spacepoint_iterator_t, typename callable_t>
Acts::BinnedSPGroup<external_spacepoint_t>::BinnedSPGroup(
spacepoint_iterator_t spBegin, spacepoint_iterator_t spEnd,
callable_t&& toGlobal,
std::shared_ptr<const Acts::BinFinder<external_spacepoint_t>> botBinFinder,
std::shared_ptr<const Acts::BinFinder<external_spacepoint_t>> tBinFinder,
std::shared_ptr<const Acts::GridBinFinder<2ul>> botBinFinder,
std::shared_ptr<const Acts::GridBinFinder<2ul>> tBinFinder,
std::unique_ptr<SpacePointGrid<external_spacepoint_t>> grid,
Acts::Extent& rRangeSPExtent,
const SeedFinderConfig<external_spacepoint_t>& config,
const SeedFinderOptions& options) {
const SeedFinderOptions& options)
: m_grid(std::move(grid)),
m_topBinFinder(std::move(tBinFinder)),
m_bottomBinFinder(std::move(botBinFinder)) {
if (!config.isInInternalUnits) {
throw std::runtime_error(
"SeedFinderConfig not in ACTS internal units in BinnedSPGroup");
Expand Down Expand Up @@ -171,20 +171,20 @@ Acts::BinnedSPGroup<external_spacepoint_t>::BinnedSPGroup(
// fill rbins into grid
Acts::Vector2 spLocation(isp->phi(), isp->z());
std::vector<std::unique_ptr<InternalSpacePoint<external_spacepoint_t>>>&
rbin = grid->atPosition(spLocation);
rbin = m_grid->atPosition(spLocation);
rbin.push_back(std::move(isp));

// keep track of the bins we modify so that we can later sort the SPs in
// those bins only
if (rbin.size() > 1) {
rBinsIndex.insert(grid->globalBinFromPosition(spLocation));
rBinsIndex.insert(m_grid->globalBinFromPosition(spLocation));
}
}

// sort SPs in R for each filled (z, phi) bin
for (auto& binIndex : rBinsIndex) {
std::vector<std::unique_ptr<InternalSpacePoint<external_spacepoint_t>>>&
rbin = grid->atPosition(binIndex);
rbin = m_grid->atPosition(binIndex);
std::sort(
rbin.begin(), rbin.end(),
[](std::unique_ptr<InternalSpacePoint<external_spacepoint_t>>& a,
Expand All @@ -193,10 +193,6 @@ Acts::BinnedSPGroup<external_spacepoint_t>::BinnedSPGroup(
});
}

m_grid = std::move(grid);
m_bottomBinFinder = botBinFinder;
m_topBinFinder = tBinFinder;

// phi axis
m_bins[INDEX::PHI].resize(m_grid->numLocalBins()[0]);
std::iota(m_bins[INDEX::PHI].begin(), m_bins[INDEX::PHI].end(), 1ul);
Expand Down
114 changes: 114 additions & 0 deletions Core/include/Acts/Utilities/GridBinFinder.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
// This file is part of the Acts project.
//
// Copyright (C) 2024 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 http://mozilla.org/MPL/2.0/.

#pragma once

#include "Acts/Seeding/SpacePointGrid.hpp"
#include "Acts/Utilities/Holders.hpp"
#include "Acts/Utilities/detail/grid_helper.hpp"

#include <variant>
#include <vector>

#include <boost/container/small_vector.hpp>

namespace Acts {

/// @class BinFinder
/// @tparam DIM Dimension of the Grid on which the GridBinFinder will be used
///
/// The BinFinder is used by the ISPGroupSelector. It can be
/// used to find both bins that could be bottom bins as well as bins that could
/// be top bins, which are assumed to be the same bins. Does not take
/// interaction region into account to limit z-bins.
template <std::size_t DIM>
class GridBinFinder {
public:
/// @brief Constructor
/// @tparam args ... Input parameters provided by the user
///
/// @param [in] vals The input parameters that define how many neighbours we need to find
///
/// @pre The provided paramers must be of time 'int' or 'std::vector<std::pair<int, int>>'
/// no other type is allowed. The order of these parameters must correspond to
/// the same ordering of the axes in the grid
template <typename... args>
GridBinFinder(args&&... vals);

/// @brief Retrieve the neighbouring bins given a local position in the grid
///
/// Return all bins that could contain space points that can be used with the
/// space points in the bin with the provided indices to create seeds.
///
/// @tparam stored_t The type of elements stored in the Grid
/// @tpatam Axes ... The type of the axes of the grid
///
/// @param [in] locPosition The N-dimentional local position in the grid
/// @param [in] grid The grid
/// @output The list of neighbouring bins
///
/// @pre The provided local position must be a valid local bins configuration in the grid
template <typename stored_t, class... Axes>
boost::container::small_vector<std::size_t, Acts::detail::ipow(3, DIM)>
findBins(const std::array<std::size_t, DIM>& locPosition,
const Acts::Grid<stored_t, Axes...>& grid) const;

private:
/// @brief Store the values provided by the user for each axis in the grid
/// @tparam first_value_t Type of the first value
/// @tparam vals ... values of the remaining values
///
/// @param [in] fv The first value in the list
/// @param [in] others The remaining values in the list
///
/// @pre both first_value_t and vals ... can be only int or std::vector<std::pair<int, int>>
/// In the second case, the number of entries of the vector of pairs MUST be
/// equal to the number of bins in that specific axis. Empty vectors are also
/// allowed but in this case the value will be replaced with a 1 (integer),
/// thus instructing the code to look for neighbours in the range {-1 ,1}
template <typename first_value_t, typename... vals>
void storeValue(first_value_t&& fv, vals&&... others);

/// @brief Get the instructions for retrieving the neighbouring bins given a local position
///
/// @param [in] locPosition The requested local position
/// @return the instructions for retrieving the neighbouring bins for this local position
///
/// @pre The local position must be a valid local bins configuration for the grid
std::array<std::pair<int, int>, DIM> getSizePerAxis(
const std::array<std::size_t, DIM>& locPosition) const;

/// @brief Check the GridBinFinder configuration is compatible with the grid
/// by checking the values of m_values against the axes of the grid
/// This function is called only in debug mode
///
/// @tparam stored_t The type of elements stored in the Grid
/// @tpatam Axes ... The type of the axes of the grid
///
/// @param [in] grid The Grid
/// @return If the GridBinFinder is compatible with the grid
template <typename stored_t, class... Axes>
bool isGridCompatible(const Acts::Grid<stored_t, Axes...>& grid) const;

private:
using stored_values_t = std::variant<int, std::vector<std::pair<int, int>>>;
/// @brief the instructions for retrieving the nieghbouring bins for each given axis in the grid
/// These values are provided by the user and can be either ints or a vector
/// of pair of ints. In the first case, the neighbours will be +/- bins from
/// the given local bin In the second case, the user defines how many bins in
/// both directions should be provided
///
/// @pre The list of entries of the vector of pairs MUST be equal to the number of bins in that specific
/// axis. Empty vectors are also allowed but in this case the value will be
/// replaced with a 1 (integer), thus instructing the code to look for
/// neighbours in the range {-1 ,1}
std::array<stored_values_t, DIM> m_values{};
};

} // namespace Acts
#include "Acts/Utilities/GridBinFinder.ipp"
Loading

0 comments on commit 354d0f6

Please sign in to comment.