Belle II Software light-2607-kasei
NodeFactory Class Reference

Wrapper class for static node compile functions. More...

#include <NodeFactory.h>

Static Public Member Functions

template<class AVariableManager>
static std::unique_ptr< const AbstractBooleanNode< AVariableManager > > compile_boolean_node (Nodetuple tuple)
 This template function creates a boolean node from a boost::python::tuple The Python Parser encodes the node type as int as the first argument of each tuple.
 
template<class AVariableManager>
static std::unique_ptr< const AbstractExpressionNode< AVariableManager > > compile_expression_node (Nodetuple tuple)
 This template function creates a ExpressionNode from a boost::python::tuple The Python Parser encodes the node type as int in the first argument of each tuple.
 

Detailed Description

Wrapper class for static node compile functions.

Definition at line 64 of file NodeFactory.h.

Member Function Documentation

◆ compile_boolean_node()

template<class AVariableManager>
static std::unique_ptr< const AbstractBooleanNode< AVariableManager > > compile_boolean_node ( Nodetuple tuple)
inlinestatic

This template function creates a boolean node from a boost::python::tuple The Python Parser encodes the node type as int as the first argument of each tuple.

Node types are decoded via the NodeType enum defined in framework/utilities/include/AbstractNodes.h e.g (2, (11, True)) is a UnaryRelationalNode (nodetype value 2), which has a BooleanNode(nodetype value 11) as a child. List of Nodes:

Definition at line 80 of file NodeFactory.h.

81 {
82 if (py::len(tuple) == 0) B2FATAL("BooleanNode tuple is empty, this is invalid.");
83 // First argument of every NodeTuple is an integer indicating the NodeType
84 NodeType node_type = static_cast<NodeType>(static_cast<int>(py::extract<int>(tuple[0])));
85
86 if (node_type == NodeType::UnaryBooleanNode) {
87 // Extract first child tuple
88 if (py::len(tuple) != 4) B2FATAL("UnaryBooleanNode tuple has to have length 4." << LogVar("actual length", py::len(tuple)));
89 Nodetuple child = static_cast<const py::tuple>(tuple[1]);
90 bool negation = py::extract<bool>(tuple[2]);
91 bool bracketized = py::extract<bool>(tuple[3]);
92 return std::unique_ptr<const AbstractBooleanNode<AVariableManager>>(new UnaryBooleanNode<AVariableManager>(child, negation,
93 bracketized));
94
95 } else if (node_type == NodeType::BinaryBooleanNode) {
96 if (py::len(tuple) != 4) B2FATAL("BinaryBooleanNode tuple has to have length 4." << LogVar("actual length", py::len(tuple)));
97 Nodetuple left_node = static_cast<const py::tuple>(tuple[1]);
98 Nodetuple right_node = static_cast<const py::tuple>(tuple[2]);
99 BooleanOperator boperator = static_cast<BooleanOperator>(static_cast<int>(py::extract<int>(tuple[3])));
100 return std::unique_ptr<const AbstractBooleanNode<AVariableManager>>(new BinaryBooleanNode<AVariableManager>(left_node, right_node,
101 boperator));
102 } else if (node_type == NodeType::UnaryRelationalNode) {
103 if (py::len(tuple) != 2) B2FATAL("UnaryRelationalNode tuple has to have length 2." << LogVar("actual length", py::len(tuple)));
104 Nodetuple node = static_cast<const py::tuple>(tuple[1]);
105 return std::unique_ptr<const AbstractBooleanNode<AVariableManager>>(new UnaryRelationalNode<AVariableManager>(node));
106 } else if (node_type == NodeType::BinaryRelationalNode) {
107 if (py::len(tuple) != 4) B2FATAL("BinaryRelationalNode tuple has to have length 4." << LogVar("actual length", py::len(tuple)));
108 Nodetuple left_node = static_cast<const py::tuple>(tuple[1]);
109 Nodetuple right_node = static_cast<const py::tuple>(tuple[2]);
110 ComparisonOperator coperator = static_cast<ComparisonOperator>(static_cast<int>(py::extract<int>(tuple[3])));
111 return std::unique_ptr<const AbstractBooleanNode<AVariableManager>>(new BinaryRelationalNode<AVariableManager>(left_node,
112 right_node, coperator));
113 } else if (node_type == NodeType::TernaryRelationalNode) {
114 if (py::len(tuple) != 6) B2FATAL("TernaryRelationalNode tuple has to have length 6." << LogVar("actual length", py::len(tuple)));
115 Nodetuple left_node = static_cast<const py::tuple>(tuple[1]);
116 Nodetuple center_node = static_cast<const py::tuple>(tuple[2]);
117 Nodetuple right_node = static_cast<const py::tuple>(tuple[3]);
118 ComparisonOperator lc_coperator = static_cast<ComparisonOperator>(static_cast<int>(py::extract<int>(tuple[4])));
119 ComparisonOperator cr_coperator = static_cast<ComparisonOperator>(static_cast<int>(py::extract<int>(tuple[5])));
120
121 return std::unique_ptr<const AbstractBooleanNode<AVariableManager>>(new TernaryRelationalNode<AVariableManager>(left_node,
122 center_node, right_node,
123 lc_coperator, cr_coperator));
124 } else {
125 throw std::runtime_error("error NodeFactory::compile_boolean_node: got invalid boolean NodeType.");
126 }
127 }
NodeType
Enum of possible Nodes in parsing tree.
ComparisonOperator
Enum for decoding the comparison operator type.
BooleanOperator
Enum for decoding the boolean operator type.

◆ compile_expression_node()

template<class AVariableManager>
static std::unique_ptr< const AbstractExpressionNode< AVariableManager > > compile_expression_node ( Nodetuple tuple)
inlinestatic

This template function creates a ExpressionNode from a boost::python::tuple The Python Parser encodes the node type as int in the first argument of each tuple.

Node types are decoded via the NodeType enum defined in framework/utilities/include/AbstractNodes.h e.g (9, 1.2) is a DataNode<double> with value 1.2 List of Nodes:

Definition at line 141 of file NodeFactory.h.

142 {
143 if (py::len(tuple) == 0) B2FATAL("ExpressionNode tuple is empty, this is invalid.");
144
145 // int is extracted from the py::tuple and cast as NodeTuple enum
146 NodeType node_type = static_cast<NodeType>(static_cast<int>(py::extract<int>(tuple[0])));
147 if (node_type == NodeType::UnaryExpressionNode) {
148 if (py::len(tuple) != 4) B2FATAL("UnaryExpression nodetuple has to have length 4." << LogVar("actual length", py::len(tuple)));
149 Nodetuple node = static_cast<const py::tuple>(tuple[1]);
150 bool unary_minus = py::extract<bool>(tuple[2]);
151 bool parenthesized = py::extract<bool>(tuple[3]);
152 return std::unique_ptr<const AbstractExpressionNode<AVariableManager>>(new UnaryExpressionNode<AVariableManager>(node,
153 unary_minus, parenthesized));
154 } else if (node_type == NodeType::BinaryExpressionNode) {
155 if (py::len(tuple) != 4) B2FATAL("BinaryExpression nodetuple has to have length 4." << LogVar("actual length", py::len(tuple)));
156 Nodetuple left_node = static_cast<const py::tuple>(tuple[1]);
157 Nodetuple right_node = static_cast<const py::tuple>(tuple[2]);
158 ArithmeticOperation aoperation = static_cast<ArithmeticOperation>(static_cast<int>(py::extract<int>(tuple[3])));
159 return std::unique_ptr<const AbstractExpressionNode<AVariableManager>>(new BinaryExpressionNode<AVariableManager>(left_node,
160 right_node,
161 aoperation));
162 } else if (node_type == NodeType::IntegerNode) {
163 if (py::len(tuple) != 2) B2FATAL("IntegerNode nodetuple has to have length 2." << LogVar("actual length", py::len(tuple)));
164 double d = py::extract<double>(tuple[1]);
165 if (std::numeric_limits<int>::min() <= d && d <= std::numeric_limits<int>::max()) {
166 int i = py::extract<int>(tuple[1]);
167 return std::unique_ptr<const AbstractExpressionNode<AVariableManager>>(new DataNode<AVariableManager, int>(i));
168 } else {
169 B2WARNING("Overflow for integer constant in cut detected. Create Double Node instead.");
170 return std::unique_ptr<const AbstractExpressionNode<AVariableManager>>(new DataNode<AVariableManager, double>(d));
171 }
172 } else if (node_type == NodeType::DoubleNode) {
173 if (py::len(tuple) != 2) B2FATAL("DoubleNode nodetuple has to have length 2." << LogVar("actual length", py::len(tuple)));
174 // We have to check for inf and nan values.
175 // use python math functions to check
176 py::object math = py::import("math");
177 // Get tuple item as object
178 py::object data = static_cast<py::object>(tuple[1]);
179 if (py::extract<bool>(math.attr("isinf")(data))) {
180 // Extract sign of inf float object
181 double inf_sign = py::extract<double>(math.attr("copysign")(1.0, data));
182 double inf;
183 if (inf_sign > 0) {
184 inf = std::numeric_limits<double>::infinity();
185 } else {
186 inf = -1 * std::numeric_limits<double>::infinity();
187 }
188 return std::unique_ptr<const AbstractExpressionNode<AVariableManager>>(new DataNode<AVariableManager, double>(inf));
189 }
190 if (py::extract<bool>(math.attr("isnan")(data))) {
191 double nan = std::nan("");
192 return std::unique_ptr<const AbstractExpressionNode<AVariableManager>>(new DataNode<AVariableManager, double>(nan));
193 }
194 double d = py::extract<double>(tuple[1]);
195 return std::unique_ptr<const AbstractExpressionNode<AVariableManager>>(new DataNode<AVariableManager, double>(d));
196 } else if (node_type == NodeType::BooleanNode) {
197 if (py::len(tuple) != 2) B2FATAL("BooleanNode nodetuple has to have length 2." << LogVar("actual length", py::len(tuple)));
198 bool b = py::extract<bool>(tuple[1]);
199 return std::unique_ptr<const AbstractExpressionNode<AVariableManager>>(new DataNode<AVariableManager, bool>(b));
200 } else if (node_type == NodeType::IdentifierNode) {
201 if (py::len(tuple) != 2) B2FATAL("IdentifierNode nodetuple has to have length 2." << LogVar("actual length", py::len(tuple)));
202 // boost::python::extract<std::string> triggers a false-positive
203 // -Wmaybe-uninitialized in GCC.
204#if defined(__GNUC__) && !defined(__clang__)
205#pragma GCC diagnostic push
206#pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
207#endif
208 std::string identifier = py::extract<std::string>(tuple[1]);
209#if defined(__GNUC__) && !defined(__clang__)
210#pragma GCC diagnostic pop
211#endif
212 return std::unique_ptr<const AbstractExpressionNode<AVariableManager>>(new IdentifierNode<AVariableManager>(identifier));
213 } else if (node_type == NodeType::FunctionNode) {
214 if (py::len(tuple) != 3) B2FATAL("FunctionNode nodetuple has to have length 3." << LogVar("actual length", py::len(tuple)));
215
216 // boost::python::extract<std::string> triggers a false-positive
217 // -Wmaybe-uninitialized in GCC.
218#if defined(__GNUC__) && !defined(__clang__)
219#pragma GCC diagnostic push
220#pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
221#endif
222 // Extract functionName as second argument of the tuple
223 std::string functionName = py::extract<std::string>(tuple[1]);
224
225 // Extract argument tuple
226 std::string argument = py::extract<std::string>(tuple[2]);
227#if defined(__GNUC__) && !defined(__clang__)
228#pragma GCC diagnostic pop
229#endif
230 boost::algorithm::trim(argument);
231 // Define vector for function arguments
232 std::vector<std::string> functionArguments = splitOnDelimiterAndConserveParenthesis(argument, ',', '(', ')');
233 for (auto& str : functionArguments) {
234 boost::algorithm::trim(str);
235 if (str.empty()) {
236 B2WARNING("Empty parameter for metavariable '" << functionName << "' in cut.");
237 }
238 }
239
240 return std::unique_ptr<const AbstractExpressionNode<AVariableManager>>(new FunctionNode<AVariableManager>(functionName,
241 functionArguments));
242 } else {
243 throw std::runtime_error("error NodeFactory::compile_expression_node: got invalid expression NodeType.");
244 }
245 }
std::vector< std::string > splitOnDelimiterAndConserveParenthesis(const std::string &str, char delimiter, char open, char close)
Split into std::vector on delimiter ignoring delimiters between parenthesis.
Definition CutHelpers.cc:81
ArithmeticOperation
Enum for decoding the comparison operator type.

The documentation for this class was generated from the following file: