All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
OneTo01Data.h
Go to the documentation of this file.
1 /**
2  * @file lardata/RecoBaseProxy/ProxyBase/OneTo01Data.h
3  * @brief Auxiliary data from one-to-(zero-or-one) sequential association.
4  * @author Gianluca Petrillo (petrillo@fnal.gov)
5  * @date July 27, 2017
6  * @see lardata/RecoBaseProxy/ProxyBase.h
7  *
8  * This library is header-only.
9  */
10 
11 #ifndef LARDATA_RECOBASEPROXY_PROXYBASE_ONETO01DATA_H
12 #define LARDATA_RECOBASEPROXY_PROXYBASE_ONETO01DATA_H
13 
14 // LArSoft libraries
16 #include "lardata/Utilities/TupleLookupByTag.h" // util::add_tag_t(), ...
17 
18 // framework libraries
19 #include "canvas/Persistency/Common/Assns.h"
20 #include "canvas/Persistency/Common/Ptr.h"
21 
22 // C/C++ standard
23 #include <vector>
24 #include <tuple> // std::tuple_element_t<>, std::get()
25 #include <iterator> // std::cbegin(), std::cend()
26 #include <utility> // std::move()
27 #include <type_traits> // std::is_convertible<>
28 #include <cstdlib> // std::size_t
29 
30 
31 namespace proxy {
32 
33  namespace details {
34 
35  /**
36  * @brief Object for one-to-zero/or/one associated data interface.
37  * @tparam Main type of the main associated object (one)
38  * @tparam Aux type of the additional associated objects (zero or one)
39  * @tparam Metadata type of associated metadata
40  * @tparam Tag tag this data is labeled with
41  *
42  * Allows:
43  * * random access (no index check guarantee)
44  * * forward iteration
45  *
46  * Construction is not part of the interface.
47  *
48  * The `OneTo01Data` object acquires a vector of _art_ pointers, one for
49  * each element in the main collection.
50  * It is an implementation detail for associations fulfilling the
51  * @ref LArSoftProxyDefinitionOneToZeroOrOneSeqAssn "one-to-(zero-or-one) sequential association"
52  * requirement.
53  *
54  * @note This data structure marks the main elements which have no
55  * associated data with an invalid _art_ pointer (default-constructed)
56  * and it does not distinguish that from the element being actually
57  * associated to a default-constructed _art_ pointer.
58  *
59  * The `OneTo01Data` object also provides a container-like view of this
60  * information, where each element in the container is associated to a
61  * single `Main` and it is an _art_ pointer to the `Right` element.
62  *
63  * Association metadata is not accessible from this object.
64  *
65  * @todo Metadata for `proxy::details::OneTo01Data` is not supported yet.
66  */
67  template <
68  typename Main, typename Aux, typename Metadata /* = void */,
69  typename Tag /* = Aux */
70  >
71  class OneTo01Data {
73 
74  public:
75  /// Type of associated datum.
76  using aux_t = Aux;
77 
78  /// Type of associated metadata.
79  using metadata_t = Metadata;
80 
81  /// Type of tag.
82  using tag = Tag;
83 
84  /// Type of main datum.
85  using main_t = Main;
86 
87  /// Type of _art_ pointer to associated datum.
88  using aux_ptr_t = art::Ptr<aux_t>;
89 
90  /// Type of auxiliary data associated with a main item.
92 
93  /// Type of collection of auxiliary data for all main elements.
94  using aux_coll_t = std::vector<aux_ptr_t>;
95 
96  /// Type of the source association.
97  using assns_t = art::Assns<main_t, aux_t>;
98 
99 
100  OneTo01Data(aux_coll_t&& data): auxData(std::move(data)) {}
101 
102  /// Returns whether the element `i` is associated with auxiliary datum.
103  bool has(std::size_t i) const
104  { return get(i) == aux_ptr_t(); }
105 
106  /// Returns a copy of the pointer to data associated with element `i`.
107  auxiliary_data_t get(std::size_t i) const
108  { return auxiliary_data_t(auxData[i]); }
109 
110 
111  /// Returns the range with the specified index (no check performed).
112  auto operator[] (std::size_t index) const -> decltype(auto)
113  {
114  static_assert(
115  std::is_convertible<decltype(get(index)), auxiliary_data_t>(),
116  "Inconsistent data types."
117  );
118  return get(index);
119  }
120 
121  private:
122  aux_coll_t auxData; ///< Data associated to the main collection.
123 
124  }; // class OneTo01Data<>
125 
126  } // namespace details
127 
128 
129  //@{
130  /**
131  * @brief Processes and returns an one-to-(zero/one) associated data object.
132  * @tparam Tag the tag labelling this associated data
133  * (if omitted: second type of the association: `right_t`)
134  * @tparam Assns type of association to be processed
135  * @param assns association object to be processed
136  * @param minSize minimum number of entries in the produced association data
137  * @return a new `OneTo01Data` filled with associations from `tag`
138  *
139  * The content of the association object must fulfill the requirements of
140  * @ref LArSoftProxyDefinitionOneToZeroOrOneSeqAssn "one-to-(zero or one) sequential association".
141  * The `Assns` type is expected to be a `art::Assns` instance. At least,
142  * the `Assns` type is required to have `left_t` and `right_t` definitions
143  * representing respectively the main data type and the associated one, and
144  * to respond to `begin()` and `end()` functions. The iterated object must
145  * also respond to `std::get<0>()` with a `art::Ptr<left_t>` and to
146  * `std::get<1>()` with a `art::Ptr<right_t>`.
147  *
148  * Elements in the main collection not associated with any object will present
149  * an invalid _art_ pointer (`isNull()` true). If there is information for
150  * less than `minSize` main objects, more records will be added to mark the
151  * missing objects as not associated to anything.
152  *
153  * Example:
154  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
155  * art::Assns<recob::Track, recob::Vertex> trackVertexAssns;
156  * // ...
157  * auto assData = proxy::makeOneTo01data(assns);
158  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
159  * will have `assData` tagged as `recob::Vertex`.
160  *
161  * If `Tag` type is omitted, the class to the right side of the association
162  * is used as tag.
163  */
164  template <typename Tag, typename Assns>
165  auto makeOneTo01data(Assns const& assns, std::size_t minSize = 0);
166 
167  template <typename Assns>
168  auto makeOneTo01data(Assns const& assns, std::size_t minSize = 0)
169  { return makeOneTo01data<typename Assns::right_t>(assns, minSize); }
170  //@}
171 
172  //@{
173  /**
174  * @brief Creates and returns an one-to-(zero/one) associated data object.
175  * @tparam Tag the tag labelling this associated data
176  * (if omitted: second type of the association: `right_t`)
177  * @tparam MainColl type of the main collection object
178  * @tparam Assns type of the association object
179  * @param mainColl the main collection object
180  * @param assns association data object
181  * @return a new `OneTo01Data` wrapping the information in `assns`
182  * @see `makeOneTo01data(Assns const&, std::size_t)`
183  *
184  * This function operates like
185  * `makeOneTo01data(Assns const&, std::size_t)`, where the size is
186  * extracted from the main data collection.
187  *
188  * If `Tag` type is omitted, the class to the right side of the association
189  * is used as tag.
190  */
191  template <typename Tag, typename MainColl, typename Assns>
192  auto makeOneTo01data(MainColl const& mainColl, Assns const& assns)
193  { return makeOneTo01data<Tag>(assns, mainColl.size()); }
194 
195  template <typename MainColl, typename Assns>
196  auto makeOneTo01data(MainColl const& mainColl, Assns const& assns)
197  { return makeOneTo01data<typename Assns::right_t>(mainColl, assns); }
198  //@}
199 
200 } // namespace proxy
201 
202 
203 //------------------------------------------------------------------------------
204 //--- template implementation
205 //------------------------------------------------------------------------------
206 namespace proxy {
207 
208  namespace details {
209 
210  //--------------------------------------------------------------------------
211  // Extends vector v with default-constructed data
212  // and executes v[index]=value
213  template <typename T>
215  std::vector<T>& v,
216  typename std::vector<T>::size_type index,
217  typename std::vector<T>::value_type const& value
218  ) {
219  if (index >= v.size()) {
220  v.reserve(index + 1);
221  v.resize(index);
222  v.push_back(value);
223  }
224  else v[index] = value;
225  } // extendAndAssign()
226 
227  // Extends vector v with default-constructed data
228  // and executes v[index]=move(value)
229  template <typename T>
231  std::vector<T>& v,
232  typename std::vector<T>::size_type index,
233  typename std::vector<T>::value_type&& value
234  ) {
235  if (index >= v.size()) {
236  v.reserve(index + 1);
237  v.resize(index);
238  v.push_back(std::move(value));
239  }
240  else v[index] = std::move(value);
241  } // extendAndAssign()
242 
243 
244  //--------------------------------------------------------------------------
245  template <std::size_t Key, std::size_t Data, typename Iter>
246  auto associationOneToOneFullSequence(Iter begin, Iter end, std::size_t n) {
247  //
248  // Here we are actually not using the assumption that the keys are in
249  // increasing order; which is just as good as long as we use a fast random
250  // access container as STL vector.
251  // We do assume the key side of the association to be valid, though.
252  //
253  using value_type = typename Iter::value_type;
254  using data_t = std::tuple_element_t<Data, value_type>;
255  std::vector<data_t> data(n); // all default-constructed
256  for (auto it = begin; it != end; ++it) {
257  auto const& keyPtr = std::get<Key>(*it);
258  extendAndAssign(data, keyPtr.key(), std::get<Data>(*it));
259  }
260  return data;
261  } // associationOneToOneFullSequence(Iter, Iter, std::size_t)
262 
263  } // namespace details
264 
265 
266  //----------------------------------------------------------------------------
267  //--- makeOneTo01data() implementation
268  //----------------------------------------------------------------------------
269  template <typename Tag, typename Assns>
270  auto makeOneTo01data(Assns const& assns, std::size_t minSize /* = 0 */)
271  {
272  using Main_t = typename Assns::left_t;
273  using Aux_t = typename Assns::right_t;
274  using Metadata_t = lar::util::assns_metadata_t<Assns>;
275  using AssociatedData_t
277 
278  using std::cbegin;
279  using std::cend;
280  return AssociatedData_t(
281  details::associationOneToOneFullSequence<0U, 1U>
282  (cbegin(assns), cend(assns), minSize)
283  );
284  } // makeOneTo01data(assns)
285 
286  //----------------------------------------------------------------------------
287 
288 } // namespace proxy
289 
290 
291 #endif // LARDATA_RECOBASEPROXY_PROXYBASE_ONETO01DATA_H
double std(const std::vector< short > &wf, const double ped_mean, size_t start, size_t nsample)
Definition: UtilFunc.cxx:42
auto makeOneTo01data(Assns const &assns, std::size_t minSize=0)
Processes and returns an one-to-(zero/one) associated data object.
Definition: OneTo01Data.h:270
art::Assns< main_t, aux_t > assns_t
Type of the source association.
Definition: OneTo01Data.h:97
art::Ptr< aux_t > aux_ptr_t
Type of art pointer to associated datum.
Definition: OneTo01Data.h:88
bool has(std::size_t i) const
Returns whether the element i is associated with auxiliary datum.
Definition: OneTo01Data.h:103
typename assns_metadata_type< Assns >::type assns_metadata_t
Trait: type of metadata in Assns (association or its node).
Definition: AssnsTraits.h:62
auto cbegin(FixedBins< T, C > const &) noexcept
Definition: FixedBins.h:567
OneTo01Data(aux_coll_t &&data)
Definition: OneTo01Data.h:100
Main main_t
Type of main datum.
Definition: OneTo01Data.h:85
typename add_tag< T, Tag >::type add_tag_t
auto cend(FixedBins< T, C > const &) noexcept
Definition: FixedBins.h:579
Tag tag
Type of tag.
Definition: OneTo01Data.h:82
auto operator[](std::size_t index) const -> decltype(auto)
Returns the range with the specified index (no check performed).
Definition: OneTo01Data.h:112
Object for one-to-zero/or/one associated data interface.
Definition: OneTo01Data.h:71
auto end(FixedBins< T, C > const &) noexcept
Definition: FixedBins.h:585
Aux aux_t
Type of associated datum.
Definition: OneTo01Data.h:76
auto begin(FixedBins< T, C > const &) noexcept
Definition: FixedBins.h:573
Utilities to address elements of a tuple-like class by tag.
Traits for art associations.
Metadata metadata_t
Type of associated metadata.
Definition: OneTo01Data.h:79
void extendAndAssign(std::vector< T > &v, typename std::vector< T >::size_type index, typename std::vector< T >::value_type const &value)
Definition: OneTo01Data.h:214
temporary value
std::vector< aux_ptr_t > aux_coll_t
Type of collection of auxiliary data for all main elements.
Definition: OneTo01Data.h:94
aux_coll_t auxData
Data associated to the main collection.
Definition: OneTo01Data.h:122
util::add_tag_t< aux_ptr_t, tag > auxiliary_data_t
Type of auxiliary data associated with a main item.
Definition: OneTo01Data.h:91
auto associationOneToOneFullSequence(Iter begin, Iter end, std::size_t n)
Definition: OneTo01Data.h:246