ChargedSpacePoints.h
Go to the documentation of this file.
1 /**
2  * @file lardata/RecoBaseProxy/ChargedSpacePoints.h
3  * @brief Offers `proxy::ChargedSpacePoints` and `proxy::SpacePointWithCharge`
4  * class for `recob::SpacePoint` with `recob:Charge` access.
5  * @author Gianluca Petrillo (petrillo@fnal.gov)
6  * @date December 20, 2017
7  *
8  * This file defined the proxy of a space point collection with associated
9  * reconstructed charge. It contains:
10  *
11  * * `proxy::ChargedSpacePoints`: the formal name of the proxy, also containing
12  * information about its main collection and the definition of the standard
13  * tags
14  * * `proxy::getChargedSpacePoints()`: a function to create a collection proxy
15  * of that type
16  * * `proxy::withCharge()`: a function that can be used as an argument of
17  * `proxy::getChargedSpacePoints()` (or `proxy::getCollection()`) to add
18  * further associated charge collections
19  * * `proxy::SpacePointWithCharge`: the interface that users see when accessing
20  * one element of the collection proxy (derived and extended from the
21  * standard one)
22  * * `proxy::ChargedSpacePointsCollectionProxy`: the interface of the collection
23  * proxy (derived and extended from the standard one)
24  * * a specialization of `proxy::CollectionProxyMakerTraits` for this collection
25  * proxy, which informs the infrastructure about the two customized classes
26  * above (in fact, only about the latter, which in turn contains the
27  * information about the other one)
28  *
29  * See the documentation about @ref LArSoftProxyChargedSpacePoint "this proxy"
30  * for examples on how to use it.
31  */
32 
33 /**
34  * @brief Proxy for a `recob::SpacePoint` collection with associated charge.
35  * @defgroup LArSoftProxyChargedSpacePoint Space points with charge
36  * @ingroup LArSoftProxyReco
37  *
38  * Some algorithms can reconstruct the position of some activity in the active
39  * volume of the detector, locating it as a 3D point, and also estimate the
40  * electric charge associated to that localized activity.
41  *
42  * The prescription is for such algorithms to produce as output two data
43  * products:
44  * 1. a collection of points (`std::vector<recob::SpacePoint>`) containing the
45  * location of each reconstructed activity
46  * 2. a collection of charge information (`std::vector<recob::PointCharge>`)
47  * containing the reconstructed charge for each activity.
48  *
49  * The two data products are _implicitly_ associated by counting the same number
50  * of elements, and being sorted so that the _i_-th charge pertains the _i_-th
51  * location (@ref LArSoftProxyDefinitionParallelData "parallel data product"
52  * requirement).
53  *
54  * Access to this information is facilitated via the low-overhead data proxy
55  * `proxy::ChargedSpacePoints`.
56  *
57  *
58  *
59  * Obtaining a charged space point proxy
60  * ======================================
61  *
62  * The charged space point proxy can be obtained directly as:
63  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
64  * auto spacePoints = proxy::getChargedSpacePoints(event, pointsTag);
65  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
66  * where `tag` is the input tag for both the space points and the charge, which
67  * must have been created by the same module (usually, the tag is just the
68  * module label).
69  *
70  *
71  * Extending the proxy collection object
72  * --------------------------------------
73  *
74  * This proxy can be augmented with the usual proxy operations (see
75  * `proxy::getCollection()`); `proxy::getChargedSpacePoints()` calls
76  * are in fact equivalent to:
77  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
78  * proxy::getCollection<proxy::ChargedSpacePoints>
79  * (event, tag, proxy::withParallelData<recob::PointCharge>(), ...);
80  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
81  *
82  *
83  * Types of proxies, and what to do with them
84  * ===========================================
85  *
86  * Currently there are two different type of proxy-like objects for space points
87  * with added charge.
88  * Each one supports a specific concept:
89  *
90  * * `proxy::ChargedSpacePoints` represents the whole collection of space
91  * points; it covers the location and the associated charge. It is obtained
92  * by calling `getChargedSpacePoints()` as described above.
93  * * `proxy::SpacePointWithCharge` represents a single point with charge
94  * information; the location and the charge can be accessed through it.
95  * These proxies are obtained from the space point collection proxy above.
96  *
97  * For the details of the interface and the information that is exposed by each
98  * of these proxy classes, please refer to each class documentation. In
99  * particular, see `proxy::ChargedSpacePoints` documentation for more usage
100  * examples.
101  *
102  */
103 
104 #ifndef LARDATA_RECOBASEPROXY_CHARGEDSPACEPOINTS_H
105 #define LARDATA_RECOBASEPROXY_CHARGEDSPACEPOINTS_H
106 
107 
108 // LArSoft libraries
109 #include "lardata/RecoBaseProxy/ProxyBase.h" // proxy namespace
112 #include "larcorealg/Geometry/geo_vectors_utils.h" // geo::vect namespace
113 
114 // framework libraries
115 
116 
117 namespace proxy {
118 
119  //----------------------------------------------------------------------------
120 
121  /**
122  * @brief Proxy tag for a `recob::SpacePoint` collection with charge.
123  * @see `proxy::getChargedSpacePoints()`,
124  * `proxy::SpacePointWithCharge`,
125  * `proxy::ChargedSpacePointsCollectionProxy`
126  * @ingroup LArSoftProxyChargedSpacePoint
127  *
128  * This type can be used to get a proxy for `recob::SpacePoint` collection
129  * with charge. Normally, you want to use
130  * `proxy::getChargedSpacePoints()` directly instead:
131  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
132  * auto spacePoints = proxy::getChargedSpacePoints(event, pointsTag);
133  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
134  *
135  * An example of usage for a simple space point processing loop:
136  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
137  * void MyAnalyzer::analyze(art::Event const& event) {
138  *
139  * auto points = proxy::getChargedSpacePoints(event, pointsTag);
140  *
141  * if (points.empty()) {
142  * mf::LogVerbatim("ProxyTest")
143  * << "No points in '" << pointsTag.encode() << "'";
144  * return;
145  * }
146  *
147  * mf::LogVerbatim log("ProxyTest");
148  * for (auto point: points) {
149  * log << "\nPoint at " << point.position() << " (ID=" << point.ID()
150  * << ") has ";
151  * if (point.hasCharge()) log << "charge " << point.charge();
152  * else log << "no charge";
153  * } // for point
154  *
155  * mf::LogVerbatim("ProxyTest") << "Collection '" << pointsTag.encode()
156  * << "' contains " << points.size() << " points.";
157  *
158  * } // MyAnalyzer::analyze()
159  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
160  * In this example, the charged space point proxy accesses the information
161  * exclusively via its specific interface.
162  * The complete documentation of the interface is split between
163  * `proxy::ChargedSpacePointsCollectionProxy` (treating the collection as a
164  * whole) and `proxy::SpacePointWithCharge` (accessing the individual element
165  * of the collection).
166  *
167  * Unfortunately, the proxy object (`point` in the example) can be of a
168  * different class depending on which data is merged into it (via optional
169  * arguments after the `tag` argument).
170  * This implies than when passing proxies as arguments to functions, template
171  * types must be used. For example, the following code is equivalent to the
172  * one above, but with methods processing a single point (a point proxy):
173  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
174  * template <typename Point>
175  * void MyAnalyzer::processPoint(Point const& point) const {
176  *
177  * mf::LogVerbatim log("ProxyTest");
178  * log << "\nPoint at " << point.position() << " (ID=" << point.ID()
179  * << ") has ";
180  * if (point.hasCharge()) log << "charge " << point.charge();
181  * else log << "no charge";
182  *
183  * } // MyAnalyzer::processPoint()
184  *
185  *
186  * void MyAnalyzer::proxyUsageExample(art::Event const& event) {
187  *
188  * auto points = proxy::getChargedSpacePoints(event, pointsTag);
189  *
190  * if (points.empty()) {
191  * mf::LogVerbatim("ProxyTest")
192  * << "No points in '" << pointsTag.encode() << "'";
193  * return;
194  * }
195  *
196  * mf::LogVerbatim("ProxyTest") << "Collection '" << pointsTag.encode()
197  * << "' contains " << points.size() << " points.";
198  *
199  * for (auto point: points) {
200  *
201  * processPoint(point);
202  *
203  * } // for point
204  *
205  * } // MyAnalyzer::proxyUsageExample()
206  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
207  *
208  * A new, filtered collection of proxies can be created with obvious means and
209  * with a less-than-friendly declaration:
210  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
211  * std::vector<decltype(points)::element_proxy_t> strongPoints;
212  * for (auto point: points) {
213  * if (point.charge() >= 30.0) strongPoints.push_back(point);
214  * }
215  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
216  * The collection thus created (`strongPoints`) is valid also after the
217  * collection proxy (`points`) has fallen out of scope.
218  *
219  * @note `proxy::ChargedSpacePoints` is *not* the type of the collection proxy
220  * returned by `proxy::getChargedSpacePoints()`.
221  */
223 
224  /// Type of the main collection.
225  using SpacePointDataProduct_t = std::vector<recob::SpacePoint>;
226 
227  /// Tag used for the "standard" charge information.
229 
230  }; // struct ChargedSpacePoints
231 
232 
233 
234  //--------------------------------------------------------------------------
235  /**
236  * @brief Proxy class for charged space point proxy elements.
237  * @tparam CollProxy type of point proxy collection to get data from
238  * @see `proxy::CollectionProxyElement`,
239  * `proxy::ChargedSpacePointsCollectionProxy`
240  *
241  * For details on the space point interface see `proxy::ChargedSpacePoints`.
242  */
243  template <typename CollProxy>
244  struct SpacePointWithCharge: public CollectionProxyElement<CollProxy> {
245 
246  using base_t = CollectionProxyElement<CollProxy>; ///< Base type.
247  using base_t::base_t; // inherit constructors
248 
249  public:
250 
251  // --- BEGIN data object access --------------------------------------------
252  /// @{
253  /// @name Full data object access
254 
255  /// Returns the original space point.
256  recob::SpacePoint const& point() const { return base_t::operator*(); }
257 
258  /// @}
259  // --- END data object access ----------------------------------------------
260 
261  /// Returns the `recob::PointCharge` object with the complete charge
262  /// information.
264  { return base_t::template get<ChargedSpacePoints::ChargeTag>(); }
265 
266  // --- BEGIN space point access --------------------------------------------
267  /// @{
268  /// @name Direct space point interface
269 
270  /// Returns the ID of the space point.
271  auto ID() const { return point().ID(); }
272 
273  /// Returns the position of the space point.
275  { return geo::vect::makePointFromCoords(point().XYZ()); }
276 
277  /// @}
278  // --- END space point access ----------------------------------------------
279 
280 
281  // --- BEGIN charge access -------------------------------------------------
282  /// @{
283  /// @name Direct charge interface
284 
285  /// Returns the charge associated to this point
286  /// @see `recob::PointCharge::charge()`
288  { return chargeInfo().charge(); }
289 
290  /// Returns whether the charge associated to the space point is valid.
291  /// @see `recob::PointCharge::hasCharge()`
292  bool hasCharge() const { return chargeInfo().hasCharge(); }
293 
294  /// @}
295  // --- END charge access ---------------------------------------------------
296 
297 
298  }; // SpacePointWithCharge<>
299 
300 
301  //----------------------------------------------------------------------------
302  /**
303  * @brief Proxy collection class for space points associated to charge.
304  * @tparam MainColl type of space point collection
305  * @tparam AuxColl types of auxiliary data collections
306  * @see `proxy::SpacePointWithCharge`, `proxy::CollectionProxyBase`
307  *
308  * This proxy collection allows access to space point and charge collection
309  * directly:
310  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
311  * auto points = proxy::getChargedSpacePoints(event, pointsTag);
312  * auto const& spacePoints = points.spacePoints();
313  * auto const& charges = points.charges();
314  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
315  * When accessing the collection proxy element by element (that is, charged
316  * space point by charged space point), the available interface is documented
317  * in `proxy::SpacePointWithCharge`.
318  *
319  * The standard proxy interface is also available
320  * (see `proxy::CollectionProxyBase`).
321  */
322  template <typename MainColl, typename... AuxColl>
324  : public CollectionProxyBase<SpacePointWithCharge, MainColl, AuxColl...>
325  {
326  using base_t
327  = CollectionProxyBase<SpacePointWithCharge, MainColl, AuxColl...>;
328  using base_t::base_t;
329 
330  public:
331 
332  /// Returns the original collection of space points.
333  auto const& spacePoints() const
334  { return base_t::main(); }
335 
336  /// Returns the original collection of charge information.
337  auto const& charges() const
338  {
339  return base_t::template get<ChargedSpacePoints::ChargeTag>().dataRef();
340  }
341 
342  }; // ChargedSpacePointsCollectionProxy
343 
344 
345  //----------------------------------------------------------------------------
346  /**
347 [ * @brief Adds additional `recob::PointCharge` information to the proxy.
348  * @param inputTag the data product label to read the data from
349  * @return an object driving `getCollection()` to use a `recob::PointCharge`
350  * @ingroup LArSoftProxyChargedSpacePoint
351  *
352  * The `proxy::ChargedSpacePoints` returned by
353  * `proxy::getChargedSpacePoints()` comes with its charge by default.
354  * If a different one is required, `proxy::withCharge()` can be used:
355  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
356  * auto points = proxy::getCollection<proxy::ChargedSpacePoints>
357  * (event, pointsTag, proxy::withCharge(calibrationTag));
358  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
359  * The charge from the data product of type `std::vector<recob::PointCharge>`
360  * with input tag `calibrationTag` will be used as default charge of the proxy
361  * instead of the one from `pointsTag`.
362  */
363  template <typename Tag = proxy::ChargedSpacePoints::ChargeTag>
364  auto withCharge(art::InputTag inputTag)
365  { return proxy::withParallelDataAs<recob::PointCharge, Tag>(inputTag); }
366 
367 
368  /**
369  * @brief Creates and returns a proxy to space points with associated charge.
370  * @tparam Event type of the event to read data from
371  * @tparam Args additional arguments
372  * @param event event to read the data from
373  * @param inputTag tag for the reconstructed space points and charge data
374  * @param withArgs additional elements to be merged into the proxy
375  * @return a proxy to space points with associated charge
376  * @ingroup LArSoftProxyChargedSpacePoint
377  * @see `proxy::ChargedSpacePoints`, `proxy::SpacePointWithCharge`,
378  * `proxy::ChargedSpacePointsCollectionProxy`, `proxy::getCollection()`
379  *
380  * This function initializes and return a space point proxy with associated
381  * charge.
382  * The proxy has a `recob::SpacePoint` as main data product, and it comes with
383  * an association of a single `recob::PointCharge` per space point.
384  * It is recommended that the interface documented in
385  * `proxy::ChargedSpacePoints` is used to interact with this proxy.
386  * The standard proxy interface is nevertheless also available (the charge
387  * is associated with the tag `proxy::ChargedSpacePoints::ChargeTag`).
388  *
389  * Additional elements can be merged into the proxy, in the usual way of
390  * `proxy::getCollection()`.
391  *
392  */
393  template <typename Event, typename... Args>
395  (Event const& event, art::InputTag inputTag, Args&&... withArgs)
396  {
397  return proxy::getCollection<ChargedSpacePoints>(
398  event, inputTag, withCharge(inputTag), std::forward<Args>(withArgs)...
399  );
400  } // getChargedSpacePoints()
401 
402 
403  //----------------------------------------------------------------------------
404  /**
405  * @brief Traits of `proxy::ChargedSpacePoints` proxy
406  *
407  * The `proxy::ChargedSpacePoints` is special in that it uses a custom
408  * collection proxy, `ChargedSpacePointsCollectionProxy`, which in turns uses
409  * a custom collection proxy element, `SpacePointWithCharge`.
410  * The former allows to access all the charges and space points with
411  * meaningful methods (`spacePoints()` and `charges()`), and the latter allows
412  * the same when addressing the single element of the collection
413  * (`position()`, `charge()`, etc.).
414  *
415  * The price for this candy is that those interfaces need to be written, and
416  * then the traits of the proxy needs to be specialized to register that
417  * customization.
418  *
419  * Specifying `collection_proxy_impl_t` is the way to do that. The other
420  * traits are inherited from "default" values of an unflavoured proxy.
421  */
422  template <>
424  : public
425  CollectionProxyMakerTraits<ChargedSpacePoints::SpacePointDataProduct_t>
426  {
427  template <typename... Args>
429  };
430 
431  //----------------------------------------------------------------------------
432 
433 
434 } // namespace proxy
435 
436 
437 #endif // LARDATA_RECOBASEPROXY_CHARGEDSPACEPOINTS_H
Utilities to extend the interface of geometry vectors.
Collection of data type definitions for collection proxies.
auto getChargedSpacePoints(Event const &event, art::InputTag inputTag, Args &&...withArgs)
Creates and returns a proxy to space points with associated charge.
auto withCharge(art::InputTag inputTag)
Adds additional recob::PointCharge information to the proxy.
Information about charge reconstructed in the active volume.
Base utilities for the implementation of data product facades.
Base representation of a collection of proxied objects.
GENVECTOR_CONSTEXPR::geo::Point_t makePointFromCoords(Coords &&coords)
Creates a geo::Point_t from its coordinates (see makeFromCoords()).
Proxy class for charged space point proxy elements.
std::vector< recob::SpacePoint > SpacePointDataProduct_t
Type of the main collection.
auto const & spacePoints() const
Returns the original collection of space points.
recob::SpacePoint const & point() const
Returns the original space point.
float Charge_t
Type for the amount of reconstructed charge.
Definition: PointCharge.h:35
auto ID() const
Returns the ID of the space point.
Proxy collection class for space points associated to charge.
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
geo::Point_t position() const
Returns the position of the space point.
An element of a collection proxy.
Proxy tag for a recob::SpacePoint collection with charge.
Definition: types.h:32
recob::PointCharge::Charge_t charge() const
QuadExpr operator*(double v, const QuadExpr &e)
Definition: QuadExpr.h:39
recob::PointCharge const & chargeInfo() const
auto const & charges() const
Returns the original collection of charge information.
Event finding and building.
Charge reconstructed in the active volume.
Definition: PointCharge.h:31