LArSoft  v09_90_00
Liquid Argon Software toolkit - https://larsoft.org/
FindAllP.h
Go to the documentation of this file.
1 
11 #ifndef FINDALLP_H
12 #define FINDALLP_H 1
13 
14 // C/C++ standard libraries
15 #include <climits> // CHAR_BIT
16 #include <functional> // std::hash<>
17 #include <stdexcept> // std::out_of_range
18 #include <unordered_map>
19 #include <vector>
20 
21 // framework libraries
29 
31 namespace lar {
32 
34  namespace util {
35 
37  namespace details {
38 
40  template <typename T>
41  struct hash {
42  using result_type = size_t;
43  using argument_type = T;
44 
45  result_type operator()(argument_type const& v) const;
46 
47  }; // class hash<>
48 
60  template <typename Source, typename Dest>
62  public:
63  using Source_t = Source;
64  using Dest_t = Dest;
65 
68 
70  using InProductCache_t = std::vector<DestPtr_t>;
71 
74 
76  using Cache_t = std::unordered_map<art::ProductID, InProductCache_t, Hash_t>;
77 
79 
81  UniqueAssociationCache() = default;
82 
88  DestPtr_t operator[](SourcePtr_t const& src) const
89  {
90  return AssnCache[src.id()][src.key()];
91  }
92 
94  void clear() { AssnCache.clear(); }
95 
96  size_t NProductIDs() const { return AssnCache.size(); }
97 
98  }; // class UniqueAssociationCache<>
99 
111  template <typename Source, typename Dest>
112  class FindAllP {
113  public:
114  using Source_t = Source;
115  using Dest_t = Dest;
116 
118  FindAllP() = default;
119 
122 
124  FindAllP(art::Event& event, art::InputTag assnTag) : FindAllP() { Read(event, assnTag); }
125 
131  art::Ptr<Dest_t> const& operator[](art::Ptr<Dest_t> const& src) const;
132 
134  bool hasProduct(art::ProductID const& id) const;
135 
137  bool hasProduct(art::Ptr<Source_t> const& ptr) const;
138 
144  unsigned int Read(art::Event& event);
145 
157  unsigned int Read(art::Event& event, art::InputTag const& assnTag);
158 
172  unsigned int Add(art::Event& event, art::InputTag const& assnTag);
173 
174  protected:
176 
179 
181 
183  unsigned int Merge(art::Handle<Assns_t>& handle);
184  }; // class FindAllP<>
185 
195  template <typename T>
196  void ResizeToPower2(std::vector<T>& v, size_t min_size);
197 
198  } // namespace details
199  } // namespace util
200 } // namespace lar
201 
202 //******************************************************************************
203 //*** Template implementation
204 //******************************************************************************
205 
206 namespace lar {
207  namespace util {
208  namespace details {
209  //------------------------------------------------------------------------
210  //--- FindAllP
211 
212  template <typename Source, typename Dest>
214  -> art::Ptr<Dest_t> const&
215  {
216  // we expect a missing match to be exceptional
217  try {
218  return cache.AssnCache.at(src.id()).at(src.key());
219  }
220  catch (std::out_of_range) {
221  return {};
222  }
223  } // FindAllP<>::operator[]
224 
225  template <typename Source, typename Dest>
227  {
228  return cache.AssnCache.count(id) > 0;
229  }
230 
231  template <typename Source, typename Dest>
233  {
234  return hasProduct(ptr.id());
235  }
236 
237  template <typename Source, typename Dest>
239  {
240 
241  // read all the associations between source and destination class types
242  //std::vector<art::Handle<Assns_t>> assns_list;
243  //event.getManyByType(assns_list);
244  auto assns_list = event.getMany<Assns_t>();
245 
246  MF_LOG_DEBUG("FindAllP") << "Read(): read " << assns_list.size() << " association sets";
247 
248  unsigned int count = 0;
249  // parse all the associations, and translate them into a local cache
250  for (art::Handle<Assns_t> handle : assns_list)
251  count += Merge(handle);
252 
253  MF_LOG_DEBUG("FindAllP") << "Read " << count << " associations for " << cache.NProductIDs()
254  << " product IDs";
255 
256  return count;
257  } // FindAllP::Read(Event)
258 
259  template <typename Source, typename Dest>
261  {
262  cache.clear();
263  return Add(event, assnTag);
264  } // FindAllP::Read(Event, InputTag)
265 
266  template <typename Source, typename Dest>
268  {
269 
270  // read the association between source and destination class types
271  art::Handle<Assns_t> handle;
272  if (!event.getByLabel(assnTag, handle)) {
274  << "no association found with input tag '" << assnTag << "'";
275  }
276 
277  return Merge(handle);
278  } // FindAllP::Add(Event, InputTag)
279 
280  template <typename Source, typename Dest>
282  {
283  // product ID of the last source object; initialized invalid
284  art::ProductID LastProductID = art::Ptr<Source_t>().id();
285  typename Cache_t::InProductCache_t const* AssnsList = nullptr;
286 
287  unsigned int count = 0;
288 
289  MF_LOG_DEBUG("FindAllP") << "Merge(): importing " << handle->size() << " associations from "
290  << handle.provenance();
291 
292  for (auto const& assn : *handle) {
293  // assn is a std::pair<art::Ptr<Source_t>, art::Ptr<Dest_t>>
294  art::Ptr<Source_t> const& src = assn.first;
295 
296  if (src.isNull()) {
297  MF_LOG_ERROR("FindAllP")
298  << "Empty pointer found in association " << handle.provenance();
299  continue; // this should not happen
300  }
301 
302  art::Ptr<Dest_t> const& dest = assn.second;
303 
304  // if we have changed product (that should be fairly rare),
305  // update the running pointers
306  if (src.id() != LastProductID) {
307  LastProductID = src.id();
308  AssnsList = &(cache.AssnCache[LastProductID]);
309 
310  // if the list is empty, it means we have just created it!
311  if (AssnsList->empty()) {
312  // allocate enough space to accomodate all the associations,
313  // (provided that source IDs are sequencial);
314  // in fact typically all the associations in the same handle
315  // have the same product ID
316  ResizeToPower2(*AssnsList, handle->size());
317  }
318  } // if different product ID
319 
320  // make sure there is enough room in the vector
321  typename art::Ptr<Source_t>::key_type key = src.key();
322  if (key >= AssnsList->size()) ResizeToPower2(*AssnsList, key + 1);
323 
324  // store the association to dest
325  art::Ptr<Dest_t>& dest_cell = (*AssnsList)[key];
326  if (dest_cell.isNonnull() && (dest_cell != dest)) {
328  << "Object Ptr" << src << " is associated with at least two objects: " << dest
329  << " and " << dest_cell;
330  }
331  dest_cell = dest;
332  ++count;
333  } // for all associations in a list
334 
335  MF_LOG_DEBUG("FindAllP") << "Merged " << count << " associations from "
336  << handle.provenance();
337  return count;
338  } // FindAllP::Merge()
339 
340  //------------------------------------------------------------------------
341  template <>
343  {
344  // make sure we have enough bits in result_type;
345  // if not, we need a more clever algorithm
346  //static_assert(
347  // sizeof(id.processIndex()) + sizeof(id.productIndex())
348  // <= sizeof(result_type),
349  // "hash return type not large enough for hashing art::ProductID"
350  //);
351  // stack the process and product IDs in one integer
352  //return result_type(
353  //(id.processIndex() << sizeof(id.productIndex() * CHAR_BIT))
354  //+ id.productIndex()
355  //);
356  return result_type(id.value());
357  } // hash<art::ProductID>::operator()
358 
359  //------------------------------------------------------------------------
360  template <typename T>
361  void ResizeToPower2(std::vector<T>& v, size_t min_size)
362  {
363  if (min_size == 0) {
364  v.clear();
365  return;
366  }
367  size_t new_size = 1;
368  while (new_size < min_size)
369  new_size *= 2;
370 
371  v.resize(new_size);
372  } // ResizeToPower2()
373 
374  } // namespace details
375  } // namespace util
376 } // namespace lar
377 
378 //------------------------------------------------------------------------------
379 #endif // FINDALLP_H 1
Namespace for general, non-LArSoft-specific utilities.
Definition: PIDAAlg.h:26
FindAllP(art::Event &event, art::InputTag assnTag)
Constructor: reads one association from the specified event.
Definition: FindAllP.h:124
unsigned int Merge(art::Handle< Assns_t > &handle)
Adds all associations in the specified handle; returns their number.
Definition: FindAllP.h:281
Read("Flexi","livermore")
bool hasProduct(art::ProductID const &id) const
Returns whether there are associations from objects in product id.
Definition: FindAllP.h:226
A class holding many associations between objects.
Definition: FindAllP.h:61
DestPtr_t operator[](SourcePtr_t const &src) const
Returns the specified element of the cache.
Definition: FindAllP.h:88
#define MF_LOG_ERROR(category)
void clear()
Empties the cache.
Definition: FindAllP.h:94
result_type operator()(argument_type const &v) const
std::size_t key_type
Definition: Ptr.h:78
Cache_t AssnCache
association cache, keyed by product ID and index
Definition: FindAllP.h:78
Provenance const * provenance() const
Definition: Handle.h:217
Cache_t cache
set of associations, keyed by product ID and key
Definition: FindAllP.h:180
key_type key() const noexcept
Definition: Ptr.h:166
bool isNull() const noexcept
Definition: Ptr.h:211
FindAllP(art::Event &event)
Constructor: reads all associations from the specified event.
Definition: FindAllP.h:121
std::vector< DestPtr_t > InProductCache_t
type for a cache of dest products for a given source product ID
Definition: FindAllP.h:70
ProductID id() const noexcept
Definition: Ptr.h:160
unsigned int Add(art::Event &event, art::InputTag const &assnTag)
Reads the specified association from the event.
Definition: FindAllP.h:267
unsigned int Read(art::Event &event)
Reads all the associations from the event.
Definition: FindAllP.h:238
double value
Definition: spectrum.C:18
Query object reading all the associations between two classes.
Definition: FindAllP.h:112
void ResizeToPower2(std::vector< T > &v, size_t min_size)
Resizes a vector to a size power of 2, with a minimum size.
Definition: FindAllP.h:361
cet::coded_exception< errors::ErrorCodes, ExceptionDetail::translate > Exception
Definition: Exception.h:66
bool isNonnull() const noexcept
Definition: Ptr.h:204
bool getByLabel(std::string const &label, std::string const &instance, Handle< PROD > &result) const
LArSoft-specific namespace.
Hash functions for art and larsoft objects.
Definition: FindAllP.h:41
#define MF_LOG_DEBUG(id)
std::unordered_map< art::ProductID, InProductCache_t, Hash_t > Cache_t
type for the complete cache, keyed by source product ID
Definition: FindAllP.h:76
art::Ptr< Dest_t > const & operator[](art::Ptr< Dest_t > const &src) const
Returns the object associated to the specified one.
Definition: FindAllP.h:213
Definition: fwd.h:26
Event finding and building.