Belle II Software prerelease-10-00-00a
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
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
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:53
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:315
TObject ** getObject(const StoreAccessorBase &accessor)
Get a pointer to a pointer of an object in the DataStore.
Definition DataStore.cc:305
Optimizes class to iterate over TObjArray and classes inheriting from it.
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.
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.
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* ).
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.
void consolidate()
Consolidate Relation Elements.
RelationElement::index_type index_type
Typedef to simplify use of correct index_type.
EConsolidationAction
Modification actions for the consolidate member.
@ c_negativeWeight
Flip the sign of the weight to become negative if the original element got re-attributed.
@ c_zeroWeight
Set the weight of the relation to 0 if the original element got re-attributed.
@ c_deleteElement
Delete the whole relation element if the original element got re-attributed.
@ c_doNothing
Do nothing, just treat it as reordering.
~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.
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.
Class to store a single element of a relation.
unsigned int index_type
type used for indices.
float weight_type
type used for weights.
StoreAccessorBase(const std::string &name, DataStore::EDurability durability, TClass *objClass, bool isArray)
Constructor to access an object or array in the DataStore.
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
STL class.
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.
consolidation_type operator()(index_type old) const
Take old index and return the new index.