Belle II Software  release-08-01-10
SelectSubset.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 
12 #include <framework/datastore/StoreArray.h>
13 #include <framework/datastore/RelationVector.h>
14 #include <framework/datastore/RelationsObject.h>
15 #include <framework/logging/Logger.h>
16 
17 #include <string>
18 #include <functional>
19 #include <vector>
20 #include <type_traits>
21 
22 
23 namespace Belle2 {
30  public:
32  std::vector<std::string> getInheritFromArrays() const { return m_inheritFromArrays; }
34  std::vector<std::string> getInheritToArrays() const { return m_inheritToArrays; }
36  bool getInheritToSelf() const { return m_inheritToSelf; }
37 
39  virtual StoreAccessorBase* getSet() = 0;
41  virtual StoreAccessorBase* getSubSet() = 0;
42 
48 
49  protected:
50  SelectSubsetBase() { }
51  virtual ~SelectSubsetBase() { }
52 
54  std::vector<std::string> m_inheritFromArrays;
56  std::vector<std::string> m_inheritToArrays;
58  bool m_inheritToSelf = false;
60  bool m_reduceExistingSet = false;
61  };
62 
192  template < typename StoredClass >
194  static_assert(std::is_base_of<RelationsObject, StoredClass>::value,
195  "SelectSubset<T> only works with classes T inheriting from RelationsObject.");
196  public:
199 
202  {
203  delete m_set;
204  delete m_subset;
205  }
206 
217  {
218  m_reduceExistingSet = true;
219  registerSubset(set, set.getName() + "_tmpSubset", storeFlags | DataStore::c_DontWriteOut);
220 
222  }
223 
229  void registerSubset(const StoreArray< StoredClass >& set, const std::string& subsetName,
231  {
232  if (m_set or m_subset) {
233  B2FATAL("SelectSubset::registerSubset() can only be called once!");
234  }
235 
236  m_set = new StoreArray<StoredClass>(set);
237 
238  m_subset = new StoreArray<StoredClass>(subsetName, m_set->getDurability());
239  m_subset->registerInDataStore(storeFlags);
240  m_subsetFlags = storeFlags;
241 
242  set.registerRelationTo(*m_subset, m_subset->getDurability(), storeFlags);
243  }
244 
249  template<class T, class ... MoreArguments >
250  void inheritRelationsFrom(const StoreArray<T>& array, MoreArguments... moreArgs)
251  {
252  if (array.getName() == m_set->getName()) {
253  m_inheritToSelf = true;
254  inheritRelationsFrom(*m_subset, moreArgs...);
255  } else {
256  const_cast<StoreArray<T>&>(array).isRequired();
257 
259  if (m_subset->notWrittenOut() or array.notWrittenOut())
260  flags |= DataStore::c_DontWriteOut;
262 
263  if (array.getName() != m_subset->getName())
264  m_inheritFromArrays.push_back(array.getName());
265 
266  inheritRelationsFrom(moreArgs ...);
267  }
268  }
269 
274  template<class T, class ... MoreArguments >
275  void inheritRelationsTo(const StoreArray<T>& array, MoreArguments... moreArgs)
276  {
277  if (array.getName() == m_set->getName()) {
278  m_inheritToSelf = true;
279  inheritRelationsTo(*m_subset, moreArgs...);
280  } else {
281  const_cast<StoreArray<T>&>(array).isRequired();
282 
284  if (m_subset->notWrittenOut() or array.notWrittenOut())
285  flags |= DataStore::c_DontWriteOut;
287 
288  if (array.getName() != m_subset->getName())
289  m_inheritToArrays.push_back(array.getName());
290 
291  inheritRelationsTo(moreArgs ...);
292  }
293  }
294 
302  {
304 
305  for (std::string arrayName : arrays) {
306  StoreArray<TObject> array(arrayName, m_set->getDurability());
307  if (array == *m_subset)
308  continue; // from registerSubset(), ignore
309 
311  inheritRelationsFrom(array);
313  inheritRelationsTo(array);
314  }
315  }
316 
322  void select(const std::function<bool (const StoredClass*)>& f);
323 
325  StoreAccessorBase* getSet() override { return m_set; }
327  StoreAccessorBase* getSubSet() override { return m_subset; }
328 
329  protected:
331  std::map<int, int> copySetWithRelations(std::function<bool (const StoredClass*)> f);
332 
335 
340 
347  };
348 
349  template < class StoredClass>
350  std::map<int, int>
351  SelectSubset< StoredClass >::copySetWithRelations(std::function<bool (const StoredClass*)> f)
352  {
353  std::map<int, int> oldToNew;
354  for (const StoredClass& setObject : *m_set) {
355  if (!f(&setObject))
356  continue;
357 
358  oldToNew[setObject.getArrayIndex()] = m_subset->getEntries();
359  const StoredClass* subsetObject = m_subset->appendNew(setObject);
360  if (!m_reduceExistingSet)
361  setObject.addRelationTo(subsetObject);
362  }
363 
364 
365  //TODO this is the slow bit, can probably be improved by directly dealing with indices
366  for (const auto& oldToNewPair : oldToNew) {
367  const StoredClass* setObject = (*m_set)[oldToNewPair.first];
368  const StoredClass* subsetObject = (*m_subset)[oldToNewPair.second];
369 
370  for (std::string fromArray : m_inheritFromArrays) {
371  const RelationVector<RelationsObject>& relations = setObject->template getRelationsFrom<RelationsObject>(fromArray);
372  for (unsigned int iRel = 0; iRel < relations.size(); iRel++) {
373  relations.object(iRel)->addRelationTo(subsetObject, relations.weight(iRel));
374  }
375  }
376  for (std::string toArray : m_inheritToArrays) {
377  const RelationVector<RelationsObject>& relations = setObject->template getRelationsTo<RelationsObject>(toArray);
378  for (unsigned int iRel = 0; iRel < relations.size(); iRel++) {
379  subsetObject->addRelationTo(relations.object(iRel), relations.weight(iRel));
380  }
381  }
382  }
383 
384  return oldToNew;
385  }
386 
387 
388  template < class StoredClass>
389  void
391  {
392  for (const StoredClass& subsetObject1 : *m_subset) {
393  //TODO: change relation direction to set -> subset?
394  const StoredClass* setObject1 = subsetObject1.template getRelatedFrom<StoredClass>(m_set->getName());
395 
396  if (setObject1 != nullptr) {
397  //get all objects in original set related to setObject1
398  const RelationVector<StoredClass>& relations = setObject1->template getRelationsTo<StoredClass>(m_set->getName());
399  for (unsigned int iRel = 0; iRel < relations.size(); iRel++) {
400  const StoredClass* setObject2 = relations.object(iRel);
401  const double weight = relations.weight(iRel);
402  //if setObject2 was selected into subset, inherit relation
403  const StoredClass* subsetObject2 = setObject2->template getRelatedTo<StoredClass>(m_subset->getName());
404  if (subsetObject2) {
405  subsetObject1.addRelationTo(subsetObject2, weight);
406  }
407  }
408  }
409  }
410  }
411 
412  template < class StoredClass>
413  void
414  SelectSubset< StoredClass >::select(const std::function<bool (const StoredClass*)>& f)
415  {
416  copySetWithRelations(f);
417 
418  if (m_inheritToSelf) {
419  copyRelationsToSelf();
420  }
421 
422  if (m_reduceExistingSet) {
423  swapSetsAndDestroyOriginal();
424  }
425  }
427 }
std::vector< std::string > getListOfRelatedArrays(const StoreAccessorBase &array) const
Returns a list of names of arrays which have registered relations that point to or from 'array'.
Definition: DataStore.cc:640
EStoreFlags
Flags describing behaviours of objects etc.
Definition: DataStore.h:69
@ c_WriteOut
Object/array should be saved by output modules.
Definition: DataStore.h:70
@ c_DontWriteOut
Object/array should be NOT saved by output modules.
Definition: DataStore.h:71
@ c_ErrorIfAlreadyRegistered
If the object/array was already registered, produce an error (aborting initialisation).
Definition: DataStore.h:72
static DataStore & Instance()
Instance of singleton Store.
Definition: DataStore.cc:54
Class for type safe access to objects that are referred to in relations.
size_t size() const
Get number of relations.
T * object(int index) const
Get object with index.
float weight(int index) const
Get weight with index.
Type-independent implementation details of SelectSubset.
Definition: SelectSubset.h:29
std::vector< std::string > m_inheritFromArrays
array names we inherit relations from.
Definition: SelectSubset.h:54
virtual StoreAccessorBase * getSet()=0
Get accessor for original set.
bool m_inheritToSelf
If true, relations from set objects to set objects are copied.
Definition: SelectSubset.h:58
bool m_reduceExistingSet
If true, non-selected candidates are removed from m_set, m_subset only exists temporarily.
Definition: SelectSubset.h:60
virtual StoreAccessorBase * getSubSet()=0
Get accessor for reduced set.
std::vector< std::string > getInheritToArrays() const
Get list of arrays we inherit relations to.
Definition: SelectSubset.h:34
std::vector< std::string > getInheritFromArrays() const
Get list of arrays we inherit relations from.
Definition: SelectSubset.h:32
bool getInheritToSelf() const
Do we inherit relations from original set to itself?
Definition: SelectSubset.h:36
void swapSetsAndDestroyOriginal()
Swap set and subset (+relations), and keep only the reduced set.
Definition: SelectSubset.cc:14
std::vector< std::string > m_inheritToArrays
array names we inherit relations to.
Definition: SelectSubset.h:56
Class to create a subset of a given StoreArray together with the relations with other StoreArrays.
Definition: SelectSubset.h:193
void inheritRelationsTo(const StoreArray< T > &array, MoreArguments... moreArgs)
Inherit relations pointing from objects selected into this subset to Other.
Definition: SelectSubset.h:275
StoreArray< StoredClass > * m_set
The array we use as input.
Definition: SelectSubset.h:342
void inheritRelationsTo()
Empty method to stop the recursion of the variadic template.
Definition: SelectSubset.h:339
StoreAccessorBase * getSet() override
Get accessor for original set.
Definition: SelectSubset.h:325
~SelectSubset()
Destructor.
Definition: SelectSubset.h:201
StoreArray< StoredClass > * m_subset
The array we create.
Definition: SelectSubset.h:344
DataStore::EStoreFlags m_subsetFlags
Flags used for m_subset.
Definition: SelectSubset.h:346
void inheritRelationsFrom(const StoreArray< T > &array, MoreArguments... moreArgs)
Inherit relations pointing from Other to objects selected into this subset.
Definition: SelectSubset.h:250
void inheritAllRelations()
Automatically inherit all relations to or from the original set (if registered when calling this func...
Definition: SelectSubset.h:301
void registerSubset(const StoreArray< StoredClass > &set, const std::string &subsetName, DataStore::EStoreFlags storeFlags=DataStore::c_ErrorIfAlreadyRegistered)
Register the StoreArray<StoredClass> that will contain the subset of selected elements.
Definition: SelectSubset.h:229
void inheritRelationsFrom()
Empty method to stop the recursion of the variadic template.
Definition: SelectSubset.h:337
SelectSubset()
Constructor.
Definition: SelectSubset.h:198
StoreAccessorBase * getSubSet() override
Get accessor for reduced set.
Definition: SelectSubset.h:327
void registerSubset(const StoreArray< StoredClass > &set, DataStore::EStoreFlags storeFlags=DataStore::c_ErrorIfAlreadyRegistered)
Remove all non-selected objects from set.
Definition: SelectSubset.h:215
Base class for StoreObjPtr and StoreArray for easier common treatment.
DataStore::EDurability getDurability() const
Return durability with which the object is saved in the DataStore.
bool notWrittenOut() const
Returns true if this object/array should not be saved by output modules.
const std::string & getName() const
Return name under which the object is saved in the DataStore.
bool registerInDataStore(DataStore::EStoreFlags storeFlags=DataStore::c_WriteOut)
Register the object/array in the DataStore.
bool optionalRelationTo(const StoreArray< TO > &toArray, DataStore::EDurability durability=DataStore::c_Event, const std::string &namedRelation="") const
Tell the data store about a relation that we could make use of.
Definition: StoreArray.h:172
bool registerRelationTo(const StoreArray< TO > &toArray, DataStore::EDurability durability=DataStore::c_Event, DataStore::EStoreFlags storeFlags=DataStore::c_WriteOut, const std::string &namedRelation="") const
Register a relation to the given StoreArray.
Definition: StoreArray.h:140
void select(const std::function< bool(const StoredClass *)> &f)
This method is the actual worker.
Definition: SelectSubset.h:414
std::map< int, int > copySetWithRelations(std::function< bool(const StoredClass *)> f)
Selects the elements, fill the subset and copies all the relations in which the set is involved.
Definition: SelectSubset.h:351
void copyRelationsToSelf()
Copy any set -> set relations between selected objects.
Definition: SelectSubset.h:390
Abstract base class for different kinds of events.