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 {
29 class SelectSubsetBase {
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:
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 >
193 class SelectSubset : public SelectSubsetBase {
194 static_assert(std::is_base_of<RelationsObject, StoredClass>::value,
195 "SelectSubset<T> only works with classes T inheriting from RelationsObject.");
196 public:
198 SelectSubset(): SelectSubsetBase() {};
199
201 SelectSubset(const SelectSubset&) = delete;
202
205
207 ~SelectSubset() override
208 {
209 delete m_set;
210 delete m_subset;
211 }
212
223 {
224 m_reduceExistingSet = true;
225 registerSubset(set, set.getName() + "_tmpSubset", storeFlags | DataStore::c_DontWriteOut);
226
228 }
229
235 void registerSubset(const StoreArray< StoredClass >& set, const std::string& subsetName,
237 {
238 if (m_set or m_subset) {
239 B2FATAL("SelectSubset::registerSubset() can only be called once!");
240 }
241
243
244 m_subset = new StoreArray<StoredClass>(subsetName, m_set->getDurability());
245 m_subset->registerInDataStore(storeFlags);
246 m_subsetFlags = storeFlags;
247
248 set.registerRelationTo(*m_subset, m_subset->getDurability(), storeFlags);
249 }
250
255 template<class T, class ... MoreArguments >
256 void inheritRelationsFrom(const StoreArray<T>& array, MoreArguments... moreArgs)
257 {
258 if (array.getName() == m_set->getName()) {
259 m_inheritToSelf = true;
260 inheritRelationsFrom(*m_subset, moreArgs...);
261 } else {
262 const_cast<StoreArray<T>&>(array).isRequired();
263
265 if (m_subset->notWrittenOut() or array.notWrittenOut())
267 array.registerRelationTo(*m_subset, m_subset->getDurability(), flags);
268
269 if (array.getName() != m_subset->getName())
270 m_inheritFromArrays.push_back(array.getName());
271
272 inheritRelationsFrom(moreArgs ...);
273 }
274 }
275
280 template<class T, class ... MoreArguments >
281 void inheritRelationsTo(const StoreArray<T>& array, MoreArguments... moreArgs)
282 {
283 if (array.getName() == m_set->getName()) {
284 m_inheritToSelf = true;
285 inheritRelationsTo(*m_subset, moreArgs...);
286 } else {
287 const_cast<StoreArray<T>&>(array).isRequired();
288
290 if (m_subset->notWrittenOut() or array.notWrittenOut())
292 m_subset->registerRelationTo(array, m_subset->getDurability(), flags);
293
294 if (array.getName() != m_subset->getName())
295 m_inheritToArrays.push_back(array.getName());
296
297 inheritRelationsTo(moreArgs ...);
298 }
299 }
300
308 {
310
311 for (const std::string& arrayName : arrays) {
312 StoreArray<TObject> array(arrayName, m_set->getDurability());
313 if (array == *m_subset)
314 continue; // from registerSubset(), ignore
315
316 if (array.optionalRelationTo(*m_set, m_set->getDurability()))
318 if (m_set->optionalRelationTo(array, m_set->getDurability()))
319 inheritRelationsTo(array);
320 }
321 }
322
328 void select(const std::function<bool (const StoredClass*)>& f);
329
331 StoreAccessorBase* getSet() override { return m_set; }
333 StoreAccessorBase* getSubSet() override { return m_subset; }
334
335 protected:
337 std::map<int, int> copySetWithRelations(std::function<bool (const StoredClass*)> f);
338
341
343 static void inheritRelationsFrom() { }
345 static void inheritRelationsTo() { }
346
353 };
354
355 template < class StoredClass>
356 std::map<int, int>
357 SelectSubset< StoredClass >::copySetWithRelations(std::function<bool (const StoredClass*)> f)
358 {
359 std::map<int, int> oldToNew;
360 for (const StoredClass& setObject : *m_set) {
361 if (!f(&setObject))
362 continue;
363
364 oldToNew[setObject.getArrayIndex()] = m_subset->getEntries();
365 const StoredClass* subsetObject = m_subset->appendNew(setObject);
367 setObject.addRelationTo(subsetObject);
368 }
369
370
371 //TODO this is the slow bit, can probably be improved by directly dealing with indices
372 for (const auto& oldToNewPair : oldToNew) {
373 const StoredClass* setObject = (*m_set)[oldToNewPair.first];
374 const StoredClass* subsetObject = (*m_subset)[oldToNewPair.second];
375
376 for (std::string fromArray : m_inheritFromArrays) {
377 const RelationVector<RelationsObject>& relations = setObject->template getRelationsFrom<RelationsObject>(fromArray);
378 for (unsigned int iRel = 0; iRel < relations.size(); iRel++) {
379 relations.object(iRel)->addRelationTo(subsetObject, relations.weight(iRel));
380 }
381 }
382 for (std::string toArray : m_inheritToArrays) {
383 const RelationVector<RelationsObject>& relations = setObject->template getRelationsTo<RelationsObject>(toArray);
384 for (unsigned int iRel = 0; iRel < relations.size(); iRel++) {
385 subsetObject->addRelationTo(relations.object(iRel), relations.weight(iRel));
386 }
387 }
388 }
389
390 return oldToNew;
391 }
392
393
394 template < class StoredClass>
395 void
397 {
398 for (const StoredClass& subsetObject1 : *m_subset) {
399 //TODO: change relation direction to set -> subset?
400 const StoredClass* setObject1 = subsetObject1.template getRelatedFrom<StoredClass>(m_set->getName());
401
402 if (setObject1 != nullptr) {
403 //get all objects in original set related to setObject1
404 const RelationVector<StoredClass>& relations = setObject1->template getRelationsTo<StoredClass>(m_set->getName());
405 for (unsigned int iRel = 0; iRel < relations.size(); iRel++) {
406 const StoredClass* setObject2 = relations.object(iRel);
407 const double weight = relations.weight(iRel);
408 //if setObject2 was selected into subset, inherit relation
409 const StoredClass* subsetObject2 = setObject2->template getRelatedTo<StoredClass>(m_subset->getName());
410 if (subsetObject2) {
411 subsetObject1.addRelationTo(subsetObject2, weight);
412 }
413 }
414 }
415 }
416 }
417
418 template < class StoredClass>
419 void
420 SelectSubset< StoredClass >::select(const std::function<bool (const StoredClass*)>& f)
421 {
423
424 if (m_inheritToSelf) {
426 }
427
430 }
431 }
432
433}
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:639
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:53
Class for type safe access to objects that are referred to in relations.
Type-independent implementation details of SelectSubset.
std::vector< std::string > m_inheritFromArrays
array names we inherit relations from.
virtual StoreAccessorBase * getSubSet()=0
Get accessor for reduced set.
bool m_inheritToSelf
If true, relations from set objects to set objects are copied.
bool m_reduceExistingSet
If true, non-selected candidates are removed from m_set, m_subset only exists temporarily.
std::vector< std::string > getInheritToArrays() const
Get list of arrays we inherit relations to.
bool getInheritToSelf() const
Do we inherit relations from original set to itself?
void swapSetsAndDestroyOriginal()
Swap set and subset (+relations), and keep only the reduced set.
virtual StoreAccessorBase * getSet()=0
Get accessor for original set.
std::vector< std::string > getInheritFromArrays() const
Get list of arrays we inherit relations from.
std::vector< std::string > m_inheritToArrays
array names we inherit relations to.
void inheritRelationsTo(const StoreArray< T > &array, MoreArguments... moreArgs)
Inherit relations pointing from objects selected into this subset to Other.
StoreArray< StoredClass > * m_set
The array we use as input.
~SelectSubset() override
Destructor.
static void inheritRelationsTo()
Empty method to stop the recursion of the variadic template.
SelectSubset & operator=(const SelectSubset &)=delete
no assignment operator
static void inheritRelationsFrom()
Empty method to stop the recursion of the variadic template.
StoreArray< StoredClass > * m_subset
The array we create.
DataStore::EStoreFlags m_subsetFlags
Flags used for m_subset.
void inheritRelationsFrom(const StoreArray< T > &array, MoreArguments... moreArgs)
Inherit relations pointing from Other to objects selected into this subset.
void inheritAllRelations()
Automatically inherit all relations to or from the original set (if registered when calling this func...
StoreAccessorBase * getSet() override
Get accessor for original set.
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.
SelectSubset()
Constructor.
StoreAccessorBase * getSubSet() override
Get accessor for reduced set.
void registerSubset(const StoreArray< StoredClass > &set, DataStore::EStoreFlags storeFlags=DataStore::c_ErrorIfAlreadyRegistered)
Remove all non-selected objects from set.
SelectSubset(const SelectSubset &)=delete
no copy constructor
Base class for StoreObjPtr and StoreArray for easier common treatment.
void select(const std::function< bool(const StoredClass *)> &f)
This method is the actual worker.
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.
void copyRelationsToSelf()
Copy any set -> set relations between selected objects.
Abstract base class for different kinds of events.