Belle II Software  release-06-01-15
variableManager.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 #include <analysis/VariableManager/Manager.h>
9 #include <analysis/VariableManager/Utility.h>
10 #include <analysis/dataobjects/Particle.h>
11 #include <framework/utilities/TestHelpers.h>
12 
13 #include <gtest/gtest.h>
14 
15 using namespace std;
16 using namespace Belle2;
17 using namespace Belle2::Variable;
18 namespace {
19 
21  double dummyVar(const Particle*) { return 42.0; }
22  double dummyVarWithParameters(const Particle*, const std::vector<double>& parameters)
23  {
24  double result = 0;
25  for (auto& x : parameters)
26  result += x;
27  return result;
28  }
29  Manager::FunctionPtr dummyMetaVar(const std::vector<std::string>& arguments)
30  {
31  std::string arg = arguments[0];
32  auto func = [arg](const Particle*) -> double {
33  return arg.size();
34  };
35  return func;
36  }
37 
39  TEST(VariableTest, ManagerDeathTest)
40  {
41 
42  EXPECT_B2FATAL(Manager::Instance().getVariable("THISDOESNTEXIST"));
43 
44  //this exists
45  const Manager::Var* pvar = Manager::Instance().getVariable("p");
46  EXPECT_TRUE(pvar != nullptr);
47 
48  //test special variable operations
49  const Manager::Var* daughterProductP = Manager::Instance().getVariable("daughterProductOf(p)");
50  EXPECT_TRUE(daughterProductP != nullptr);
51 
52  const Manager::Var* daughterSumP = Manager::Instance().getVariable("daughterSumOf(p)");
53  EXPECT_TRUE(daughterSumP != nullptr);
54 
55  const Manager::Var* daughter1P = Manager::Instance().getVariable("daughter(1, p)");
56  EXPECT_TRUE(daughter1P != nullptr);
57 
58  const Manager::Var* extraInfo = Manager::Instance().getVariable("extraInfo(signalProbability)");
59  EXPECT_TRUE(extraInfo != nullptr);
60 
61  const Manager::Var* nested = Manager::Instance().getVariable("daughterSumOf(daughter(1, extraInfo(signalProbability)))");
62  EXPECT_TRUE(nested != nullptr);
63 
64  EXPECT_B2FATAL(Manager::Instance().getVariable("funcDoesNotExist(p)"));
65 
66  EXPECT_B2FATAL(Manager::Instance().getVariable("daughterSumOf(daughter(1, ExtraInfoWrongName(signalProbability)))"));
67 
68  // Test collection
69  auto vec = Manager::Instance().resolveCollections({"myCollection"});
70  EXPECT_EQ(vec.size(), 1);
71  EXPECT_EQ(vec[0], "myCollection");
72  EXPECT_TRUE(Manager::Instance().addCollection("myCollection", {"p", "px", "py", "pz"}));
73 
74  auto vec2 = Manager::Instance().resolveCollections({"myCollection"});
75  EXPECT_EQ(vec2.size(), 4);
76  EXPECT_EQ(vec2[0], "p");
77  EXPECT_EQ(vec2[1], "px");
78  EXPECT_EQ(vec2[2], "py");
79  EXPECT_EQ(vec2[3], "pz");
80 
81  // Test alias
82  EXPECT_B2FATAL(Manager::Instance().getVariable("myAlias"));
83  Manager::Instance().addAlias("myAlias", "daughterSumOf(daughter(1, extraInfo(signalProbability)))");
84  const Manager::Var* aliasDoesExists = Manager::Instance().getVariable("myAlias");
85  EXPECT_TRUE(aliasDoesExists != nullptr);
86 
87  // aliases also should work recursively
88  auto& vm = Manager::Instance();
89  EXPECT_TRUE(vm.addAlias("myAliasAlias", "myAlias"));
90  // and it should resolve to the same variable as the original alias
91  EXPECT_EQ(aliasDoesExists, vm.getVariable("myAliasAlias"));
92 
93  // but we expect a fatal if there's a loop in alias definitions
94  EXPECT_TRUE(vm.addAlias("aliasLoop1", "aliasLoop2"));
95  EXPECT_TRUE(vm.addAlias("aliasLoop2", "aliasLoop3"));
96  EXPECT_TRUE(vm.addAlias("aliasLoop3", "aliasLoop4"));
97  EXPECT_TRUE(vm.addAlias("aliasLoop4", "aliasLoop1"));
98  EXPECT_B2FATAL(vm.getVariable("aliasLoop1"));
99  EXPECT_B2FATAL(vm.getVariable("aliasLoop3"));
100 
101  // redefine the alias with the same values is fine
102  EXPECT_NO_B2WARNING(Manager::Instance().addAlias("myAlias", "daughterSumOf(daughter(1, extraInfo(signalProbability)))"));
103  // redefine the alias with a different value gives an error
104  EXPECT_B2WARNING(Manager::Instance().addAlias("myAlias", "daughterSumOf(daughter(0, extraInfo(signalProbability)))"));
105  // creating an alias for a known variables doesn't work and gives an error
106  EXPECT_B2ERROR(Manager::Instance().addAlias("M", "daughterSumOf(daughter(1, extraInfo(signalProbability)))"));
107 
108  //re-registration not allowed
109  EXPECT_B2FATAL(Manager::Instance().registerVariable("p", (Manager::FunctionPtr)&dummyVar, "description"));
110 
111  EXPECT_B2FATAL(Manager::Instance().registerVariable("something", (Manager::FunctionPtr)nullptr, "blah"));
112 
113 
114  Manager::Instance().registerVariable("testingthedummyvar", (Manager::FunctionPtr)&dummyVar, "blah");
115  const Manager::Var* dummy = Manager::Instance().getVariable("testingthedummyvar");
116  ASSERT_NE(dummy, nullptr);
117  EXPECT_TRUE(dummy->description == "blah");
118  EXPECT_DOUBLE_EQ(dummy->function(nullptr), 42.0);
119 
120  //also test the macro (with other name)
121  REGISTER_VARIABLE("testingthedummyvar2", dummyVar, "something else");
122  dummy = Manager::Instance().getVariable("testingthedummyvar2");
123  ASSERT_NE(dummy, nullptr);
124  EXPECT_TRUE(dummy->description == "something else");
125  EXPECT_DOUBLE_EQ(dummy->function(nullptr), 42.0);
126 
127 
128  Manager::Instance().registerVariable("testingthedummyvarwithparameters(n)", (Manager::ParameterFunctionPtr)&dummyVarWithParameters,
129  "blah");
130  dummy = Manager::Instance().getVariable("testingthedummyvarwithparameters(3)");
131  ASSERT_NE(dummy, nullptr);
132  EXPECT_DOUBLE_EQ(dummy->function(nullptr), 3.0);
133  EXPECT_DOUBLE_EQ(Manager::Instance().getVariable("testingthedummyvarwithparameters(3)")->function(nullptr), 3.0);
134  EXPECT_DOUBLE_EQ(Manager::Instance().getVariable("testingthedummyvarwithparameters(3,5)")->function(nullptr), 8.0);
135  EXPECT_DOUBLE_EQ(Manager::Instance().getVariable("testingthedummyvarwithparameters(3,7,8)")->function(nullptr), 18.0);
136 
137  Manager::Instance().registerVariable("testingthedummymetavar(cut)", (Manager::MetaFunctionPtr)&dummyMetaVar,
138  "blah");
139  dummy = Manager::Instance().getVariable("testingthedummymetavar(1 < 2)");
140  ASSERT_NE(dummy, nullptr);
141  EXPECT_DOUBLE_EQ(dummy->function(nullptr), 5.0);
142  EXPECT_DOUBLE_EQ(Manager::Instance().getVariable("testingthedummymetavar(123)")->function(nullptr), 3.0);
143 
144 
145  //also test the macro (with other name)
146  REGISTER_VARIABLE("testingthedummyvarwithparameters2(n,m)", dummyVarWithParameters, "something else");
147  dummy = Manager::Instance().getVariable("testingthedummyvarwithparameters2(4,5)");
148  ASSERT_NE(dummy, nullptr);
149  EXPECT_DOUBLE_EQ(dummy->function(nullptr), 9.0);
150 
151  //test list
152  /*
153  for (const Manager::Var* v : Manager::Instance().getVariables()) {
154  B2WARNING(v->name);
155  }
156  */
157  EXPECT_TRUE(Manager::Instance().getVariables().size() > 0);
158 
159  //special characters are not allowed!
160  EXPECT_B2FATAL(Manager::Instance().registerVariable(" space", (Manager::FunctionPtr)dummyVar, "blah"));
161  EXPECT_B2FATAL(Manager::Instance().registerVariable("star*", (Manager::FunctionPtr)dummyVar, "blah"));
162  EXPECT_B2FATAL(Manager::Instance().registerVariable("*", (Manager::FunctionPtr)dummyVar, "blah"));
163 
164  //this is ok, though
165  Manager::Instance().registerVariable("abcdef0123945859432689_ZEFUEONHSUTNSXA", (Manager::FunctionPtr)dummyVar, "blah");
166  }
167 
168  TEST(VariableTest, Cut)
169  {
170  Manager::Instance().registerVariable("dummyvar", (Manager::FunctionPtr)&dummyVar, "blah");
171  Manager::Instance().registerVariable("dummymetavar(cut)", (Manager::MetaFunctionPtr)&dummyMetaVar, "blah");
172 
173  std::unique_ptr<Cut> a = Cut::compile("dummyvar > 1.0");
174  EXPECT_TRUE(a->check(nullptr));
175  a = Cut::compile("1.0 < dummyvar <= dummyvar");
176  EXPECT_TRUE(a->check(nullptr));
177 
178  a = Cut::compile("dummyvar < 100.0");
179  EXPECT_TRUE(a->check(nullptr));
180  a = Cut::compile("dummyvar <= dummyvar <= dummyvar");
181  EXPECT_TRUE(a->check(nullptr));
182 
183  a = Cut::compile("dummymetavar(123) < 100.0");
184  EXPECT_TRUE(a->check(nullptr));
185  a = Cut::compile("dummymetavar(1) <= dummymetavar(1<) <= dummymetavar(1<3)");
186  EXPECT_TRUE(a->check(nullptr));
187  }
188 
189 
190 } // namespace
This class implements a common way to implement cut/selection functionality for arbitrary objects.
Definition: GeneralCut.h:91
Class to store reconstructed particles.
Definition: Particle.h:74
std::function< double(const Particle *, const std::vector< double > &)> ParameterFunctionPtr
parameter functions stored take a const Particle*, const std::vector<double>& and return double.
Definition: Manager.h:110
std::function< FunctionPtr(const std::vector< std::string > &)> MetaFunctionPtr
meta functions stored take a const std::vector<std::string>& and return a FunctionPtr.
Definition: Manager.h:112
std::function< double(const Particle *)> FunctionPtr
NOTE: the python interface is documented manually in analysis/doc/Variables.rst (because we use ROOT ...
Definition: Manager.h:108
TEST(TestgetDetectorRegion, TestgetDetectorRegion)
Test Constructors.
Abstract base class for different kinds of events.
std::string description
Description of what this function does.
Definition: Manager.h:119
A variable returning a floating-point value for a given Particle.
Definition: Manager.h:133
FunctionPtr function
Pointer to function.
Definition: Manager.h:134