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