9 #include <analysis/VariableManager/Manager.h>
10 #include <analysis/dataobjects/Particle.h>
12 #include <framework/logging/Logger.h>
13 #include <framework/utilities/Conversion.h>
14 #include <framework/utilities/GeneralCut.h>
16 #include <boost/algorithm/string.hpp>
24 Variable::Manager::~Manager() =
default;
35 std::set<std::string> aliasesSeen;
36 for (
auto aliasIter = m_alias.find(name); aliasIter != m_alias.end(); aliasIter = m_alias.find(name)) {
37 const auto [it, added] = aliasesSeen.insert(name);
39 B2FATAL(
"Encountered a loop in the alias definitions between the aliases "
40 << boost::algorithm::join(aliasesSeen,
", "));
42 name = aliasIter->second;
44 auto mapIter = m_variables.find(name);
45 if (mapIter == m_variables.end()) {
46 if (!createVariable(name))
return nullptr;
47 mapIter = m_variables.find(name);
48 if (mapIter == m_variables.end())
return nullptr;
50 return mapIter->second.get();
56 std::vector<const Variable::Manager::Var*> variable_pointers;
57 for (
auto& variable : variables) {
58 const Var* x = getVariable(variable);
60 B2WARNING(
"Couldn't find variable " << variable <<
" via the Variable::Manager. Check the name!");
62 variable_pointers.push_back(x);
64 return variable_pointers;
72 assertValidName(alias);
74 if (m_alias.find(alias) != m_alias.end()) {
75 if (variable == m_alias[alias]) {
return true; }
76 B2WARNING(
"An alias with the name '" << alias <<
"' exists and is set to '" << m_alias[alias] <<
"', setting it to '" << variable <<
77 "'. Be aware: only the last alias defined before processing the events will be used!");
78 m_alias[alias] = variable;
82 if (m_variables.find(alias) != m_variables.end()) {
83 B2ERROR(
"Variable with the name '" << alias <<
"' exists already, cannot add it as an alias!");
87 m_alias.insert(std::make_pair(alias, variable));
94 long unsigned int longest_alias_size = 0;
95 for (
const auto& a : m_alias) {
96 if (a.first.length() > longest_alias_size) {
97 longest_alias_size = a.first.length();
100 B2INFO(
"=====================================");
101 B2INFO(
"The following aliases are registered:");
102 for (
const auto& a : m_alias) {
103 B2INFO(std::string(a.first, 0, longest_alias_size) << std::string(longest_alias_size - a.first.length(),
104 ' ') <<
" --> " << a.second);
106 B2INFO(
"=====================================");
112 assertValidName(collection);
114 if (m_collection.find(collection) != m_collection.end()) {
115 B2WARNING(
"Another collection with the name'" << collection <<
"' is already set! I overwrite it!");
116 m_collection[collection] = variables;
120 if (m_variables.find(collection) != m_variables.end()) {
121 B2ERROR(
"Variable with the name '" << collection <<
"' exists already, won't add it as an collection!");
125 m_collection.insert(std::make_pair(collection, variables));
133 return m_collection[collection];
140 std::vector<std::string> temp;
142 for (
const auto& var : variables) {
143 auto it = m_collection.find(var);
144 if (it != m_collection.end()) {
145 temp.insert(temp.end(), it->second.begin(), it->second.end());
157 const static std::regex allowedNameRegex(
"^[a-zA-Z0-9_]*$");
159 if (!std::regex_match(name, allowedNameRegex)) {
160 B2FATAL(
"Variable '" << name <<
161 "' contains forbidden characters! Only alphanumeric characters plus underscores (_) are allowed for variable names.");
168 m_currentGroup = groupName;
173 std::match_results<std::string::const_iterator> results;
176 if (std::regex_match(name, results, std::regex(
"^([0-9]+\\.?[0-9]*)$"))) {
177 float float_number = std::stof(results[1]);
178 auto func = [float_number](
const Particle*) ->
double {
181 m_variables[name] = std::make_shared<Var>(name, func, std::string(
"Returns number ") + name);
186 if (std::regex_match(name, results, std::regex(
"^([a-zA-Z0-9_]*)\\((.*)\\)$"))) {
188 std::string functionName = results[1];
189 boost::algorithm::trim(functionName);
191 for (
auto& str : functionArguments) {
192 boost::algorithm::trim(str);
196 auto parameterIter = m_parameter_variables.find(functionName);
197 if (parameterIter != m_parameter_variables.end()) {
199 std::vector<double> arguments;
200 for (
auto& arg : functionArguments) {
202 number = Belle2::convertString<double>(arg);
203 arguments.push_back(number);
205 auto pfunc = parameterIter->second->function;
206 auto func = [pfunc, arguments](
const Particle * particle) ->
double {
return pfunc(particle, arguments); };
207 m_variables[name] = std::make_shared<Var>(name, func, parameterIter->second->description, parameterIter->second->group);
213 auto metaIter = m_meta_variables.find(functionName);
214 if (metaIter != m_meta_variables.end()) {
215 auto func = metaIter->second->function(functionArguments);
216 m_variables[name] = std::make_shared<Var>(name, func, metaIter->second->description, metaIter->second->group);
221 B2FATAL(
"Encountered bad variable name '" << name <<
"'. Maybe you misspelled it?");
227 const std::string& description)
230 B2FATAL(
"No function provided for variable '" << name <<
"'.");
233 assertValidName(name);
235 auto mapIter = m_variables.find(name);
236 if (mapIter == m_variables.end()) {
237 auto var = std::make_shared<Var>(name, f, description, m_currentGroup);
238 B2DEBUG(19,
"Registered Variable " << name);
239 m_variables[name] = var;
240 m_variablesInRegistrationOrder.push_back(var.get());
242 B2FATAL(
"A variable named '" << name <<
"' was already registered! Note that all variables need a unique name!");
247 const std::string& description)
250 B2FATAL(
"No function provided for variable '" << name <<
"'.");
253 auto mapIter = m_parameter_variables.find(name);
254 if (mapIter == m_parameter_variables.end()) {
255 auto var = std::make_shared<ParameterVar>(name, f, description, m_currentGroup);
256 std::string rawName = name.substr(0, name.find(
'('));
257 assertValidName(rawName);
258 B2DEBUG(19,
"Registered parameter Variable " << rawName);
259 m_parameter_variables[rawName] = var;
260 m_variablesInRegistrationOrder.push_back(var.get());
262 B2FATAL(
"A variable named '" << name <<
"' was already registered! Note that all variables need a unique name!");
267 const std::string& description)
270 B2FATAL(
"No function provided for variable '" << name <<
"'.");
273 auto mapIter = m_meta_variables.find(name);
274 if (mapIter == m_meta_variables.end()) {
275 auto var = std::make_shared<MetaVar>(name, f, description, m_currentGroup);
276 std::string rawName = name.substr(0, name.find(
'('));
277 assertValidName(rawName);
278 B2DEBUG(19,
"Registered meta Variable " << rawName);
279 m_meta_variables[rawName] = var;
280 m_variablesInRegistrationOrder.push_back(var.get());
282 B2FATAL(
"A variable named '" << name <<
"' was already registered! Note that all variables need a unique name!");
287 const std::string& description)
289 auto varIter = m_deprecated.find(name);
290 if (varIter == m_deprecated.end())
291 m_deprecated.insert(std::make_pair(name, std::make_pair(make_fatal, description)));
293 B2FATAL(
"There seem to be two calls to deprecate the variable: Please remove one.");
295 auto mapIter = m_variables.find(name);
296 if (mapIter != m_variables.end()) {
298 mapIter->second.get()->extendDescriptionString(
"\n\n.. warning:: ");
300 mapIter->second.get()->extendDescriptionString(
"\n\n.. note:: ");
302 mapIter->second.get()->extendDescriptionString(
".. deprecated:: " + version +
"\n " + description);
309 auto varIter = m_deprecated.find(name);
311 if (varIter == m_deprecated.end())
314 bool make_fatal = varIter->second.first;
315 std::string message = varIter->second.second;
317 B2FATAL(
"Variable " << name <<
" is deprecated. " << message);
319 B2WARNING(
"Variable " << name <<
" is deprecated. " << message);
326 std::vector<std::string> names;
327 for (
const VarBase* var : m_variablesInRegistrationOrder) {
328 names.push_back(var->name);
335 std::vector<std::string> names;
336 for (
auto al : m_alias) names.push_back(al.first);
342 const Var* var = getVariable(varName);
344 throw std::runtime_error(
"Variable::Manager::evaluate(): variable '" + varName +
"' not found!");
348 return var->function(p);
Class to store reconstructed particles.
Global list of available variables.
std::function< double(const Particle *, const std::vector< double > &)> ParameterFunctionPtr
parameter functions stored take a const Particle*, const std::vector<double>& and return double.
std::vector< std::string > getAliasNames() const
Return a list of all variable alias names (in reverse order added).
void registerVariable(const std::string &name, const Manager::FunctionPtr &f, const std::string &description)
Register a variable.
std::vector< std::string > resolveCollections(const std::vector< std::string > &variables)
Resolve Collection Returns variable names corresponding to the given collection or if it is not a col...
const Var * getVariable(std::string name)
Get the variable belonging to the given key.
void deprecateVariable(const std::string &name, bool make_fatal, const std::string &version, const std::string &description)
Make a variable deprecated.
std::vector< const Belle2::Variable::Manager::VarBase * > getVariables() const
Return list of all variables (in order registered).
static Manager & Instance()
get singleton instance.
void printAliases()
Print existing aliases.
bool createVariable(const std::string &name)
Creates and registers a concrete variable (Var) from a MetaVar, ParameterVar or numeric constant.
void assertValidName(const std::string &name)
Abort with B2FATAL if name is not a valid name for a variable.
std::function< FunctionPtr(const std::vector< std::string > &)> MetaFunctionPtr
meta functions stored take a const std::vector<std::string>& and return a FunctionPtr.
std::vector< std::string > getNames() const
Return list of all variable names (in order registered).
std::function< double(const Particle *)> FunctionPtr
NOTE: the python interface is documented manually in analysis/doc/Variables.rst (because we use ROOT ...
void setVariableGroup(const std::string &groupName)
All variables registered after VARIABLE_GROUP(groupName) will be added to this group.
std::vector< std::string > getCollection(const std::string &collection)
Get Collection Returns variable names corresponding to the given collection.
bool addAlias(const std::string &alias, const std::string &variable)
Add alias Return true if the alias was successfully added.
bool addCollection(const std::string &collection, const std::vector< std::string > &variables)
Add collection Return true if the collection was successfully added.
void checkDeprecatedVariable(const std::string &name)
Check if a variable is deprecated.
double evaluate(const std::string &varName, const Particle *p)
evaluate variable 'varName' on given Particle.
std::vector< std::string > splitOnDelimiterAndConserveParenthesis(std::string str, char delimiter, char open, char close)
Split into std::vector on delimiter ignoring delimiters between parenthesis.
Abstract base class for different kinds of events.
Base class for information common to all types of variables.
A variable returning a floating-point value for a given Particle.