Belle II Software prerelease-10-00-00a
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
230 Filter< SquaredDistance3D, Range<double, double>, VoidObserver > filter(Range<double, double>(0., 1.));
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
246 Filter< SquaredDistance3D, Range<double, double>, VoidObserver > unobservedFilter(Range<double, double>(0., 1.));
247
248 Filter< SquaredDistance3D, Range<double, double>, Observer > filter(unobservedFilter);
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
306 Filter< SquaredDistance3D, Range<double, double>, Observer > nonBypassableFilter(Range<double, double>(0., 1.));
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 set of arithmetic types.
Definition ClosedRange.h:32
Represents a range of arithmetic types.
Definition Range.h:29
VoidObserver()
An empty constructor for an empty class.
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
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.