Belle II Software light-2607-kasei
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 // cppcheck-suppress duplInheritedMember ; intentionally hides the base class member
154 bool create(bool replace = false)
155 {
156 bool result = DataStore::Instance().createObject(0, replace, *this);
157 m_relations = reinterpret_cast<RelationContainer**>(DataStore::Instance().getObject(*this));
158 if (result) {
159 (*m_relations)->setFromName(m_accessorFrom.first);
160 (*m_relations)->setFromDurability(m_accessorFrom.second);
161 (*m_relations)->setToName(m_accessorTo.first);
162 (*m_relations)->setToDurability(m_accessorTo.second);
163 }
164 return result;
165 }
166
179 template <class FROM, class TO> RelationArray(const StoreArray<FROM>& from, const StoreArray<TO>& to, const std::string& name = "",
181 StoreAccessorBase(name.empty() ? DataStore::relationName(from.getName(), to.getName()) : name, durability,
182 RelationContainer::Class(), false),
185 m_relations(0)
186 {
187 if (m_accessorFrom.second > m_durability || m_accessorTo.second > m_durability) {
188 B2FATAL("Tried to create RelationArray '" << m_name << "' with a durability larger than the StoreArrays it relates");
189 }
190 }
191
199 RelationArray(const AccessorParams& fromAccessor, const AccessorParams& toAccessor,
201 StoreAccessorBase(DataStore::relationName(fromAccessor.first, toAccessor.first), durability, RelationContainer::Class(), false),
202 m_accessorFrom(fromAccessor),
203 m_accessorTo(toAccessor),
204 m_relations(nullptr)
205 {
206 if (m_accessorFrom.second > m_durability || m_accessorTo.second > m_durability) {
207 B2FATAL("Tried to create RelationArray '" << m_name << "' with a durability larger than the StoreArrays it relates");
208 }
209 }
210
219 explicit RelationArray(const std::string& name, DataStore::EDurability durability = DataStore::c_Event):
220 StoreAccessorBase(name, durability, RelationContainer::Class(), false),
221 m_relations(0)
222 {
223 if (name.empty()) {
224 B2FATAL("Cannot guess relation name, please supply correct name");
225 }
226 }
227
229 ~RelationArray() override {}
230
235 inline bool isValid() const { ensureAttached(); return m_relations && *m_relations;}
237 inline operator bool() const { return isValid(); }
238
240 const RelationElement& operator[](int i) const { assertValid(); return (*m_relations)->getElement(i);}
241
243 int getEntries() const { return isValid() ? ((*m_relations)->getEntries()) : 0; }
244
247 {
249 if (m_accessorFrom.first.empty())
250 B2FATAL("trying to get accessor params from non-existing relation (this is likely a framework bug)");
251 return m_accessorFrom;
252 }
253
256 {
258 if (m_accessorTo.first.empty())
259 B2FATAL("trying to get accessor params from non-existing relation (this is likely a framework bug)");
260 return m_accessorTo;
261 }
262
264 bool getModified() const { assertValid(); return (*m_relations)->getModified(); }
265
267 void setModified(bool modified) { assertCreated(); (*m_relations)->setModified(modified); }
268
270 void clear() override
271 {
272 setModified(true);
273 (*m_relations)->elements().Delete();
274 }
275
282 void add(index_type from, index_type to, weight_type weight = 1.0)
283 {
284 setModified(true);
285 new (next()) RelationElement(from, to, weight);
286 }
287
294 void add(index_type from, const std::vector<index_type>& to, weight_type weight = 1.0)
295 {
296 setModified(true);
297 std::vector<weight_type> weights(to.size(), weight);
298 new (next()) RelationElement(from, to, weights);
299 }
300
307 void add(index_type from, const std::vector<index_type>& to, const std::vector<weight_type>& weights)
308 {
309 setModified(true);
310 new (next()) RelationElement(from, to, weights);
311 }
312
321 template <class InputIterator> void add(index_type from, const InputIterator& begin, const InputIterator& end)
322 {
323 setModified(true);
324 new (next()) RelationElement(from, begin, end);
325 }
326
333
364 template<class FunctionFrom, class FunctionTo> void consolidate(const
365 FunctionFrom& replaceFrom = FunctionFrom(), const FunctionTo &
366 replaceTo = FunctionTo(), EConsolidationAction action =
368
370 const_iterator begin() const { assertValid(); return const_iterator((*m_relations)->elements(), 0); }
372 const_iterator end() const { assertValid(); return const_iterator((*m_relations)->elements(), getEntries()); }
373
374 private:
382 explicit RelationArray(const AccessorParams& params):
383 StoreAccessorBase(params.first, params.second, RelationContainer::Class(), false),
384 m_relations(0)
385 {
386 if (params.first.empty()) {
387 B2FATAL("Cannot guess relation name, please supply correct name");
388 }
389 }
390
391
394 {
395 int index = (*m_relations)->elements().GetLast() + 1;
396 return static_cast<RelationElement*>((*m_relations)->elements().AddrAt(index));
397 }
398
400 void checkRelation(const std::string& direction, const AccessorParams& array, const AccessorParams& rel) const
401 {
402 if (array.second == 0 && array.first.empty())
403 return; //no information to check against...
404
405 if (array != rel) {
406 B2FATAL("Relation '" << m_name << "' exists but points " << direction << " wrong array:"
407 << " requested " << array.first << "(" << array.second << ")"
408 << ", got " << rel.first << "(" << rel.second << ")"
409 );
410 }
411 }
412
414 void ensureAttached() const
415 {
416 if (m_relations)
417 return;
418
419 const_cast<RelationArray*>(this)->m_relations = reinterpret_cast<RelationContainer**>(DataStore::Instance().getObject(*this));
420 if (m_relations && *m_relations && !(*m_relations)->isDefaultConstructed()) {
421 AccessorParams fromAccessorRel((*m_relations)->getFromName(), (DataStore::EDurability)(*m_relations)->getFromDurability());
422 AccessorParams toAccessorRel((*m_relations)->getToName(), (DataStore::EDurability)(*m_relations)->getToDurability());
423 //set if unset
424 if (m_accessorFrom.first.empty())
425 const_cast<RelationArray*>(this)->m_accessorFrom = fromAccessorRel;
426 if (m_accessorTo.first.empty())
427 const_cast<RelationArray*>(this)->m_accessorTo = toAccessorRel;
428 checkRelation("from", m_accessorFrom, fromAccessorRel);
429 checkRelation("to", m_accessorTo, toAccessorRel);
430 } else {
431 //no relation found, mark as invalid
432 const_cast<RelationArray*>(this)->m_relations = nullptr;
433 }
434 }
435
437 void assertValid() const { if (!isValid()) B2FATAL("RelationArray does not point to valid StoreObject"); }
438
444 {
445 if (!isValid()) {
446 if (!create()) {
447 B2FATAL("Couldn't create relation " << m_name << "!");
448 }
449 }
450 }
451
454
457
460
461 template<class FROM, class TO> friend class RelationIndex;
462 template<class FROM, class TO> friend class RelationIndexContainer;
463
464 };
465
466 template<class FunctionFrom, class FunctionTo>
467 void RelationArray::consolidate(const FunctionFrom& replaceFrom, const FunctionTo& replaceTo, EConsolidationAction action)
468 {
469 if (!isValid()) {
470 B2ERROR("Cannot consolidate an invalid relation (" << m_name << ")");
471 return;
472 }
473 typedef std::map<index_type, weight_type> element_t;
474 typedef std::map<index_type, element_t > buffer_t;
475 buffer_t buffer;
476
477 //Fill all existing elements in a nested map, adding the weights of
478 //duplicate elements
479 index_type lastFromIndex(0);
480 buffer_t::iterator lastFromIter = buffer.end();
481 unsigned int nElements = (*m_relations)->getEntries();
482 TClonesArray& elements = (*m_relations)->elements();
483 for (unsigned int i = 0; i < nElements; ++i) {
484 const RelationElement& element = *static_cast<RelationElement*>(elements[i]);
485 //Replace from index
486 consolidation_type from = replaceFrom(element.getFromIndex());
487
488 //Ignore whole element if original element got deleted
489 if (action == c_deleteElement && from.second) continue;
490
491 //Check if the fromIndex is the same as the last one and reuse
492 //iterator if possible
493 if (from.first != lastFromIndex || lastFromIter == buffer.end()) {
494 lastFromIter = buffer.insert(make_pair(from.first, element_t())).first;
495 lastFromIndex = from.first;
496 }
497 //Loop over all elements of this relationelement and add them to the map
498 size_t size = element.getSize();
499 for (size_t j = 0; j < size; ++j) {
500 //Replace to Index
501 consolidation_type to = replaceTo(element.getToIndex(j));
502 //Ignore whole element if original element got deleted
503 if (action == c_deleteElement && to.second) continue;
504 double weight = element.getWeight(j);
505 //Original from or to element got deleted. Do whatever is specified by action
506 //Warning: if there is more than one element pointing to the same
507 //from->to element after transformation the negative weight option is
508 //not safe as we sum a positive and a negative weight when
509 //consolidating.
510 if (from.second || to.second) {
511 if (action == c_zeroWeight) {
512 weight = 0;
513 } else if (action == c_negativeWeight && weight > 0) {
514 weight = -weight;
515 }
516 }
517 //add the weight to the new from->to index pair
518 lastFromIter->second[to.first] += weight;
519 }
520 }
521 //Clear the existing relation
522 elements.Delete();
523 //Fill the map into the relation
524 for (buffer_t::iterator iter = buffer.begin(); iter != buffer.end(); ++iter) {
525 add(iter->first, iter->second.begin(), iter->second.end());
526 }
527 }
528
530} // 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:314
TObject ** getObject(const StoreAccessorBase &accessor)
Get a pointer to a pointer of an object in the DataStore.
Definition DataStore.cc:304
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.
~RelationArray() override
Empty destructor.
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.
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.
index_type getFromIndex() const
Get index we point from.
index_type getToIndex(size_t n=0) const
Get nth index we point to.
unsigned int index_type
type used for indices.
float weight_type
type used for weights.
size_t getSize() const
Get number of indices we points to.
weight_type getWeight(size_t n=0) const
Get nth weight we point to.
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
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.