Belle II Software development
filters.cc
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#include <gtest/gtest.h>
10
11
12#include <tracking/trackFindingVXD/filterMap/filterFramework/Shortcuts.h>
13#include <tuple>
14#include <iostream>
15#include <math.h>
16
17using namespace std;
18
19using namespace Belle2;
20
21namespace VXDTFfilterTest {
22
24 class spacePoint: public tuple<float, float, float> {
25 public:
27 spacePoint(float x, float y, float z): tuple<float, float, float>(x, y, z)
28 {};
29 private:
32 spacePoint(const spacePoint&) = delete;
33 };
34
35
37 class SquaredDistance3D : public SelectionVariable< spacePoint, 2, float > {
38 public:
40 static const std::string name(void) {return "SquaredDistance3D"; };
41
43 static float value(const spacePoint& p1, const spacePoint& p2)
44 {
45 return
46 pow(get<0>(p1) - get<0>(p2), 2) +
47 pow(get<1>(p1) - get<1>(p2), 2) +
48 pow(get<2>(p1) - get<2>(p2), 2) ;
49 }
50 };
51
52
54 class SquaredDistance2Dxy : public SelectionVariable< spacePoint, 2, float > {
55 public:
57 static const std::string name(void) {return "SquaredDistance2Dxy"; };
58
60 static float value(const spacePoint& p1, const spacePoint& p2)
61 {
62 return
63 pow(get<0>(p1) - get<0>(p2), 2) +
64 pow(get<1>(p1) - get<1>(p2), 2) ;
65 }
66 };
67
68
70 class SquaredDistance1Dx : public SelectionVariable< spacePoint, 2, float > {
71 public:
73 static const std::string name(void) {return "SquaredDistance1Dx"; };
74
76 static float value(const spacePoint& p1, const spacePoint& p2)
77 {
78 return
79 pow(get<0>(p1) - get<0>(p2), 2);
80 }
81 };
82
83
85 class BooleanVariable : public SelectionVariable< spacePoint, 2, bool > {
86 public:
88 static const std::string name(void) {return "BooleanVariable"; };
89
91 static float value(const spacePoint& p1, const spacePoint& p2)
92 {
93 return
94 get<0>(p1) - get<0>(p2) == 0.;
95 }
96 };
97
98
100 template < class T> class counter {
101 public:
102 static int N;
103 counter() {};
104 ~counter() {};
105 };
106
107
109 template<>
111
112
114 template<>
116
117
119 template<>
121
122
124 class Observer : public VoidObserver {
125 public:
127 template<class Var, typename ... otherTypes>
128 static void notify(const Var&,
129 const otherTypes& ...)
130 {
131 counter<Var>::N ++ ;
132 }
133 };
134
135
136
138 class FilterTest : public ::testing::Test {
139 protected:
140 };
141
142
144 TEST_F(FilterTest, Range)
145 {
146
147 Range<double, double> range(0., 1.);
148 EXPECT_TRUE(range.contains(0.5));
149 EXPECT_FALSE(range.contains(-1.));
150 EXPECT_FALSE(range.contains(0.));
151 EXPECT_FALSE(range.contains(1.));
152 EXPECT_FALSE(range.contains(2.));
153 EXPECT_EQ(0., range.getInf());
154 EXPECT_EQ(1., range.getSup());
155 }
156
158 TEST_F(FilterTest, ClosedRange)
159 {
160
161 ClosedRange<double, double> range(0., 1.);
162 EXPECT_TRUE(range.contains(0.5));
163 EXPECT_FALSE(range.contains(-1.));
164 EXPECT_TRUE(range.contains(0.));
165 EXPECT_TRUE(range.contains(1.));
166 EXPECT_FALSE(range.contains(2.));
167 EXPECT_EQ(0., range.getInf());
168 EXPECT_EQ(1., range.getSup());
169 }
170
171
173 TEST_F(FilterTest, UpperBoundedSet)
174 {
175
176 UpperBoundedSet<double> upperBoundedSet(0.);
177 EXPECT_TRUE(upperBoundedSet.contains(-1.));
178 EXPECT_FALSE(upperBoundedSet.contains(0.));
179 EXPECT_FALSE(upperBoundedSet.contains(1.));
180 EXPECT_EQ(0., upperBoundedSet.getSup());
181 }
182
184 TEST_F(FilterTest, ClosedUpperBoundedSet)
185 {
186
187 ClosedUpperBoundedSet<double> upperBoundedSet(0.);
188 EXPECT_TRUE(upperBoundedSet.contains(-1.));
189 EXPECT_TRUE(upperBoundedSet.contains(0.));
190 EXPECT_FALSE(upperBoundedSet.contains(1.));
191 EXPECT_EQ(0., upperBoundedSet.getSup());
192 }
193
194
196 TEST_F(FilterTest, LowerBoundedSet)
197 {
198
199 LowerBoundedSet<double> lowerBoundedSet(0.);
200 EXPECT_TRUE(lowerBoundedSet.contains(1.));
201 EXPECT_FALSE(lowerBoundedSet.contains(0.));
202 EXPECT_FALSE(lowerBoundedSet.contains(-1.));
203 EXPECT_EQ(0., lowerBoundedSet.getInf());
204 }
205
207 TEST_F(FilterTest, ClosedLowerBoundedSet)
208 {
209
210 ClosedLowerBoundedSet<double> lowerBoundedSet(0.);
211 EXPECT_TRUE(lowerBoundedSet.contains(1.));
212 EXPECT_TRUE(lowerBoundedSet.contains(0.));
213 EXPECT_FALSE(lowerBoundedSet.contains(-1.));
214 EXPECT_EQ(0., lowerBoundedSet.getInf());
215 }
216
217
219 TEST_F(FilterTest, SelectionVariableName)
220 {
221
222 EXPECT_EQ("SquaredDistance3D", SquaredDistance3D().name());
223 }
224
225
227 TEST_F(FilterTest, BasicFilter)
228 {
229 // Very verbose declaration, see below for convenient shortcuts
231
232 spacePoint x1(0.0f, 0.0f, 0.0f);
233 spacePoint x2(0.5f, 0.0f, 0.0f);
234 spacePoint x3(2.0f, 0.0f, 0.0f);
235
236 EXPECT_TRUE(filter.accept(x1, x2));
237 EXPECT_FALSE(filter.accept(x1, x3));
238
239 }
240
241
243 TEST_F(FilterTest, ObservedFilter)
244 {
245 // Very verbose declaration, see below for convenient shortcuts
247
249 spacePoint x1(0.0f, 0.0f, 0.0f);
250 spacePoint x2(0.5f, 0.0f, 0.0f);
251 spacePoint x3(2.0f, 0.0f, 0.0f);
253
254 EXPECT_TRUE(filter.accept(x1, x2));
255 EXPECT_FALSE(filter.accept(x1, x3));
257 }
258
260 TEST_F(FilterTest, SwitchingObservers)
261 {
262 //build an dummy filter which is unobserved (VoidObserver)
263 auto dummyFilter = ((-10. <= SquaredDistance3D() <= 10.) &&
264 ((-100. <= SquaredDistance2Dxy() <= -10.) || // put 2nd pair of parentheses to silence warning
265 (-10. <= SquaredDistance1Dx() <= 10.)) &&
266 // cppcheck-suppress duplicateExpression
267 !(-10. <= SquaredDistance1Dx() <= -10.));
268
269 // values are chosen in that way that all sub-filters of dummyFilter have to be called (see comment below)
270 // and so that dummyFilter is always true
271 spacePoint x1(0.0f, 0.0f, 0.0f);
272 spacePoint x2(0.5f, 0.0f, 0.0f);
273 spacePoint x3(2.0f, 0.0f, 0.0f);
274
278
279 dummyFilter.accept(x1, x2);
280 dummyFilter.accept(x1, x3);
281
282 // useless test as it tests if really unobserved
286
287 // Now switch observer, this is done recursively for each of the underlying filters
288 // One cannot switch the observer of an existing filter (as it would mean to switch type) so one has to create a new one!
289 // Note that if one filter is evaluated as false the other filter are not evaluated anymore and thus not observed!
290 auto observedDummyFilter = dummyFilter.observe(Observer());
291 observedDummyFilter.accept(x1, x2);
292 observedDummyFilter.accept(x1, x3);
293
296 //Note SquaredDistance1D is used twice in the filter so it is evaluated twice!
298 }
299
300
302 TEST_F(FilterTest, BypassableFilter)
303 {
304 bool bypassControl(false);
305 // Very verbose declaration, see below for convenient shortcuts
307 auto filter = nonBypassableFilter.bypass(bypassControl);
308 spacePoint x1(0.0f, 0.0f, 0.0f);
309 spacePoint x2(2.0f, 0.0f, 0.0f);
311
312 EXPECT_FALSE(filter.accept(x1, x2));
314
315 // The clang static analyser doesn't understand that the `filter` has a pointer to
316 // `bypassControl` and thus doesn't know that the variable is in fact used after being changed to `true` here.
317 // According to https://clang-analyzer.llvm.org/faq.html#exclude_code, the only way to suppress these
318 // warnings as of May 2023 is the following
319#ifndef __clang_analyzer__
320 bypassControl = true;
321#endif
322 EXPECT_TRUE(filter.accept(x1, x2));
324
325 }
326
327
329 TEST_F(FilterTest, Shortcuts)
330 {
331
332 spacePoint x1(0.0f, 0.0f, 0.0f);
333 spacePoint x2(0.5f, 0.0f, 0.0f);
334 spacePoint x3(2.0f, 0.0f, 0.0f);
335 spacePoint x4(1.0f, 0.0f, 0.0f);
336
337 auto filterSup = (SquaredDistance3D() < 1.) ;
338 EXPECT_TRUE(filterSup.accept(x1, x2));
339 EXPECT_FALSE(filterSup.accept(x1, x4));
340 EXPECT_FALSE(filterSup.accept(x1, x3));
341
342 auto filterMax = (SquaredDistance3D() <= 1.) ;
343 EXPECT_TRUE(filterMax.accept(x1, x2));
344 EXPECT_TRUE(filterMax.accept(x1, x4));
345 EXPECT_FALSE(filterMax.accept(x1, x3));
346
347
348 auto filterSup2 = (1 > SquaredDistance3D()) ;
349 EXPECT_TRUE(filterSup2.accept(x1, x2));
350 EXPECT_FALSE(filterSup2.accept(x1, x3));
351 EXPECT_FALSE(filterSup2.accept(x1, x4));
352
353 auto filterMax2 = (1 >= SquaredDistance3D()) ;
354 EXPECT_TRUE(filterMax2.accept(x1, x2));
355 EXPECT_FALSE(filterMax2.accept(x1, x3));
356 EXPECT_TRUE(filterMax2.accept(x1, x4));
357
358 auto filterInf = (SquaredDistance3D() > 1.) ;
359 EXPECT_TRUE(filterInf.accept(x1, x3));
360 EXPECT_FALSE(filterInf.accept(x1, x2));
361 EXPECT_FALSE(filterInf.accept(x1, x4));
362
363 auto filterMin = (SquaredDistance3D() >= 1.) ;
364 EXPECT_TRUE(filterMin.accept(x1, x3));
365 EXPECT_FALSE(filterMin.accept(x1, x2));
366 EXPECT_TRUE(filterMin.accept(x1, x4));
367
368 auto filterInf2 = (1 < SquaredDistance3D()) ;
369 EXPECT_TRUE(filterInf2.accept(x1, x3));
370 EXPECT_FALSE(filterInf2.accept(x1, x2));
371 EXPECT_FALSE(filterInf2.accept(x1, x4));
372
373 auto filterMin2 = (1 <= SquaredDistance3D()) ;
374 EXPECT_TRUE(filterMin2.accept(x1, x3));
375 EXPECT_FALSE(filterMin2.accept(x1, x2));
376 EXPECT_TRUE(filterMin2.accept(x1, x4));
377
378 auto filterRange = (0. < SquaredDistance3D() < 1);
379 EXPECT_FALSE(filterRange.accept(x1, x1));
380 EXPECT_TRUE(filterRange.accept(x1, x2));
381 EXPECT_FALSE(filterRange.accept(x1, x3));
382 EXPECT_FALSE(filterRange.accept(x1, x4));
383
384 // cppcheck-suppress compareBoolExpressionWithInt
385 auto filterClosedRange = (0. <= SquaredDistance3D() <= 1);
386 EXPECT_TRUE(filterClosedRange.accept(x1, x1));
387 EXPECT_TRUE(filterClosedRange.accept(x1, x2));
388 EXPECT_FALSE(filterClosedRange.accept(x1, x3));
389 EXPECT_TRUE(filterClosedRange.accept(x1, x4));
390
391 }
392
393
395 TEST_F(FilterTest, BooleanOperations)
396 {
397
398
399 spacePoint x1(0.0f, 0.0f, 0.0f);
400 spacePoint x2(1.0f, 0.0f, 0.0f);
401 spacePoint x3(2.0f, 0.0f, 0.0f);
402
403 auto filter = !(SquaredDistance3D() > 1.);
404 EXPECT_TRUE(filter.accept(x1, x2));
405 EXPECT_TRUE(filter.accept(x1, x1));
406 EXPECT_FALSE(filter.accept(x1, x3));
407
408 auto filter2 =
409 !(SquaredDistance3D() > 1.) &&
410 !(SquaredDistance3D() < 1);
411 // i.e. SquaredDistance3D == 1
412 EXPECT_TRUE(filter2.accept(x1, x2));
413 EXPECT_FALSE(filter2.accept(x1, x1));
414 EXPECT_FALSE(filter2.accept(x1, x3));
415
416
417 auto filter3 =
418 (SquaredDistance3D() > 1.) ||
419 (SquaredDistance3D() < 1);
420 // i.e. SquaredDistance3D != 1
421 EXPECT_FALSE(filter3.accept(x1, x2));
422 EXPECT_TRUE(filter3.accept(x1, x1));
423 EXPECT_TRUE(filter3.accept(x1, x3));
424
425
426 }
427
428
430 TEST_F(FilterTest, ShortCircuitsEvaluation)
431 {
432 auto filter(
433 (SquaredDistance2Dxy() < 1).observeLeaf(Observer()) &&
434 (SquaredDistance3D() < 1).observeLeaf(Observer())
435 );
436
437 spacePoint x1(0.0f, 0.0f, 0.0f);
438 spacePoint x3(2.0f, 0.0f, 0.0f);
439
442
443 EXPECT_FALSE(filter.accept(x1, x3));
444 // since the pair x1, x3 does not satisfy the SquaredDistance2Dxy
445 // requirement, we do expect SquaredDistance2Dxy evaluated once:
447 // and SquaredDistance3D not evaluated at all
449
450 EXPECT_TRUE(filter.accept(x1, x1));
451 // in this case Distance2Dxy is satisfied
453 // and Distance3D is evaluated
455
456 }
457
458
460 TEST_F(FilterTest, BooleanVariableShortcuts)
461 {
462 auto filter1(BooleanVariable() == true);
463 auto filter2(false == BooleanVariable());
464 spacePoint x1(0.0f, 0.0f, 0.0f);
465 spacePoint x2(1.0f, 0.0f, 0.0f);
466
467 EXPECT_TRUE(filter1.accept(x1, x1));
468 EXPECT_FALSE(filter1.accept(x1, x2));
469
470
471 EXPECT_FALSE(filter2.accept(x1, x1));
472 EXPECT_TRUE(filter2.accept(x1, x2));
473
474
475
476 }
477
478}
Represents a closed lower bounded set of arithmetic types.
Represents a closed set of arithmetic types.
Definition: ClosedRange.h:32
Represents an upper bounded set of arithmetic types.
This class is used to select pairs, triplets... of objects.
Definition: Filter.h:34
Represents a lower bounded set of arithmetic types.
Observer base class which can be used to evaluate the VXDTF2's Filters.
Definition: Observer.h:19
Represents a range of arithmetic types.
Definition: Range.h:29
Base class of the selection variable objects used for pair filtering.
Represents an upper bounded set of arithmetic types.
The most CPU efficient Observer for the VXDTF filter tools (even if useless).
Definition: VoidObserver.h:30
a small filter illustrating the behavior of a filter which is compatible with boolean comparisons
Definition: filters.cc:85
static float value(const spacePoint &p1, const spacePoint &p2)
value function does the actual calculation of this class.
Definition: filters.cc:91
static const std::string name(void)
return name of the class
Definition: filters.cc:88
Test class for Filter object.
Definition: filters.cc:138
this observer does simply count the number of times, the attached Filter was used
Definition: filters.cc:124
static void notify(const Var &, const otherTypes &...)
notify function is called by the filter, this one increases the counter.
Definition: filters.cc:128
a small filter illustrating the behavior of a distance1D-filter in X
Definition: filters.cc:70
static float value(const spacePoint &p1, const spacePoint &p2)
value function does the actual calculation of this class.
Definition: filters.cc:76
static const std::string name(void)
return name of the class
Definition: filters.cc:73
a small filter illustrating the behavior of a distance2D-filter in XY
Definition: filters.cc:54
static float value(const spacePoint &p1, const spacePoint &p2)
value function does the actual calculation of this class.
Definition: filters.cc:60
static const std::string name(void)
return name of the class
Definition: filters.cc:57
a small filter illustrating the behavior of a distance3D-filter
Definition: filters.cc:37
static float value(const spacePoint &p1, const spacePoint &p2)
value function does the actual calculation of this class.
Definition: filters.cc:43
static const std::string name(void)
return name of the class
Definition: filters.cc:40
small class counting usage.
Definition: filters.cc:100
static int N
counter.
Definition: filters.cc:102
~counter()
constructor.
Definition: filters.cc:104
just a small proto-container storing coordinates
Definition: filters.cc:24
spacePoint(const spacePoint &)=delete
private copy constructor to test that all the arguments are passed by reference.
spacePoint(float x, float y, float z)
Constructor accepting coordinates.
Definition: filters.cc:27
std::map< ExpRun, std::pair< double, double > > filter(const std::map< ExpRun, std::pair< double, double > > &runs, double cut, std::map< ExpRun, std::pair< double, double > > &runsRemoved)
filter events to remove runs shorter than cut, it stores removed runs in runsRemoved
Definition: Splitter.cc:38
Abstract base class for different kinds of events.
STL namespace.