LDMX Software
GeometryContainers.h
1// This file is part of the Acts project.
2//
3// Copyright (C) 2017-2020 CERN for the benefit of the Acts project
4//
5// This Source Code Form is subject to the terms of the Mozilla Public
6// License, v. 2.0. If a copy of the MPL was not distributed with this
7// file, You can obtain one at http://mozilla.org/MPL/2.0/.
8
9#pragma once
10
11#include <algorithm>
12#include <boost/container/flat_set.hpp>
13#include <cassert>
14#include <utility>
15
16#include "Acts/Geometry/GeometryIdentifier.hpp"
17#include "Tracking/Sim/GroupBy.h"
18#include "Tracking/Sim/Range.h"
19
20namespace acts_examples {
21namespace detail {
22
23// extract the geometry identifier from a variety of types
25 // explicit geometry identifier are just forwarded
26 constexpr Acts::GeometryIdentifier operator()(
27 Acts::GeometryIdentifier geometryId) const {
28 return geometryId;
29 }
30 // encoded geometry ids are converted back to geometry identifiers.
31 constexpr Acts::GeometryIdentifier operator()(
32 Acts::GeometryIdentifier::Value encoded) const {
33 return Acts::GeometryIdentifier(encoded);
34 }
35 // support elements in map-like structures.
36 template <typename T>
37 constexpr Acts::GeometryIdentifier operator()(
38 const std::pair<Acts::GeometryIdentifier, T>& mapItem) const {
39 return mapItem.first;
40 }
41 // support elements that implement `.geometryId()`.
42 template <typename T>
43 inline auto operator()(const T& thing) const
44 -> decltype(thing.geometryId(), Acts::GeometryIdentifier()) {
45 return thing.geometryId();
46 }
47 // support reference_wrappers around such types as well
48 template <typename T>
49 inline auto operator()(std::reference_wrapper<T> thing) const
50 -> decltype(thing.get().geometryId(), Acts::GeometryIdentifier()) {
51 return thing.get().geometryId();
52 }
53};
54
56 // indicate that comparisons between keys and full objects are allowed.
57 using is_transparent = void;
58 // compare two elements using the automatic key extraction.
59 template <typename Left, typename Right>
60 constexpr bool operator()(Left&& lhs, Right&& rhs) const {
61 return GeometryIdGetter()(lhs) < GeometryIdGetter()(rhs);
62 }
63};
64
65} // namespace detail
66
77template <typename T>
78using GeometryIdMultiset =
79 boost::container::flat_multiset<T, detail::CompareGeometryId>;
80
94template <typename T>
95using GeometryIdMultimap =
96 GeometryIdMultiset<std::pair<Acts::GeometryIdentifier, T>>;
97
99template <typename T>
101selectVolume(const GeometryIdMultiset<T>& container,
102 Acts::GeometryIdentifier::Value volume) {
103 auto cmp = Acts::GeometryIdentifier().withVolume(volume);
104 auto beg = std::lower_bound(container.begin(), container.end(), cmp,
106 // WARNING overflows to volume==0 if the input volume is the last one
107 cmp = Acts::GeometryIdentifier().withVolume(volume + 1u);
108 // optimize search by using the lower bound as start point. also handles
109 // volume overflows since the geo id would be located before the start of
110 // the upper edge search window.
111 auto end =
112 std::lower_bound(beg, container.end(), cmp, detail::CompareGeometryId{});
113 return makeRange(beg, end);
114}
115
117template <typename T>
118inline auto selectVolume(const GeometryIdMultiset<T>& container,
119 Acts::GeometryIdentifier id) {
120 return selectVolume(container, id.volume());
121}
122
124template <typename T>
126selectLayer(const GeometryIdMultiset<T>& container,
127 Acts::GeometryIdentifier::Value volume,
128 Acts::GeometryIdentifier::Value layer) {
129 auto cmp = Acts::GeometryIdentifier().withVolume(volume).withLayer(layer);
130 auto beg = std::lower_bound(container.begin(), container.end(), cmp,
131 detail::CompareGeometryId{});
132 // WARNING resets to layer==0 if the input layer is the last one
133 cmp = Acts::GeometryIdentifier().withVolume(volume).withLayer(layer + 1u);
134 // optimize search by using the lower bound as start point. also handles
135 // volume overflows since the geo id would be located before the start of
136 // the upper edge search window.
137 auto end =
138 std::lower_bound(beg, container.end(), cmp, detail::CompareGeometryId{});
139 return makeRange(beg, end);
140}
141
142// Select all elements within the given layer.
143template <typename T>
144inline auto selectLayer(const GeometryIdMultiset<T>& container,
145 Acts::GeometryIdentifier id) {
146 return selectLayer(container, id.volume(), id.layer());
147}
148
150template <typename T>
152selectModule(const GeometryIdMultiset<T>& container,
153 Acts::GeometryIdentifier geoId) {
154 // module is the lowest level and defines a single geometry id value
155 return makeRange(container.equal_range(geoId));
156}
157
159template <typename T>
160inline auto selectModule(const GeometryIdMultiset<T>& container,
161 Acts::GeometryIdentifier::Value volume,
162 Acts::GeometryIdentifier::Value layer,
163 Acts::GeometryIdentifier::Value module_) {
164 return selectModule(container, Acts::GeometryIdentifier()
165 .withVolume(volume)
166 .withLayer(layer)
167 .withSensitive(module_));
168}
169
186template <typename T>
188selectLowestNonZeroGeometryObject(const GeometryIdMultiset<T>& container,
189 Acts::GeometryIdentifier geoId) {
190 assert((geoId.boundary() == 0u) and "Boundary component must be zero");
191 assert((geoId.approach() == 0u) and "Approach component must be zero");
192
193 if (geoId.sensitive() != 0u) {
194 return selectModule(container, geoId);
195 } else if (geoId.layer() != 0u) {
196 return selectLayer(container, geoId);
197 } else if (geoId.volume() != 0u) {
198 return selectVolume(container, geoId);
199 } else {
200 return makeRange(container.begin(), container.end());
201 }
202}
203
206template <typename T>
208 detail::GeometryIdGetter>
209groupByModule(const GeometryIdMultiset<T>& container) {
210 return makeGroupBy(container, detail::GeometryIdGetter());
211}
212
217template <typename T>
219 using Container = GeometryIdMultiset<T>;
220 using Key = Acts::GeometryIdentifier;
221 using Value = typename GeometryIdMultiset<T>::value_type;
222 using Iterator = typename GeometryIdMultiset<T>::const_iterator;
223
224 // pointer to the container
225 const Container* container_ = nullptr;
226};
227
228} // namespace acts_examples
Proxy for iterating over groups of elements within a container.
Definition GroupBy.h:39
A wrapper around a pair of iterators to simplify range-based loops.
Definition Range.h:27
The accessor for the GeometryIdMultiset container.