Belle II Software development
RelationArray.h
1/**************************************************************************
2 * basf2 (Belle II Analysis Software Framework) *
3 * Author: The Belle II Collaboration *
4 * *
5 * See git log for contributors and copyright holders. *
6 * This file is licensed under LGPL-3.0, see LICENSE.md. *
7 **************************************************************************/
8
9#pragma once
10
11#include <framework/datastore/DataStore.h>
12#include <framework/datastore/StoreAccessorBase.h>
13#include <framework/utilities/ArrayIterator.h>
14#include <framework/dataobjects/RelationElement.h>
15#include <framework/dataobjects/RelationContainer.h>
16#include <framework/logging/Logger.h>
17
18namespace Belle2 {
23 template <class T> class StoreArray;
24
63 public:
66
69
72
82 };
83
88 typedef std::pair<index_type, bool> consolidation_type;
89
94 struct Identity {
96 consolidation_type operator()(index_type old) const { return std::make_pair(old, false); }
97 };
98
104 template < class MapType = std::map<index_type, consolidation_type> > class ReplaceMap {
105 public:
106
108 explicit ReplaceMap(MapType& replace): m_replace(replace) {}
109
112 {
113 typename MapType::const_iterator iter = m_replace.find(old);
114 if (iter != m_replace.end()) {
115 return iter->second;
116 }
117 return std::make_pair(old, false);
118 }
119
120 private:
121
123 MapType& m_replace;
124 };
125
126
132 template < class VecType = std::vector<consolidation_type> > class ReplaceVec {
133 public:
134
136 explicit ReplaceVec(VecType& replace): m_replace(replace) {}
137
140
141 private:
142
144 VecType& m_replace;
145 };
146
147
153 bool create(bool replace = false)
154 {
155 bool result = DataStore::Instance().createObject(0, replace, *this);
156 m_relations = reinterpret_cast<RelationContainer**>(DataStore::Instance().getObject(*this));
157 if (result) {
158 (*m_relations)->setFromName(m_accessorFrom.first);
159 (*m_relations)->setFromDurability(m_accessorFrom.second);
160 (*m_relations)->setToName(m_accessorTo.first);
161 (*m_relations)->setToDurability(m_accessorTo.second);
162 }
163 return result;
164 }
165
178 template <class FROM, class TO> RelationArray(const StoreArray<FROM>& from, const StoreArray<TO>& to, const std::string& name = "",
180 StoreAccessorBase(name.empty() ? DataStore::relationName(from.getName(), to.getName()) : name, durability,
181 RelationContainer::Class(), false),
184 m_relations(0)
185 {
186 if (m_accessorFrom.second > m_durability || m_accessorTo.second > m_durability) {
187 B2FATAL("Tried to create RelationArray '" << m_name << "' with a durability larger than the StoreArrays it relates");
188 }
189 }
190
198 RelationArray(const AccessorParams& fromAccessor, const AccessorParams& toAccessor,
200 StoreAccessorBase(DataStore::relationName(fromAccessor.first, toAccessor.first), durability, RelationContainer::Class(), false),
201 m_accessorFrom(fromAccessor),
202 m_accessorTo(toAccessor),
203 m_relations(nullptr)
204 {
205 if (m_accessorFrom.second > m_durability || m_accessorTo.second > m_durability) {
206 B2FATAL("Tried to create RelationArray '" << m_name << "' with a durability larger than the StoreArrays it relates");
207 }
208 }
209
218 explicit RelationArray(const std::string& name, DataStore::EDurability durability = DataStore::c_Event):
219 StoreAccessorBase(name, durability, RelationContainer::Class(), false),
220 m_relations(0)
221 {
222 if (name.empty()) {
223 B2FATAL("Cannot guess relation name, please supply correct name");
224 }
225 }
226
229
234 inline bool isValid() const { ensureAttached(); return m_relations && *m_relations;}
236 inline operator bool() const { return isValid(); }
237
239 const RelationElement& operator[](int i) const { assertValid(); return (*m_relations)->getElement(i);}
240
242 int getEntries() const { return isValid() ? ((*m_relations)->getEntries()) : 0; }
243
246 {
248 if (m_accessorFrom.first.empty())
249 B2FATAL("trying to get accessor params from non-existing relation (this is likely a framework bug)");
250 return m_accessorFrom;
251 }
252
255 {
257 if (m_accessorTo.first.empty())
258 B2FATAL("trying to get accessor params from non-existing relation (this is likely a framework bug)");
259 return m_accessorTo;
260 }
261
263 bool getModified() const { assertValid(); return (*m_relations)->getModified(); }
264
266 void setModified(bool modified) { assertCreated(); (*m_relations)->setModified(modified); }
267
269 void clear() override
270 {
271 setModified(true);
272 (*m_relations)->elements().Delete();
273 }
274
281 void add(index_type from, index_type to, weight_type weight = 1.0)
282 {
283 setModified(true);
284 new (next()) RelationElement(from, to, weight);
285 }
286
293 void add(index_type from, const std::vector<index_type>& to, weight_type weight = 1.0)
294 {
295 setModified(true);
296 std::vector<weight_type> weights(to.size(), weight);
297 new (next()) RelationElement(from, to, weights);
298 }
299
306 void add(index_type from, const std::vector<index_type>& to, const std::vector<weight_type>& weights)
307 {
308 setModified(true);
309 new (next()) RelationElement(from, to, weights);
310 }
311
320 template <class InputIterator> void add(index_type from, const InputIterator& begin, const InputIterator& end)
321 {
322 setModified(true);
323 new (next()) RelationElement(from, begin, end);
324 }
325
331 void consolidate() { consolidate<Identity, Identity>(); }
332
363 template<class FunctionFrom, class FunctionTo> void consolidate(const
364 FunctionFrom& replaceFrom = FunctionFrom(), const FunctionTo &
365 replaceTo = FunctionTo(), EConsolidationAction action =
367
369 const_iterator begin() const { assertValid(); return const_iterator((*m_relations)->elements(), 0); }
371 const_iterator end() const { assertValid(); return const_iterator((*m_relations)->elements(), getEntries()); }
372
373 private:
381 explicit RelationArray(const AccessorParams& params):
382 StoreAccessorBase(params.first, params.second, RelationContainer::Class(), false),
383 m_relations(0)
384 {
385 if (params.first.empty()) {
386 B2FATAL("Cannot guess relation name, please supply correct name");
387 }
388 }
389
390
393 {
394 int index = (*m_relations)->elements().GetLast() + 1;
395 return static_cast<RelationElement*>((*m_relations)->elements().AddrAt(index));
396 }
397
399 void checkRelation(const std::string& direction, const AccessorParams& array, const AccessorParams& rel) const
400 {
401 if (array.second == 0 && array.first.empty())
402 return; //no information to check against...
403
404 if (array != rel) {
405 B2FATAL("Relation '" << m_name << "' exists but points " << direction << " wrong array:"
406 << " requested " << array.first << "(" << array.second << ")"
407 << ", got " << rel.first << "(" << rel.second << ")"
408 );
409 }
410 }
411
413 void ensureAttached() const
414 {
415 if (m_relations)
416 return;
417
418 const_cast<RelationArray*>(this)->m_relations = reinterpret_cast<RelationContainer**>(DataStore::Instance().getObject(*this));
419 if (m_relations && *m_relations && !(*m_relations)->isDefaultConstructed()) {
420 AccessorParams fromAccessorRel((*m_relations)->getFromName(), (DataStore::EDurability)(*m_relations)->getFromDurability());
421 AccessorParams toAccessorRel((*m_relations)->getToName(), (DataStore::EDurability)(*m_relations)->getToDurability());
422 //set if unset
423 if (m_accessorFrom.first.empty())
424 const_cast<RelationArray*>(this)->m_accessorFrom = fromAccessorRel;
425 if (m_accessorTo.first.empty())
426 const_cast<RelationArray*>(this)->m_accessorTo = toAccessorRel;
427 checkRelation("from", m_accessorFrom, fromAccessorRel);
428 checkRelation("to", m_accessorTo, toAccessorRel);
429 } else {
430 //no relation found, mark as invalid
431 const_cast<RelationArray*>(this)->m_relations = nullptr;
432 }
433 }
434
436 void assertValid() const { if (!isValid()) B2FATAL("RelationArray does not point to valid StoreObject"); }
437
443 {
444 if (!isValid()) {
445 if (!create()) {
446 B2FATAL("Couldn't create relation " << m_name << "!");
447 }
448 }
449 }
450
453
456
459
460 template<class FROM, class TO> friend class RelationIndex;
461 template<class FROM, class TO> friend class RelationIndexContainer;
462
463 };
464
465 template<class FunctionFrom, class FunctionTo>
466 void RelationArray::consolidate(const FunctionFrom& replaceFrom, const FunctionTo& replaceTo, EConsolidationAction action)
467 {
468 if (!isValid()) {
469 B2ERROR("Cannot consolidate an invalid relation (" << m_name << ")");
470 return;
471 }
472 typedef std::map<index_type, weight_type> element_t;
473 typedef std::map<index_type, element_t > buffer_t;
474 buffer_t buffer;
475
476 //Fill all existing elements in a nested map, adding the weights of
477 //duplicate elements
478 index_type lastFromIndex(0);
479 buffer_t::iterator lastFromIter = buffer.end();
480 unsigned int nElements = (*m_relations)->getEntries();
481 TClonesArray& elements = (*m_relations)->elements();
482 for (unsigned int i = 0; i < nElements; ++i) {
483 RelationElement& element = *static_cast<RelationElement*>(elements[i]);
484 //Replace from index
485 consolidation_type from = replaceFrom(element.getFromIndex());
486
487 //Ignore whole element if original element got deleted
488 if (action == c_deleteElement && from.second) continue;
489
490 //Check if the fromIndex is the same as the last one and reuse
491 //iterator if possible
492 if (from.first != lastFromIndex || lastFromIter == buffer.end()) {
493 lastFromIter = buffer.insert(make_pair(from.first, element_t())).first;
494 lastFromIndex = from.first;
495 }
496 //Loop over all elements of this relationelement and add them to the map
497 size_t size = element.getSize();
498 for (size_t j = 0; j < size; ++j) {
499 //Replace to Index
500 consolidation_type to = replaceTo(element.getToIndex(j));
501 //Ignore whole element if original element got deleted
502 if (action == c_deleteElement && to.second) continue;
503 double weight = element.getWeight(j);
504 //Original from or to element got deleted. Do whatever is specified by action
505 //Warning: if there is more than one element pointing to the same
506 //from->to element after transformation the negative weight option is
507 //not safe as we sum a positive and a negative weight when
508 //consolidating.
509 if (from.second || to.second) {
510 if (action == c_zeroWeight) {
511 weight = 0;
512 } else if (action == c_negativeWeight && weight > 0) {
513 weight = -weight;
514 }
515 }
516 //add the weight to the new from->to index pair
517 lastFromIter->second[to.first] += weight;
518 }
519 }
520 //Clear the existing relation
521 elements.Delete();
522 //Fill the map into the relation
523 for (buffer_t::iterator iter = buffer.begin(); iter != buffer.end(); ++iter) {
524 add(iter->first, iter->second.begin(), iter->second.end());
525 }
526 }
527
529} // end namespace Belle2
In the store you can park objects that have to be accessed by various modules.
Definition: DataStore.h:51
EDurability
Durability types.
Definition: DataStore.h:58
@ c_Event
Different object in each event, all objects/arrays are invalidated after event() function has been ca...
Definition: DataStore.h:59
static DataStore & Instance()
Instance of singleton Store.
Definition: DataStore.cc:54
bool createObject(TObject *object, bool replace, const StoreAccessorBase &accessor)
Create a new object/array in the DataStore or add an existing one.
Definition: DataStore.cc:316
TObject ** getObject(const StoreAccessorBase &accessor)
Get a pointer to a pointer of an object in the DataStore.
Definition: DataStore.cc:306
Optimizes class to iterate over TObjArray and classes inheriting from it.
Definition: ArrayIterator.h:23
Struct to replace indices based on a map-like container.
ReplaceMap(MapType &replace)
Set reference to used replacement map.
consolidation_type operator()(index_type old) const
Take old index and return the new index.
MapType & m_replace
Reference of the used replacement map.
Struct to replace indices based on a sequential container.
VecType & m_replace
Reference of the used replacement vector.
consolidation_type operator()(index_type old) const
Take old index and return the new index.
ReplaceVec(VecType &replace)
Set reference to used replacement vector.
Low-level class to create/modify relations between StoreArrays.
Definition: RelationArray.h:62
const AccessorParams & getFromAccessorParams() const
Return the AccessorParams the attached relation points from.
bool getModified() const
Get modified flag of underlying container.
ObjArrayIterator< const TClonesArray, const RelationElement > const_iterator
STL-like const_iterator over the T objects (not T* ).
Definition: RelationArray.h:65
const_iterator begin() const
Return const_iterator to first entry.
AccessorParams m_accessorTo
Accessor params for to array.
RelationArray(const StoreArray< FROM > &from, const StoreArray< TO > &to, const std::string &name="", DataStore::EDurability durability=DataStore::c_Event)
Constructor which takes both store arrays and performs some sanity checks on the relation.
const AccessorParams & getToAccessorParams() const
Return the AccessorParams the attached relation points to.
void checkRelation(const std::string &direction, const AccessorParams &array, const AccessorParams &rel) const
Check that the AccessorParams stored in the relation and the one given to the constructor are the sam...
RelationContainer ** m_relations
Pointer that actually holds the relations.
RelationElement * next()
Return address where the next RelationElement should be created.
void ensureAttached() const
Attach to relation, if necessary.
void add(index_type from, const std::vector< index_type > &to, weight_type weight=1.0)
Add a new element to the relation.
bool isValid() const
Check whether the object was created.
std::pair< index_type, bool > consolidation_type
Typedef declaring the return value of any consolidation mapping.
Definition: RelationArray.h:88
void consolidate()
Consolidate Relation Elements.
RelationElement::index_type index_type
Typedef to simplify use of correct index_type.
Definition: RelationArray.h:68
EConsolidationAction
Modification actions for the consolidate member.
Definition: RelationArray.h:77
@ c_negativeWeight
Flip the sign of the weight to become negative if the original element got re-attributed.
Definition: RelationArray.h:79
@ c_zeroWeight
Set the weight of the relation to 0 if the original element got re-attributed.
Definition: RelationArray.h:80
@ c_deleteElement
Delete the whole relation element if the original element got re-attributed.
Definition: RelationArray.h:81
@ c_doNothing
Do nothing, just treat it as reordering.
Definition: RelationArray.h:78
~RelationArray()
Empty destructor.
void setModified(bool modified)
Set modified flag of underlying container.
void add(index_type from, const InputIterator &begin, const InputIterator &end)
Add a new element to the relation.
void add(index_type from, const std::vector< index_type > &to, const std::vector< weight_type > &weights)
Add a new element to the relation.
int getEntries() const
Get the number of elements.
void add(index_type from, index_type to, weight_type weight=1.0)
Add a new element to the relation.
RelationElement::weight_type weight_type
Typedef to simplify use of correct weight_type.
Definition: RelationArray.h:71
RelationArray(const AccessorParams &fromAccessor, const AccessorParams &toAccessor, DataStore::EDurability durability=DataStore::c_Event)
Constructor with AccessorParams for from- and to-side.
RelationArray(const AccessorParams &params)
Constructor which accepts the AccessorParams of the relation.
RelationArray(const std::string &name, DataStore::EDurability durability=DataStore::c_Event)
Constructor which only accepts name and durability of the relation.
const_iterator end() const
Return const_iterator to last entry +1.
void assertCreated()
Create relation, if necessary.
bool create(bool replace=false)
Create an empty relation array in the data store.
AccessorParams m_accessorFrom
Accessor params for from array.
void clear() override
Clear all elements from the relation.
const RelationElement & operator[](int i) const
Imitate array functionality.
void assertValid() const
check that pointer exits, otherwise bail out.
Class to store relations between StoreArrays in the DataStore.
bool isDefaultConstructed() const
Returns true if no information was set yet or Clear() was called.
void setFromName(const std::string &name)
Set name of the StoreArray we relate from.
Class to store a single element of a relation.
unsigned int index_type
type used for indices.
float weight_type
type used for weights.
Class to store a bidirectional index between two StoreArrays.
Provides access to fast ( O(log n) ) bi-directional lookups on a specified relation.
Definition: RelationIndex.h:76
Base class for StoreObjPtr and StoreArray for easier common treatment.
DataStore::EDurability m_durability
Store durability under which the object/array is saved.
const std::string & getName() const
Return name under which the object is saved in the DataStore.
AccessorParams getAccessorParams() const
Return pair of name and durability under which stored object is saved.
std::string m_name
Store name under which this object/array is saved.
Accessor to arrays stored in the data store.
Definition: StoreArray.h:113
std::pair< std::string, DataStore::EDurability > AccessorParams
Pair of parameters needed to find an object in the DataStore.
Abstract base class for different kinds of events.
Struct for identity transformation on indices.
Definition: RelationArray.h:94
consolidation_type operator()(index_type old) const
Take old index and return the new index.
Definition: RelationArray.h:96