18 #include <unordered_map>
23 #include "messagefacility/MessageLogger/MessageLogger.h"
24 #include "canvas/Utilities/Exception.h"
25 #include "canvas/Utilities/InputTag.h"
26 #include "canvas/Persistency/Common/Ptr.h"
27 #include "canvas/Persistency/Common/Assns.h"
28 #include "canvas/Persistency/Provenance/ProductID.h"
29 #include "art/Framework/Principal/Event.h"
64 template <
typename Source,
typename Dest>
81 = std::unordered_map<art::ProductID, InProductCache_t, Hash_t>;
95 {
return AssnCache[src.id()][src.key()]; }
116 template <
typename Source,
typename Dest>
130 {
Read(event, assnTag); }
138 art::Ptr<Dest_t>
const&
operator[] (art::Ptr<Dest_t>
const& src)
const;
142 bool hasProduct(art::ProductID
const&
id)
const;
145 bool hasProduct(art::Ptr<Source_t>
const& ptr)
const;
152 unsigned int Read(art::Event& event);
165 unsigned int Read(art::Event& event, art::InputTag
const& assnTag);
181 unsigned int Add(art::Event& event, art::InputTag
const& assnTag);
193 unsigned int Merge(art::Handle<Assns_t>& handle);
208 template <
typename T>
228 template <
typename Source,
typename Dest>
229 auto FindAllP<Source, Dest>::operator[]
230 (art::Ptr<Dest_t>
const& src)
const -> art::Ptr<Dest_t>
const&
234 return cache.AssnCache.at(src.id()).at(src.key());
236 catch (std::out_of_range) {
242 template <
typename Source,
typename Dest>
244 (art::ProductID
const&
id)
const
245 {
return cache.AssnCache.count(
id) > 0; }
248 template <
typename Source,
typename Dest>
250 (art::Ptr<Source_t>
const& ptr)
const
251 {
return hasProduct(ptr.id()); }
254 template <
typename Source,
typename Dest>
262 auto assns_list =
event.getMany<
Assns_t>();
264 MF_LOG_DEBUG(
"FindAllP") <<
"Read(): read " << assns_list.size()
265 <<
" association sets";
267 unsigned int count = 0;
269 for (art::Handle<Assns_t> handle: assns_list)
270 count += Merge(handle);
272 MF_LOG_DEBUG(
"FindAllP") <<
"Read " << count <<
" associations for "
273 << cache.NProductIDs() <<
" product IDs";
280 template <
typename Source,
typename Dest>
282 (art::Event& event, art::InputTag
const& assnTag)
285 return Add(event, assnTag);
290 template <
typename Source,
typename Dest>
292 (art::Event& event, art::InputTag
const& assnTag)
296 art::Handle<Assns_t> handle;
297 if (!event.getByLabel(assnTag, handle)) {
298 throw art::Exception(art::errors::ProductNotFound)
299 <<
"no association found with input tag '" << assnTag <<
"'";
302 return Merge(handle);
306 template <
typename Source,
typename Dest>
308 (art::Handle<Assns_t>& handle)
311 art::ProductID LastProductID = art::Ptr<Source_t>().
id();
314 unsigned int count = 0;
316 MF_LOG_DEBUG(
"FindAllP") <<
"Merge(): importing " << handle->size()
317 <<
" associations from " << handle.provenance();
319 for (
auto const& assn: *handle) {
321 art::Ptr<Source_t>
const& src = assn.first;
324 MF_LOG_ERROR(
"FindAllP") <<
"Empty pointer found in association "
325 << handle.provenance();
329 art::Ptr<Dest_t>
const& dest = assn.second;
333 if (src.id() != LastProductID) {
334 LastProductID = src.id();
335 AssnsList = &(cache.AssnCache[LastProductID]);
338 if (AssnsList->empty()) {
348 typename art::Ptr<Source_t>::key_type key = src.key();
349 if (key >= AssnsList->size())
ResizeToPower2(*AssnsList, key + 1);
352 art::Ptr<Dest_t>& dest_cell = (*AssnsList)[key];
353 if (dest_cell.isNonnull() && (dest_cell != dest)) {
354 throw art::Exception(art::errors::InvalidNumber)
355 <<
"Object Ptr" << src
356 <<
" is associated with at least two objects: "
357 << dest <<
" and " << dest_cell;
363 MF_LOG_DEBUG(
"FindAllP")
364 <<
"Merged " << count <<
" associations from " << handle.provenance();
393 template <
typename T>
400 while (new_size < min_size) new_size *= 2;
411 #endif // FINDALLP_H 1
FindAllP(art::Event &event, art::InputTag assnTag)
Constructor: reads one association from the specified event.
unsigned int Merge(art::Handle< Assns_t > &handle)
Adds all associations in the specified handle; returns their number.
bool hasProduct(art::ProductID const &id) const
Returns whether there are associations from objects in product id.
A class holding many associations between objects.
DestPtr_t operator[](SourcePtr_t const &src) const
Returns the specified element of the cache.
void clear()
Empties the cache.
result_type operator()(argument_type const &v) const
art::Ptr< Dest_t > DestPtr_t
Cache_t AssnCache
association cache, keyed by product ID and index
FindAllP()=default
Default constructor: empty query, read information with Read()
Cache_t cache
set of associations, keyed by product ID and key
FindAllP(art::Event &event)
Constructor: reads all associations from the specified event.
std::vector< DestPtr_t > InProductCache_t
type for a cache of dest products for a given source product ID
unsigned int Add(art::Event &event, art::InputTag const &assnTag)
Reads the specified association from the event.
unsigned int Read(art::Event &event)
Reads all the associations from the event.
Query object reading all the associations between two classes.
void ResizeToPower2(std::vector< T > &v, size_t min_size)
Resizes a vector to a size power of 2, with a minimum size.
art::Ptr< Source_t > SourcePtr_t
art::Assns< Source_t, Dest_t > Assns_t
Hash functions for art and larsoft objects.
std::unordered_map< art::ProductID, InProductCache_t, Hash_t > Cache_t
type for the complete cache, keyed by source product ID
size_t NProductIDs() const
std::size_t count(Cont const &cont)
art::Ptr< Dest_t > const & operator[](art::Ptr< Dest_t > const &src) const
Returns the object associated to the specified one.
UniqueAssociationCache()=default
Constructor: an empty cache.