4#ifndef ACTS_INPLACECLUSTERIZATION_H
5#define ACTS_INPLACECLUSTERIZATION_H
22template <
typename cell_t>
24 return std::tuple_size<decltype(cell_t::coordinates)>();
35template <
typename cell_t>
37 return a.coordinates[axis_i];
43template <
typename cell_t, std::
unsigned_
integral index_t>
49template <
typename cell_t>
61template <
typename coordinates_t, std::
size_t N, std::
unsigned_
integral index_t>
63 Cell(
const std::array<coordinates_t, N> &the_coordinates, index_t src_index)
66 std::array<coordinates_t, N>
73template <
typename cell_t>
76 unsigned int axis_i) {
81 } -> std::convertible_to<bool>;
86template <
typename container_t>
88 typename container_t::value_type) {
91 } -> std::convertible_to<const typename container_t::value_type &>;
92 { cont.empty() } -> std::convertible_to<bool>;
93 { cont.size() } -> std::convertible_to<std::size_t>;
94} && std::permutable<typename container_t::iterator>;
97template <
typename cell_collection_t>
105template <
typename coordinates_t>
107 bool connected =
true;
108 for (
const auto &a_coordinate_diff : coordinates_diff) {
109 connected &= a_coordinate_diff <= 1;
118template <
typename coordinates_t>
121 for (
const auto &a_coordinate_diff : coordinates_diff) {
122 connections += a_coordinate_diff;
124 return connections <= 1;
137template <CellWithLabel cell_t,
142 std::declval<cell_t>(), 0u))>;
146 const std::array<coordinate_t, NDim> &coordinates_diff) {
159 const std::array<coordinate_t, NDim> &coordinates_diff,
160 unsigned int sort_axis_i) {
161 assert(sort_axis_i < coordinates_diff.size());
162 return coordinates_diff[sort_axis_i] > 1;
168 CellCollection cell_container_t = std::span<Cell<int, 2, unsigned int> > >
175template <
typename coordinate_t>
177 if constexpr (std::is_signed_v<coordinate_t>) {
180 return static_cast<coordinate_t
>(std::abs(
a - b));
182 return static_cast<coordinate_t
>((
a > b ?
a - b : b -
a));
189template <
unsigned int SORT_AXIS, CellCollection cell_collection_t,
190 std::unsigned_integral index_t =
unsigned int,
191 typename connection_helper_t>
193 connection_helper_t &&connection_helper) {
194 using cell_t =
typename cell_collection_t::value_type;
196 static_assert(NDim > 0);
200 static_assert(std::numeric_limits<index_t>::max() >=
201 std::numeric_limits<label_t>::max());
205 for (index_t idx_a = 0; idx_a < cells.size(); ++idx_a) {
207 for (index_t idx_b = idx_a; idx_b-- > 0;) {
209 std::array<coordinate_t, NDim>
diff{};
210 for (
unsigned int axis_i = 0; axis_i < NDim; ++axis_i) {
216 if (connection_helper.isConnected(
diff)) {
231 if (min_label != max_label) {
234 for (index_t idx = idx_a; idx-- > max_label;) {
243 }
else if (connection_helper.canAbortSearch(
diff, SORT_AXIS)) {
253template <
unsigned int AXIS, CellCollection cell_collection_t,
254 std::size_t NDim = 2, std::unsigned_integral index_t =
unsigned int>
255 requires(NDim > 0 && AXIS < NDim)
257 using cell_t =
typename cell_collection_t::value_type;
258 std::sort(cells.begin(), cells.end(), [](
const cell_t &
a,
const cell_t &b) {
259 return traits::getCellCoordinate(a, AXIS) <
260 traits::getCellCoordinate(b, AXIS);
265template <CellCollection cell_collection_t>
267 using cell_t =
typename cell_collection_t::value_type;
270 [](
const cell_t &
a,
const cell_t &b) {
271 return traits::getLabel(a) < traits::getLabel(b);
287 unsigned int SORT_AXIS, std::unsigned_integral index_t =
unsigned int,
288 CellCollection cell_collection_t = std::span<Cell<int, 2, unsigned int> >,
289 typename connection_helper_t =
290 ConnectionHelper<Cell<int, 2, unsigned int> > >
292 connection_helper_t &&connection_helper =
295 assert(cells.size() <= std::numeric_limits<index_t>::max());
307template <CellCollection cell_collection_t,
308 std::unsigned_integral index_t =
unsigned int>
310 assert(cells.size() <= std::numeric_limits<index_t>::max());
311 std::size_t nlabels = cells.empty() ? 0 : 1;
312 for (index_t idx_a = 1; idx_a < cells.size(); ++idx_a) {
325template <CellCollection cell_collection_t,
typename func_t>
331 index_t idx_begin = 0;
333 for (; idx < cells.size(); ++idx) {
335 func(cells, idx_begin, idx);
339 if (idx_begin < idx) {
340 func(cells, idx_begin, idx);
353template <CellCollection cell_collection_t,
typename range_collection_t>
354void addCellRanges(
const cell_collection_t &cells, range_collection_t &ranges) {
356 cells, [&ranges]([[maybe_unused]]
const cell_collection_t &all_cells,
357 unsigned int idx_begin,
unsigned int idx_end) {
358 ranges.emplace_back(idx_begin, idx_end);
372template <
unsigned int AXIS, CellCollection cell_collection_t,
373 typename range_collection_t>
375 range_collection_t &ranges) {
377 unsigned int idx_begin,
378 unsigned int idx_end) {
380 std::span(all_cells.begin() + idx_begin, all_cells.begin() + idx_end);
381 using cell_t =
typename cell_collection_t::value_type;
382 std::ranges::sort(cluster_range, [](
const cell_t &
a,
const cell_t &b) {
386 ranges.emplace_back(idx_begin, idx_end);
void diff(const Jet &rJet1, const Jet &rJet2, std::map< std::string, double > varDiff)
Difference between jets - Non-Class function required by trigger.
concept of a cell container that can be clustered
concept of a call object that can be clustered.
base concept for the container that can be used for a cell collection
std::string label(const std::string &format, int i)
auto getLabel(const cell_t &a)
Get the label associated to the given cell.
void setLabel(cell_t &a, index_t label)
Set a label for a given cell the label type must fit numbers as high as the number of cells which are...
auto getCellCoordinate(const cell_t &a, unsigned int axis_i)
Get the coordinates of a cell.
constexpr auto getCellDimension()
void labelSortedCells(cell_collection_t &cells, connection_helper_t &&connection_helper)
Label cells which are in ascending order of the coordinate of the given axis.
auto absDifference(coordinate_t a, coordinate_t b)
compute the absolute difference of two coordinates
void sortCellsByCoordinate(cell_collection_t &cells)
Sort the cells in ascending order of the coordinate of the specified axis.
bool isConnectedCommonEdge(const coordinates_t &coordinates_diff)
test whether cells are connected considering common edges only.
auto defaultConnectionHelper(const cell_container_t &cells)
void groupCellsByLabel(cell_collection_t &cells)
Sort the cells in ascending order of the asscoiated label.
bool isConnectedCommonEdgeOrCorner(const coordinates_t &coordinates_diff)
test whether cells are connected considering common corners and edges.
void for_each_cluster(cell_collection_t &cells, func_t func)
call the given function for each cluster of a label sorted cell collection.
std::size_t countLabels(const cell_collection_t &cells)
determine the number of clusters.
void addCellRangesAndSort(cell_collection_t &cells, range_collection_t &ranges)
Sort the cells of each cluster by one coordinate and add cell ranges to the given range container.
void addCellRanges(const cell_collection_t &cells, range_collection_t &ranges)
Add element ranges for each cluster in the cell collection to the given range container.
void clusterize(cell_collection_t &cells, connection_helper_t &&connection_helper=ConnectionHelper< typename cell_collection_t::value_type, EConnectionType::CommonEdgeOrCorner >{})
Sort the cell collection in such a way that cells of a cluster are adjacent.
void sort(typename DataModel_detail::iterator< DVL > beg, typename DataModel_detail::iterator< DVL > end)
Specialization of sort for DataVector/List.
void stable_sort(DataModel_detail::iterator< DVL > beg, DataModel_detail::iterator< DVL > end)
Specialization of stable_sort for DataVector/List.
index_t label
a label which will be assigned by the clusterization
std::array< coordinates_t, N > coordinates
the coordinates of the cell on the regular grid
index_t srcIndex
the index to find the source cell
Cell(const std::array< coordinates_t, N > &the_coordinates, index_t src_index)
default connection helper which should work for arbitrary cells which fulfil the CellWithLabelConcept
static constexpr std::size_t NDim
std::remove_cvref_t< decltype(traits::getCellCoordinate( std::declval< cell_t >(), 0u))> coordinate_t
static bool canAbortSearch(const std::array< coordinate_t, NDim > &coordinates_diff, unsigned int sort_axis_i)
test whether the search for connections can be aborted.
static bool isConnected(const std::array< coordinate_t, NDim > &coordinates_diff)
test whether cells are connected considering common edges or common corners