Belle II Software development
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
23namespace 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;
42
48
49 protected:
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
237
239 m_subset->registerInDataStore(storeFlags);
240 m_subsetFlags = storeFlags;
241
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())
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())
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
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.
T * object(int index) const
Get object with index.
size_t size() const
Get number of relations.
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 * getSubSet()=0
Get accessor for reduced 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
std::vector< std::string > getInheritToArrays() const
Get list of arrays we inherit relations to.
Definition: SelectSubset.h:34
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
virtual StoreAccessorBase * getSet()=0
Get accessor for original set.
std::vector< std::string > getInheritFromArrays() const
Get list of arrays we inherit relations from.
Definition: SelectSubset.h:32
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
~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
StoreAccessorBase * getSet() override
Get accessor for original set.
Definition: SelectSubset.h:325
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.
const std::string & getName() const
Return name under which the object is saved in the DataStore.
bool notWrittenOut() const
Returns true if this object/array should not be saved by output modules.
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.