IPhotonMappingTransformations.h
Go to the documentation of this file.
1 /**
2  * @file larsim/PhotonPropagation/LibraryMappingTools/IPhotonMappingTransformations.h
3  * @brief Interface for transformation of photon visibility maps.
4  * @author Gianluca Petrillo (petrillo@slac.stanford.edu)
5  * @date March 20, 2019
6  *
7  * This is a pure interface.
8  */
9 
10 #ifndef LARSIM_PHOTONPROPAGATION_LIBRARYMAPPINGTOOLS_IPHOTONMAPPINGTRANSFORMATIONS_H
11 #define LARSIM_PHOTONPROPAGATION_LIBRARYMAPPINGTOOLS_IPHOTONMAPPINGTRANSFORMATIONS_H
12 
13 // LArSoft libraries
15 #include "larcorealg/CoreUtils/ContainerMeta.h" // util::collection_value_t<>
16 #include "larcoreobj/SimpleTypesAndConstants/geo_vectors.h" // geo::Point_t
17 
18 // C++ standard libraries
19 #include <vector>
20 #include <utility> // std::forward()
21 #include <functional> // std::cref()
22 #include <stdexcept> // std::out_of_range, std::domain_error
23 
24 
25 namespace phot {
26 
27  /**
28  * @brief Collection of functions to transform photon mapping data.
29  *
30  * If the optical detectors of an experiment sport some symmetry, it may be
31  * convenient to exploit that symmetry to reduce the actual size of the
32  * internal mapping to a basic volume, and using the symmetry rules to convert
33  * between that basic volume and the world volume where the entire detector
34  * is represented.
35  * It is common that the symmetries require also a logic rearrangement of the
36  * actual optical detectors: a hook for that type of mapping is also provided,
37  * bidirectional.
38  *
39  * This interface expresses the following transformations:
40  * * `detectorToLibrary()` transform a point in the detector space
41  * to a point in the library space
42  * * `opDetToLibraryIndex()` transforms a optical detector ID into the
43  * corresponding library index
44  * * `libraryIndexToOpDet()` transforms a library index into the corresponding
45  * global optical detector ID
46  *
47  *
48  * Glossary
49  * =========
50  * @anchor PhotonMappingTransformations_Glossary
51  *
52  * In this class and its documentation the following terms are in use:
53  *
54  * * _library_ is a source of data; our libraries mapping the real space into
55  * some parametrization, and store the data as function of the
56  * parametrization values. In particular, they usually parametrize the
57  * covered space into tiny boxes ("voxels") and they address the data
58  * with a voxel index; and for each voxel index they store a collection
59  * of data values, addressed by another independent index that we call...
60  * * _detector space_ or _world_ is the physical space where the whole
61  * detector is represented; in LArSoft this space is described in the
62  * global (or world) coordinate system, and the geometry description
63  * (provided by `geo::GeometryCore`) works in this space
64  * * _library space_ is a representation of the physical space covered by the
65  * library; it may effectively be a subset of the world space (e.g.
66  * a single drift volume) or it may be a completely local representation,
67  * that needs a mapping with the world space in order to be of any use
68  * * _library identifier_ or _library ID_ or _library index_ is the index used
69  * to access a single value of the library (after having chosen the voxel
70  * to get data for); note that the "library identifier" does not actually
71  * identify a library, but rather some specific data within the a
72  * library. This mapping class uses this concept to identify and select
73  * library data values, and uses the type `LibraryIndex_t` to represent
74  * it in the code
75  * * _optical detector_ is a LArSoft concept, representing a physical detector
76  * with a presence in the real world; in LArSoft, they may be represented
77  * by...
78  * * _optical detector number_ or _optical detector ID_ is a unique identifier
79  * in the form of either an integral number or as a location structure,
80  * `geo::OpDetID`; this concept is also used, e.g., as argument of
81  * `geo::GeometryCore::OpDetGeoFromOpDet()`. This mapping class uses the
82  * concept and the single unique number representation to identify the
83  * optical detector, and uses the local type `OpDetID_t` to represent it
84  * in the code;
85  * * _optical detector readout channel_ or just _channel_ is a LArSoft
86  * * concept, representing a data single source from optical detectors, and
87  * associated with optical detector readout. In most detectors, there is
88  * one channel per optical detector and vice versa. It may be described
89  * in LArSoft by...
90  * * _optical detector channel number_ or _channel number_ or (again)
91  * _channel_ is a unique numeric identifier for a optical detector readout
92  * channel; this is used, e.g., as argument of
93  * `geo::GeometryCore::OpDetGeoFromOpDet()`)
94  *
95  *
96  * @note While optical detector and optical detector channels are different
97  * concepts, nothing this class is currently dealing with relies on any
98  * difference between the two. Nevertheless, given the nature of the
99  * library of providing visibility information based on the geometry of
100  * the detectors, using the concept of physical optical detector is more
101  * appropriate than using the one of readout channel.
102  *
103  *
104  * Technical notes
105  * ================
106  *
107  * Mapping
108  * --------
109  *
110  * Currently the mapping is expressed with a specific type. If more
111  * flexibility is needed, the mapping might use run time polymorphism.
112  * This case is not supported right now. If need arose, something might be
113  * designed on top of what is here now.
114  *
115  */
117 
118  public:
119 
120  virtual ~IPhotonMappingTransformations() = default;
121 
122  // --- BEGIN Data types ----------------------------------------------------
123  using OpDetID_t = int; ///< Type describing a optical detector ID.
124 
125  /// Type describing a library index. FIXME former LibraryOpDetID_t
126  using LibraryIndex_t = OpDetID_t; // currently bound to channel ID
127 
128  /**
129  * @brief Type describing the mapping of optical detectors into library
130  * indices.
131  *
132  * This type of mapping allows querying data values by optical detector ID,
133  * fetching them from library data source.
134  *
135  * This type guarantees:
136  * * `operator[](OpDetID_t)` to fetch the library index associated to
137  * the specified optical detector
138  * * `size()` to report how many optical detectors are supported
139  *
140  */
141  using LibraryIndexToOpDetMap = std::vector<OpDetID_t>;
142 
143  /**
144  * @brief Type describing the mapping of library indices into optical
145  * detectors.
146  *
147  * This type of mapping allows querying data values by library index,
148  * fetching them from an optical-detector-based data source.
149  *
150  * This type guarantees:
151  * * `operator[](LibraryIndex_t)` to access the optical detector ID of
152  * the specified library index
153  * * `size()` to report how many library optical detectors are supported
154  * * either conversion to `bool`, response to `empty()` or to `std::size()`
155  * to determine if the contained data is valid
156  * (actually, just response to `phot::isValidLibraryData()`)
157  *
158  */
159  using OpDetToLibraryIndexMap = std::vector<LibraryIndex_t>; // FIXME former LibOpDetIDmap
160 
161  /**
162  * @brief Type of optical detector data collection.
163  * @tparam LibDataColl type of the original library data container
164  *
165  * This type behaves like a random access collection with as index the
166  * optical detector ID and as value the data corresponding to that optical
167  * detector.
168  */
169  template <typename LibDataColl>
171  <
174  >;
175 
176  // --- END Data types ------------------------------------------------------
177 
178 
179  /**
180  * @brief Value used to identify an invalid optical detector.
181  *
182  * It may be used as value of the library-to-detector mapping.
183  */
184  static constexpr OpDetID_t InvalidOpDetID
186 
187  /**
188  * @brief Value used for an invalid library index.
189  *
190  * It may be used as value of the detector-to-library mapping.
191  */
192  static constexpr LibraryIndex_t InvalidLibraryIndex
194 
195 
196  // --- BEGIN Geometry mapping interface ------------------------------------
197  /// @name Geometry mapping interface
198  /// @{
199 
200  /**
201  * @brief Returns the representation within the library of a detector
202  * location.
203  * @param location position in world coordinates [cm]
204  * @return a vector expressing `location` in the library space
205  * @throw std::domain_error if the function can't handle `location`
206  *
207  * The units and meaning of the returned location are library-dependent.
208  *
209  * Example: assuming that `fVoxelDef` contains the description of the
210  * voxelization of the library, the ID of the voxel at `location` can be
211  * obtained from a `mapping` as:
212  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
213  * auto const voxelID
214  * = fVoxelDef.GetVoxelID(mapping->detectorToLibrary(location));
215  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
216  * where `mapping` points to an object implementing the
217  * `phot::IPhotonMappingTransformations` interface.
218  * Note that the caller here has no business with the translated location,
219  * beside propagating it to the library: caller simply is not explained
220  * the meaning of that translated location.
221  */
223  (geo::Point_t const& location) const = 0;
224 
225  /// @}
226  // --- END Geometry mapping interface --------------------------------------
227 
228 
229  // --- BEGIN Optical detector mapping interface ----------------------------
230  /**
231  * @name Optical detector mapping interface
232  *
233  * Here the mapping is provided between optical detectors (`OpDetID_t`) and
234  * library indices (`LibraryIndex_t`).
235  *
236  * Terms and roles of the various concepts involved in the mapping may be
237  * confusing: see the @ref PhotonMappingTransformations_Glossary "glossary"
238  * in `phot::IPhotonMappingTransformations` class description for their
239  * definition.
240  */
241  /// @{
242 
243  /**
244  * @brief Returns the library index for the specified optical detector.
245  * @param location a point in detector space to provide global context
246  * @param opDetID optical detector identifier
247  * @return index corresponding to `opDetID`, or `InvalidLibraryIndex`
248  * @throw std::out_of_range if input optical detector can't be handled
249  * @throw std::domain_error if location can't be handled
250  * @see `libraryIndexToOpDet()`, `opDetsToLibraryIndices()`
251  *
252  * The specified global identifier `opDetID` of an optical detector is
253  * converted into an index for the library.
254  *
255  * If the library does not include information for this optical detector,
256  * the value `InvalidLibraryIndex` is returned instead.
257  *
258  * The specified `location` is used to inform the conversion, and it is
259  * usually pointing to the source of scintillation.
260  */
262  (geo::Point_t const& location, OpDetID_t opDetID) const = 0;
263 
264  /**
265  * @brief Returns the optical detector ID for the specified library index.
266  * @param location a point in detector space to provide global context
267  * @param libIndex library index to be mapped
268  * @return optical detector corresponding to `libIndex`, or `InvalidOpDetID`
269  * @throw std::out_of_range if input index can't be handled
270  * @throw std::domain_error if location can't be handled
271  * @see `opDetToLibraryIndex()`, `libraryIndicesToOpDets()`
272  *
273  * The library index `libIndex` is converted into a optical detector ID.
274  * If the library does not include information for this optical detector,
275  * the value `InvalidLibraryIndex` is returned instead.
276  *
277  * The specified `location` is used to inform the conversion, and it is
278  * usually pointing to the source of scintillation.
279  */
281  (geo::Point_t const& location, LibraryIndex_t libIndex) const = 0;
282 
283 
284  /**
285  * @brief Returns a map of library indices as function of optical detectors.
286  * @param location a world reference point to provide global context
287  * @return library indices for all optical detectors
288  * @throw std::domain_error if location can't be handled
289  * @see `opDetToLibraryIndex()`, `opDetsToLibraryIndices()`
290  *
291  * The returned value is a mapping object (see `OpDetToLibraryIndexMap`
292  * documentation for the interface). If an optical detector has no
293  * representation in the library at `location`, the index value
294  * corresponding to it is `InvalidLibraryIndex`.
295  *
296  * The specified `location` is used to inform the conversion, and it is
297  * usually pointing to the source of scintillation. It may be left unused.
298  */
300  (geo::Point_t const& location) const = 0;
301 
302  /**
303  * @brief Expected number of mappings of optical detector into library
304  * index.
305  * @return the expected size of the mapping of optical detectors
306  * @see `opDetsToLibraryIndices()`
307  *
308  * This is effectively the number of available optical detectors, as well
309  * as the size of the mapping as returned by `opDetsToLibraryIndices()`.
310  */
311  virtual std::size_t opDetMappingSize() const = 0;
312 
313  /**
314  * @brief Returns a map of optical detectors identifiers, one for each
315  * library index.
316  * @param location a world reference point to provide global context
317  * @return optical detector identifiers for all library indices
318  * @throw std::domain_error if location can't be handled
319  * @see `opDetsToLibraryIndices()`, `libraryIndexToOpDet()`
320  *
321  * The returned value is a mapping object (see `LibraryIndexToOpDetMap`
322  * documentation for the interface). If a library index does not map to any
323  * optical detector in the library at `location` (which is unusual!),
324  * the optical detector ID corresponding to it is `InvalidOpDetID`.
325  *
326  * The specified `location` is used to provide context in a similar
327  * fashion as `detectorToLibrary()` does. It can be used to choose the
328  * correct mapping among the available ones.
329  */
331  (geo::Point_t const& location) const = 0;
332 
333  /**
334  * @brief Expected size of the mapping from library to optical detectors.
335  * @param location a world reference point to provide global context
336  * @throw std::domain_error if location can't be handled
337  * @return the expected size of the mapping from library indices to
338  * optical detectors
339  * @see `libraryIndicesToOpDets()`
340  *
341  * This is effectively the size of the mapping returned by
342  * `libraryIndicesToOpDets()`. It represents how many library indices are
343  * provided by the library for the specified `location`. For example, in
344  * an implementation exploiting the modularity of a detector with _N_
345  * channels and made of _M_ modules, this value might be _N / M_.
346  */
347  virtual std::size_t libraryMappingSize
348  (geo::Point_t const& location) const = 0;
349 
350  /// @}
351  // --- END Optical detector mapping interface ------------------------------
352 
353 
354  // --- BEGIN Utility methods -----------------------------------------------
355  /// @name Utility methods
356  /// @{
357 
358  /**
359  * @brief Remaps a collection indexed by library index into one indexed by
360  * optical detector IDs.
361  * @tparam Coll type of collection of data from the library, to be mapped
362  * @param opDetToLibraryMap the mapping to be applied
363  * @param source collection of library data to be mapped
364  * @param defaultValue value returned for unmapped optical detector IDs
365  * @return a random access collection providing data by optical detector ID
366  *
367  * This method returns a collection proxy that dynamically applies the
368  * specified mapping. The original data is not copied.
369  *
370  * The format of the map (`opDetMap`) is an object with a indexing operator
371  * where the index is _the one in the destination collection_ (i.e. the
372  * optical detector ID) and the mapped value is the index in the source
373  * collection (the libary index). Each valid optical detector ID must be
374  * mapped. If the library index mapped to an optical detector is
375  * `InvalidLibraryIndex`, that optical detector is not mapped anywhere and
376  * its entry in the mapped collection is assigned the value `defaultValue`.
377  * Otherwise, the library index must be valid (which means, up to the result
378  * of `libraryMappingSize()` applied to the location where `opDetMap` is
379  * valid).
380  *
381  */
382  template <typename Coll>
384  OpDetToLibraryIndexMap const& opDetToLibraryMap, Coll&& source,
385  util::collection_value_t<Coll> defaultValue = {}
386  ) const;
387 
388  /**
389  * @brief Remaps a collection indexed by library index into one indexed by
390  * optical detector IDs according to the mapping at `location`.
391  * @tparam Coll type of collection of data from the library, to be mapped
392  * @param location a world reference point to provide global context
393  * @param source collection of library data to be mapped
394  * @param defaultValue value returned for unmapped optical detector IDs
395  * @return a random access collection providing data by optical detector ID
396  * @see `applyOpDetMapping()`
397  *
398  * This method applies a mapping (see
399  * `applyOpDetMapping(OpDetToLibraryIndexMap const&, Coll&&, util::collection_value_t<Coll>)`)
400  * that is obtained via `libraryIndicesToOpDets()`.
401  */
402  template <typename Coll>
404  geo::Point_t const& location, Coll&& source,
405  util::collection_value_t<Coll> defaultValue = {}
406  ) const
407  {
408  return applyOpDetMapping(
409  opDetsToLibraryIndices(location), std::forward<Coll>(source),
410  defaultValue
411  );
412  }
413 
414  /// @}
415  // --- END Utility methods -------------------------------------------------
416 
417 
418  }; // class IPhotonMappingTransformations
419 
420 
421 } // namespace phot
422 
423 
424 
425 //------------------------------------------------------------------------------
426 //--- Template implementation
427 //------------------------------------------------------------------------------
428 template <typename Coll>
430  OpDetToLibraryIndexMap const& opDetToLibraryMap, Coll&& source,
431  util::collection_value_t<Coll> defaultValue /* = {} */
432 ) const
434 {
435 
436  using std::size;
437 
438  // number of available destination slots (i.e. how many optical detectors)
439  auto const n = size(opDetToLibraryMap);
440 
442  util::make_collection_reference(std::forward<Coll>(source))
443  , std::cref(opDetToLibraryMap) // mapping is referenced
444  , n // size
445  , defaultValue
446  };
447 
448 } // phot::IPhotonMappingTransformations::applyOpDetMapping()
449 
450 
451 //------------------------------------------------------------------------------
452 
453 #endif // LARSIM_PHOTONPROPAGATION_LIBRARYMAPPINGTOOLS_IPHOTONMAPPINGTRANSFORMATIONS_H
auto make_collection_reference(Coll &&coll)
Returns an object referencing to the data contained in coll.
virtual OpDetID_t libraryIndexToOpDet(geo::Point_t const &location, LibraryIndex_t libIndex) const =0
Returns the optical detector ID for the specified library index.
Data container for use with photon visibility libraries.
OpDetID_t LibraryIndex_t
Type describing a library index. FIXME former LibraryOpDetID_t.
virtual std::size_t opDetMappingSize() const =0
Expected number of mappings of optical detector into library index.
Collection of functions to transform photon mapping data.
virtual ~IPhotonMappingTransformations()=default
decltype(auto) constexpr size(T &&obj)
ADL-aware version of std::size.
Definition: StdUtils.h:92
typename collection_reference_type< Coll >::type collection_reference_t
The type contained in util::collection_reference_type trait.
auto applyOpDetMapping(geo::Point_t const &location, Coll &&source, util::collection_value_t< Coll > defaultValue={}) const
Remaps a collection indexed by library index into one indexed by optical detector IDs according to th...
static constexpr LibraryIndex_t InvalidLibraryIndex
Value used for an invalid library index.
std::void_t< T > n
static constexpr OpDetID_t InvalidOpDetID
Value used to identify an invalid optical detector.
std::vector< OpDetID_t > LibraryIndexToOpDetMap
Type describing the mapping of optical detectors into library indices.
static int max(int a, int b)
ROOT::Math::PositionVector3D< ROOT::Math::Cartesian3D< double >, ROOT::Math::GlobalCoordinateSystemTag > Point_t
Type for representation of position in physical 3D space.
Definition: geo_vectors.h:184
virtual geo::Point_t detectorToLibrary(geo::Point_t const &location) const =0
Returns the representation within the library of a detector location.
int OpDetID_t
Type describing a optical detector ID.
MappedOpDetData_t< Coll > applyOpDetMapping(OpDetToLibraryIndexMap const &opDetToLibraryMap, Coll &&source, util::collection_value_t< Coll > defaultValue={}) const
Remaps a collection indexed by library index into one indexed by optical detector IDs...
General LArSoft Utilities.
virtual LibraryIndexToOpDetMap const & libraryIndicesToOpDets(geo::Point_t const &location) const =0
Returns a map of optical detectors identifiers, one for each library index.
A container for photon visibility mapping data.
virtual OpDetToLibraryIndexMap const & opDetsToLibraryIndices(geo::Point_t const &location) const =0
Returns a map of library indices as function of optical detectors.
virtual std::size_t libraryMappingSize(geo::Point_t const &location) const =0
Expected size of the mapping from library to optical detectors.
Definitions of geometry vector data types.
typename collection_value_type< Coll >::type collection_value_t
Type contained in the collection Coll.
Definition: ContainerMeta.h:65
C++ metaprogramming utilities for dealing with containers.
virtual LibraryIndex_t opDetToLibraryIndex(geo::Point_t const &location, OpDetID_t opDetID) const =0
Returns the library index for the specified optical detector.
std::vector< LibraryIndex_t > OpDetToLibraryIndexMap
Type describing the mapping of library indices into optical detectors.