OpDetVisibilityData.h
Go to the documentation of this file.
1 /**
2  * @file larsim/PhotonPropagation/LibraryMappingTools/OpDetVisibilityData.h
3  * @brief Data container for use with photon visibility libraries.
4  * @author Gianluca Petrillo (petrillo@slac.stanford.edu)
5  * @date March 29, 2019
6  *
7  * This is a header-only library.
8  *
9  */
10 
11 #ifndef LARSIM_PHOTONPROPAGATION_LIBRARYMAPPINGTOOLS_OPDETVISIBILITYDATA_H
12 #define LARSIM_PHOTONPROPAGATION_LIBRARYMAPPINGTOOLS_OPDETVISIBILITYDATA_H
13 
14 // LArSoft libraries
16 
17 // C++ standard libraries
18 #include <iterator> // std::size()
19 #include <utility> // std::forward()
20 #include <type_traits> // std::enable_if_t<>
21 
22 
23 namespace phot {
24 
25  /**
26  * @brief Trait for determining the validity of library data in a container.
27  * @tparam Cont type of container being tested
28  * @tparam Enable dummy type for `std::enable_if_t` hooks
29  *
30  * This class is expected to be specialized to provide specific behavior for
31  * custom classes.
32  * The required interface consists of the single static method:
33  * * `static bool isValid(Cont const&)` returning whether `cont` is valid
34  *
35  *
36  * For example:
37  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
38  * template <typename T, std::size_t N>
39  * struct MyArray;
40  *
41  * template <typename T, std::size_t N>
42  * struct LibraryDataValidatorStruct<MyArray<T, N>, void> {
43  * static bool isValid(Cont const&) { return N > 0U; }
44  * };
45  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
46  * or
47  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
48  * template <typename T>
49  * struct MyVector;
50  *
51  * template <typename T>
52  * struct LibraryDataValidatorStruct
53  * <T, std::enable_if_t<util::is_instance_of<MyVector, T>>>
54  * {
55  * static bool isValid(Cont const& cont) { return !cont.isInvalid(); }
56  * };
57  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
58  */
59  template <typename Cont, typename Enable = void>
61 
62 
63  /**
64  * @brief Returns the validity of content of library data in the container.
65  * @tparam Cont type of the container being tested
66  * @param cont a reference to the container being tested
67  * @return whether the content of library data in `cont` is valid.
68  *
69  * Customization of this behaviour should be through specialization of
70  * `phot::LibraryDataValidatorStruct`.
71  *
72  */
73  template <typename Cont>
74  bool isValidLibraryData(Cont&& cont);
75 
76 
77  /**
78  * @brief A container for photon visibility mapping data.
79  *
80  * This container is designed to replace the use of plain pointers to library
81  * data, adding an intermediate mapping layer.
82  *
83  * A proper mapping allows to use symmetries of the detector to reduce the
84  * redundant size of the library, at the cost of some run time.
85  *
86  * This container is used as a `util::MappedContainer` object, with the
87  * addition of being aware of whether the contained data is valid or not.
88  * The validity is estimated by considering the original data that is being
89  * mapped, that is the data from the library. If the data is invalid or empty,
90  * as it may be for a null pointer or an empty vector, the container data is
91  * also considered to be invalid.
92  *
93  *
94  * Implementation notes
95  * ---------------------
96  *
97  * In the current implementation, the concept of data being invalid is
98  * implemented by forcing the nominal size of the container to be zero.
99  *
100  *
101  * Known limitations
102  * ------------------
103  *
104  * Currently the mapping of the optical detectors is forced to be a static
105  * collection of detector IDs. If more flexibility is needed, the design of
106  * the container internals need to be updated to allow run time polymorphism.
107  *
108  * Given the type of validity detection described above, it takes extra steps
109  * to provide a default mapping for areas not covered by the library. While
110  * with plain `util::MappedContainer` that can be achieved by a empty data
111  * container and a mapping returning `InvalidIndex` for all optical detectors,
112  * here this would just yield to an invalid container. Instead, together with
113  * that mapping, some fake data needs to be supplied to
114  * `phot::OpDetVisibilityData`, which will be basically ignored and may be of
115  * any size larger than zero (or more precisely,
116  * `phot::isValidLibraryData()` must return `false`).
117  *
118  */
119  template <typename Cont, typename Mapping>
121  : public util::MappedContainer<Cont, Mapping>
122  {
124 
125  public:
126 
127  // import types from base class
128  using typename ContainerBase_t::DataContainer_t;
129  using typename ContainerBase_t::Mapping_t;
130  using typename ContainerBase_t::size_type;
131  using typename ContainerBase_t::value_type;
132 
133  private:
134 
135  /// Determines whether the current content should be considered valid.
136  static size_type effectiveSize
137  (DataContainer_t const& cont, size_type allegedSize);
138 
139  /// Determines whether the current content should be considered valid.
140  static size_type effectiveSize
141  (DataContainer_t const& cont, Mapping_t const& mapping);
142 
143  public:
144 
145 
146  // --- BEGIN Constructors --------------------------------------------------
147 
148  /// @name Validity information
149  /// @{
150  /// Default constructor: data will be invalid.
151  OpDetVisibilityData() = default;
152 
153  /**
154  * @brief Constructor: acquires data, mapping and a default value.
155  * @param cont container with the data to be mapped
156  * @param mapping the mapping to be used
157  * @param size the size of the container after mapping
158  * @param defValue value to be used as default
159  * @see `MappedContainer(DataContainer_t const&, Mapping_t const&, size_type, value_type)`
160  *
161  * This works as the equivalent `util::MappedContainer` constructor, except
162  * that if the data in `cont` is deemed invalid the size is overridden to
163  * zero.
164  */
166  DataContainer_t const& cont,
167  Mapping_t const& mapping,
168  size_type size,
169  value_type defValue
170  )
171  : ContainerBase_t(cont, mapping, effectiveSize(cont, size), defValue)
172  {}
173 
174  /**
175  * @brief Constructor: acquires data and mapping.
176  * @param cont container with the data to be mapped
177  * @param mapping the mapping to be used
178  * @param size the size of the container after mapping
179  * @see `MappedContainer(DataContainer_t const&, Mapping_t const&, size_type)`
180  *
181  * This works as the equivalent `util::MappedContainer` constructor, except
182  * that if the data in `cont` is deemed invalid the size is overridden to
183  * zero.
184  */
186  (DataContainer_t const& cont, Mapping_t const& mapping, size_type size)
187  : ContainerBase_t(cont, mapping, effectiveSize(cont, size))
188  {}
189 
190  /**
191  * @brief Constructor: acquires data and mapping.
192  * @param cont container with the data to be mapped
193  * @param mapping the mapping to be used
194  * @see `util::MappedContainer(DataContainer_t const&, Mapping_t const&, size_type)`
195  *
196  * The size of the container is declared to be the minimal one
197  * (see `minimal_size()`), unless data of the library `cont` is invalid,
198  * in which case the full container is invalid.
199  *
200  * The default value is assigned as in
201  * `util::MappedContainer(DataContainer_t const&, Mapping_t const&, size_type)`.
202  */
203  OpDetVisibilityData(DataContainer_t const& cont, Mapping_t const& mapping)
204  : ContainerBase_t(cont, mapping, effectiveSize(cont, mapping))
205  {}
206 
207 
208  // --- END Constructors ----------------------------------------------------
209 
210 
211  // --- BEGIN Validity information ------------------------------------------
212  /// @name Validity information
213  /// @{
214 
215  /// Returns whether the contained data is valid or not.
216  bool isValid() const { return !ContainerBase_t::empty(); }
217 
218  /// Returns whether the container has valid data.
219  operator bool() const { return isValid(); }
220 
221  /// Returns whether the container has no valid data.
222  bool operator!() const { return !isValid(); }
223 
224  /// @}
225  // --- END Validity information --------------------------------------------
226 
227 
228  }; // OpDetVisibilityData
229 
230 
231 } // namespace phot
232 
233 
234 //------------------------------------------------------------------------------
235 //--- template implementation
236 //------------------------------------------------------------------------------
237 
238 namespace phot {
239 
240  namespace details {
241 
242  //--------------------------------------------------------------------------
243  template <typename Cont>
244  auto generic_size(Cont&& cont)
245  { using std::size; return size(std::forward<Cont>(cont)); }
246 
247 
248  //--------------------------------------------------------------------------
249  // layered implementation of `LibraryDataValidatorStructStandardImpl`:
250 
251  // This is the last layer: if compiler points here,
252  // the type `Cont` is not being supported yet:
253  // - std::size() (or better, `generic_size()`)
254  template <typename Cont, typename = void>
256 
257  template <typename Cont>
259  <Cont, std::enable_if_t<util::always_true_v<decltype(
260  generic_size(std::declval<Cont>())
261  )>>
262  >
263  {
264  static bool isValid(Cont const& cont) { return generic_size(cont) > 0U; }
265  }; // struct LibraryDataValidatorStructStandardImpl_size
266 
267 
268  // - Cont::empty()
269  template <typename Cont, typename = void>
272  {};
273 
274  template <typename Cont>
276  <Cont, std::enable_if_t<util::always_true_v<decltype(
277  std::declval<Cont const>().empty()
278  )>>
279  >
280  {
281  static bool isValid(Cont const& cont) { return !cont.empty(); }
282  }; // struct LibraryDataValidatorStructStandardImpl_empty
283 
284 
285  // - Cont::is_valid()
286  template <typename Cont, typename = void>
289  {};
290 
291  template <typename Cont>
293  <Cont, std::enable_if_t<util::always_true_v<decltype(
294  std::declval<Cont const>().is_valid()
295  )>>
296  >
297  {
298  static bool isValid(Cont const& cont) { return cont.is_valid(); }
299  }; // struct LibraryDataValidatorStructStandardImpl_is_valid
300 
301 
302  // - Cont::isValid()
303  template <typename Cont, typename = void>
306  {};
307 
308  template <typename Cont>
310  <Cont, std::enable_if_t<util::always_true_v<decltype(
311  std::declval<Cont const>().isValid()
312  )>>
313  >
314  {
315  static bool isValid(Cont const& cont) { return cont.isValid(); }
316  }; // struct LibraryDataValidatorStructStandardImpl_isValid
317 
318 
319  // - std::unique_ptr<> (using `enable_if` to catch all qualifiers)
320  template <typename Cont, typename = void>
323  {};
324 
325  template <typename Cont>
327  <Cont, std::enable_if_t<util::is_unique_ptr_v<Cont>>>
328  {
329  static bool isValid(Cont const& cont) { return bool(cont); }
330  }; // struct LibraryDataValidatorStructStandardImpl_unique_ptr
331 
332 
333  // C pointer types:
334  template <typename T>
336 
337  // - T*
338  template <typename T>
340  { static bool isValid(T* ptr) { return bool(ptr); } };
341 
342  // - T[]
343  template <typename T>
346 
347  // - T[N]
348  template <typename T, std::size_t N>
350  { static bool isValid(T (&) [N]) { return N > 0U; } };
351 
352  // - entry point
353  template <typename Cont, typename = void>
356  {};
357 
358  template <typename Cont>
360  <Cont, std::enable_if_t<std::is_pointer_v<std::decay_t<Cont>>>>
362  <std::decay_t<Cont>>
363  {};
364 
365 
366  // - entry point
367  template <typename Cont>
370  {};
371 
372 
373  //--------------------------------------------------------------------------
374 
375  } // namespace details
376 
377 
378  //----------------------------------------------------------------------------
379  // we pick a standard implementation of our own, and let users add here
380  template <typename Cont, typename /* = void */>
383  <std::remove_reference_t<Cont>>
384  {};
385 
386 
387  //----------------------------------------------------------------------------
388  template <typename Cont>
389  bool isValidLibraryData(Cont&& cont) {
390  return
392  } // isValidLibraryData()
393 
394 
395  //----------------------------------------------------------------------------
396  template <typename Cont, typename Mapping>
398  (DataContainer_t const& cont, size_type allegedSize) -> size_type
399  { return isValidLibraryData(cont)? allegedSize: 0U; }
400 
401 
402  template <typename Cont, typename Mapping>
404  (DataContainer_t const& cont, Mapping_t const& mapping) -> size_type
405  {
406  return isValidLibraryData(cont)
407  ? ContainerBase_t::minimal_size(cont, mapping)
408  : 0U
409  ;
410  } // OpDetVisibilityData::effectiveSize(DataContainer_t, Mapping_t)
411 
412 
413  //----------------------------------------------------------------------------
414 
415 } // namespace phot
416 
417 
418 #endif // LARSIM_PHOTONPROPAGATION_LIBRARYMAPPINGTOOLS_OPDETVISIBILITYDATA_H
Provides MappedContainer class.
auto generic_size(Cont &&cont)
A meta-container providing transparent mapping on top of another.
Mapping Mapping_t
Type of the mapping object.
size_type minimal_size() const
Returns the minimum size to include all mapped values.
OpDetVisibilityData(DataContainer_t const &cont, Mapping_t const &mapping)
Constructor: acquires data and mapping.
STL namespace.
size_type size() const
Returns the nominal size of the container (after mapping).
OpDetVisibilityData(DataContainer_t const &cont, Mapping_t const &mapping, size_type size, value_type defValue)
Constructor: acquires data, mapping and a default value.
decltype(auto) constexpr size(T &&obj)
ADL-aware version of std::size.
Definition: StdUtils.h:92
util::MappedContainer< Cont, Mapping > ContainerBase_t
static size_type effectiveSize(DataContainer_t const &cont, size_type allegedSize)
Determines whether the current content should be considered valid.
bool operator!() const
Returns whether the container has no valid data.
Cont DataContainer_t
Type of the original container.
bool isValidLibraryData(Cont &&cont)
Returns the validity of content of library data in the container.
General LArSoft Utilities.
A container for photon visibility mapping data.
bool isValid() const
Returns whether the contained data is valid or not.
bool empty() const
Returns whether the container has no elements.
int bool
Definition: qglobal.h:345
Trait for determining the validity of library data in a container.