Belle II Software  release-05-02-19
SelectSubset.h
1 /**************************************************************************
2  * BASF2 (Belle Analysis Framework 2) *
3  * Copyright(C) 2014 - Belle II Collaboration *
4  * *
5  * Author: The Belle II Collaboration *
6  * Contributors: Eugenio Paoloni ( INFN & University of Pisa ), C. Pulvermacher
7  * *
8  * This software is provided "as is" without any warranty. *
9  **************************************************************************/
10 
11 #pragma once
12 
13 
14 #include <framework/datastore/StoreArray.h>
15 #include <framework/datastore/RelationVector.h>
16 #include <framework/datastore/RelationsObject.h>
17 #include <framework/logging/Logger.h>
18 
19 #include <string>
20 #include <functional>
21 #include <vector>
22 #include <type_traits>
23 
24 
25 namespace Belle2 {
31  class SelectSubsetBase {
32  public:
34  std::vector<std::string> getInheritFromArrays() const { return m_inheritFromArrays; }
36  std::vector<std::string> getInheritToArrays() const { return m_inheritToArrays; }
38  bool getInheritToSelf() const { return m_inheritToSelf; }
39 
41  virtual StoreAccessorBase* getSet() = 0;
43  virtual StoreAccessorBase* getSubSet() = 0;
44 
45  protected:
47  virtual ~SelectSubsetBase() { }
48 
54 
56  std::vector<std::string> m_inheritFromArrays;
58  std::vector<std::string> m_inheritToArrays;
60  bool m_inheritToSelf = false;
62  bool m_reduceExistingSet = false;
63  };
64 
194  template < typename StoredClass >
195  class SelectSubset : public SelectSubsetBase {
196  static_assert(std::is_base_of<RelationsObject, StoredClass>::value,
197  "SelectSubset<T> only works with classes T inheriting from RelationsObject.");
198  public:
201 
204  {
205  delete m_set;
206  delete m_subset;
207  }
208 
219  {
220  m_reduceExistingSet = true;
221  registerSubset(set, set.getName() + "_tmpSubset", storeFlags | DataStore::c_DontWriteOut);
222 
224  }
225 
231  void registerSubset(const StoreArray< StoredClass >& set, const std::string& subsetName,
233  {
234  if (m_set or m_subset) {
235  B2FATAL("SelectSubset::registerSubset() can only be called once!");
236  }
237 
238  m_set = new StoreArray<StoredClass>(set);
239 
240  m_subset = new StoreArray<StoredClass>(subsetName, m_set->getDurability());
241  m_subset->registerInDataStore(storeFlags);
242  m_subsetFlags = storeFlags;
243 
244  set.registerRelationTo(*m_subset, m_subset->getDurability(), storeFlags);
245  }
246 
251  template<class T, class ... MoreArguments >
252  void inheritRelationsFrom(const StoreArray<T>& array, MoreArguments... moreArgs)
253  {
254  if (array.getName() == m_set->getName()) {
255  m_inheritToSelf = true;
256  inheritRelationsFrom(*m_subset, moreArgs...);
257  } else {
258  const_cast<StoreArray<T>&>(array).isRequired();
259 
261  if (m_subset->notWrittenOut() or array.notWrittenOut())
262  flags |= DataStore::c_DontWriteOut;
263  array.registerRelationTo(*m_subset, m_subset->getDurability(), flags);
264 
265  if (array.getName() != m_subset->getName())
266  m_inheritFromArrays.push_back(array.getName());
267 
268  inheritRelationsFrom(moreArgs ...);
269  }
270  }
271 
276  template<class T, class ... MoreArguments >
277  void inheritRelationsTo(const StoreArray<T>& array, MoreArguments... moreArgs)
278  {
279  if (array.getName() == m_set->getName()) {
280  m_inheritToSelf = true;
281  inheritRelationsTo(*m_subset, moreArgs...);
282  } else {
283  const_cast<StoreArray<T>&>(array).isRequired();
284 
286  if (m_subset->notWrittenOut() or array.notWrittenOut())
287  flags |= DataStore::c_DontWriteOut;
288  m_subset->registerRelationTo(array, m_subset->getDurability(), flags);
289 
290  if (array.getName() != m_subset->getName())
291  m_inheritToArrays.push_back(array.getName());
292 
293  inheritRelationsTo(moreArgs ...);
294  }
295  }
296 
303  void inheritAllRelations()
304  {
306 
307  for (std::string arrayName : arrays) {
308  StoreArray<TObject> array(arrayName, m_set->getDurability());
309  if (array == *m_subset)
310  continue; // from registerSubset(), ignore
311 
312  if (array.optionalRelationTo(*m_set, m_set->getDurability()))
313  inheritRelationsFrom(array);
314  if (m_set->optionalRelationTo(array, m_set->getDurability()))
315  inheritRelationsTo(array);
316  }
317  }
318 
324  void select(const std::function<bool (const StoredClass*)>& f);
325 
327  StoreAccessorBase* getSet() override { return m_set; }
329  StoreAccessorBase* getSubSet() override { return m_subset; }
330 
331  protected:
333  std::map<int, int> copySetWithRelations(std::function<bool (const StoredClass*)> f);
334 
336  void copyRelationsToSelf();
337 
339  void inheritRelationsFrom() { }
341  void inheritRelationsTo() { }
342 
344  StoreArray<StoredClass>* m_set = nullptr;
346  StoreArray<StoredClass>* m_subset = nullptr;
349  };
350 
351  template < class StoredClass>
352  std::map<int, int>
353  SelectSubset< StoredClass >::copySetWithRelations(std::function<bool (const StoredClass*)> f)
354  {
355  std::map<int, int> oldToNew;
356  for (const StoredClass& setObject : *m_set) {
357  if (!f(&setObject))
358  continue;
359 
360  oldToNew[setObject.getArrayIndex()] = m_subset->getEntries();
361  const StoredClass* subsetObject = m_subset->appendNew(setObject);
362  if (!m_reduceExistingSet)
363  setObject.addRelationTo(subsetObject);
364  }
365 
366 
367  //TODO this is the slow bit, can probably be improved by directly dealing with indices
368  for (const auto& oldToNewPair : oldToNew) {
369  const StoredClass* setObject = (*m_set)[oldToNewPair.first];
370  const StoredClass* subsetObject = (*m_subset)[oldToNewPair.second];
371 
372  for (std::string fromArray : m_inheritFromArrays) {
373  const RelationVector<RelationsObject>& relations = setObject->template getRelationsFrom<RelationsObject>(fromArray);
374  for (unsigned int iRel = 0; iRel < relations.size(); iRel++) {
375  relations.object(iRel)->addRelationTo(subsetObject, relations.weight(iRel));
376  }
377  }
378  for (std::string toArray : m_inheritToArrays) {
379  const RelationVector<RelationsObject>& relations = setObject->template getRelationsTo<RelationsObject>(toArray);
380  for (unsigned int iRel = 0; iRel < relations.size(); iRel++) {
381  subsetObject->addRelationTo(relations.object(iRel), relations.weight(iRel));
382  }
383  }
384  }
385 
386  return oldToNew;
387  }
388 
389 
390  template < class StoredClass>
391  void
393  {
394  for (const StoredClass& subsetObject1 : *m_subset) {
395  //TODO: change relation direction to set -> subset?
396  const StoredClass* setObject1 = subsetObject1.template getRelatedFrom<StoredClass>(m_set->getName());
397 
398  //get all objects in original set related to setObject1
399  const RelationVector<StoredClass>& relations = setObject1->template getRelationsTo<StoredClass>(m_set->getName());
400  for (unsigned int iRel = 0; iRel < relations.size(); iRel++) {
401  const StoredClass* setObject2 = relations.object(iRel);
402  const double weight = relations.weight(iRel);
403 
404  //if setObject2 was selected into subset, inherit relation
405  const StoredClass* subsetObject2 = setObject2->template getRelatedTo<StoredClass>(m_subset->getName());
406  if (subsetObject2) {
407  subsetObject1.addRelationTo(subsetObject2, weight);
408  }
409  }
410  }
411  }
412 
413  template < class StoredClass>
414  void
415  SelectSubset< StoredClass >::select(const std::function<bool (const StoredClass*)>& f)
416  {
417  copySetWithRelations(f);
418 
419  if (m_inheritToSelf) {
420  copyRelationsToSelf();
421  }
422 
423  if (m_reduceExistingSet) {
424  swapSetsAndDestroyOriginal();
425  }
426  }
428 }
Belle2::RelationVector::size
size_t size() const
Get number of relations.
Definition: RelationVector.h:98
Belle2::StoreArray::optionalRelationTo
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:182
Belle2::SelectSubset::copyRelationsToSelf
void copyRelationsToSelf()
Copy any set -> set relations between selected objects.
Definition: SelectSubset.h:400
Belle2::StoreArray::registerRelationTo
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:150
Belle2::SelectSubset::registerSubset
void registerSubset(const StoreArray< StoredClass > &set, DataStore::EStoreFlags storeFlags=DataStore::c_ErrorIfAlreadyRegistered)
Remove all non-selected objects from set.
Definition: SelectSubset.h:225
Belle2::SelectSubsetBase
Type-independent implementation details of SelectSubset.
Definition: SelectSubset.h:39
Belle2::DataStore::Instance
static DataStore & Instance()
Instance of singleton Store.
Definition: DataStore.cc:54
Belle2::SelectSubset
Class to create a subset of a given StoreArray together with the relations with other StoreArrays.
Definition: SelectSubset.h:203
Belle2::DataStore::EStoreFlags
EStoreFlags
Flags describing behaviours of objects etc.
Definition: DataStore.h:71
Belle2::SelectSubset::select
void select(const std::function< bool(const StoredClass *)> &f)
This method is the actual worker.
Definition: SelectSubset.h:423
Belle2::DataStore::getListOfRelatedArrays
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:641
Belle2::RelationsInterface::addRelationTo
void addRelationTo(const RelationsInterface< BASE > *object, float weight=1.0, const std::string &namedRelation="") const
Add a relation from this object to another object (with caching).
Definition: RelationsObject.h:144
Belle2::StoreAccessorBase
Base class for StoreObjPtr and StoreArray for easier common treatment.
Definition: StoreAccessorBase.h:29
Belle2::DataStore::c_DontWriteOut
@ c_DontWriteOut
Object/array should be NOT saved by output modules.
Definition: DataStore.h:73
Belle2::SelectSubset::getSubSet
StoreAccessorBase * getSubSet() override
Get accessor for reduced set.
Definition: SelectSubset.h:337
Belle2::SelectSubset::inheritRelationsTo
void inheritRelationsTo()
Empty method to stop the recursion of the variadic template.
Definition: SelectSubset.h:349
Belle2::DataStore::c_WriteOut
@ c_WriteOut
Object/array should be saved by output modules.
Definition: DataStore.h:72
Belle2::SelectSubset::SelectSubset
SelectSubset()
Constructor.
Definition: SelectSubset.h:208
Belle2::RelationVector
Class for type safe access to objects that are referred to in relations.
Definition: DataStore.h:38
Belle2
Abstract base class for different kinds of events.
Definition: MillepedeAlgorithm.h:19
Belle2::SelectSubsetBase::getInheritToSelf
bool getInheritToSelf() const
Do we inherit relations from original set to itself?
Definition: SelectSubset.h:46
Belle2::SelectSubsetBase::m_inheritToArrays
std::vector< std::string > m_inheritToArrays
array names we inherit relations to.
Definition: SelectSubset.h:66
Belle2::SelectSubsetBase::getSet
virtual StoreAccessorBase * getSet()=0
Get accessor for original set.
Belle2::SelectSubsetBase::m_inheritToSelf
bool m_inheritToSelf
If true, relations from set objects to set objects are copied.
Definition: SelectSubset.h:68
Belle2::RelationVector::object
T * object(int index) const
Get object with index.
Definition: RelationVector.h:106
Belle2::SelectSubsetBase::m_reduceExistingSet
bool m_reduceExistingSet
If true, non-selected candidates are removed from m_set, m_subset only exists temporarily.
Definition: SelectSubset.h:70
Belle2::SelectSubset::m_subset
StoreArray< StoredClass > * m_subset
The array we create.
Definition: SelectSubset.h:354
Belle2::SelectSubset::inheritRelationsFrom
void inheritRelationsFrom()
Empty method to stop the recursion of the variadic template.
Definition: SelectSubset.h:347
Belle2::SelectSubsetBase::getInheritToArrays
std::vector< std::string > getInheritToArrays() const
Get list of arrays we inherit relations to.
Definition: SelectSubset.h:44
Belle2::DataStore::c_ErrorIfAlreadyRegistered
@ c_ErrorIfAlreadyRegistered
If the object/array was already registered, produce an error (aborting initialisation).
Definition: DataStore.h:74
Belle2::SelectSubset::~SelectSubset
~SelectSubset()
Destructor.
Definition: SelectSubset.h:211
Belle2::RelationVector::weight
float weight(int index) const
Get weight with index.
Definition: RelationVector.h:120
Belle2::SelectSubset::copySetWithRelations
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:361
Belle2::SelectSubsetBase::getSubSet
virtual StoreAccessorBase * getSubSet()=0
Get accessor for reduced set.
Belle2::StoreArray< StoredClass >
Belle2::SelectSubset::getSet
StoreAccessorBase * getSet() override
Get accessor for original set.
Definition: SelectSubset.h:335
Belle2::SelectSubsetBase::swapSetsAndDestroyOriginal
void swapSetsAndDestroyOriginal()
Swap set and subset (+relations), and keep only the reduced set.
Definition: SelectSubset.cc:7
Belle2::SelectSubsetBase::m_inheritFromArrays
std::vector< std::string > m_inheritFromArrays
array names we inherit relations from.
Definition: SelectSubset.h:64
Belle2::SelectSubsetBase::getInheritFromArrays
std::vector< std::string > getInheritFromArrays() const
Get list of arrays we inherit relations from.
Definition: SelectSubset.h:42
Belle2::SelectSubset::m_set
StoreArray< StoredClass > * m_set
The array we use as input.
Definition: SelectSubset.h:352
Belle2::SelectSubset::m_subsetFlags
DataStore::EStoreFlags m_subsetFlags
Flags used for m_subset.
Definition: SelectSubset.h:356
Belle2::SelectSubset::inheritAllRelations
void inheritAllRelations()
Automatically inherit all relations to or from the original set (if registered when calling this func...
Definition: SelectSubset.h:311