9 #include <analysis/modules/VariablesToEventBasedTree/VariablesToEventBasedTreeModule.h>
11 #include <analysis/dataobjects/ParticleList.h>
12 #include <analysis/VariableManager/Manager.h>
13 #include <analysis/VariableManager/Utility.h>
14 #include <framework/logging/Logger.h>
15 #include <framework/pcore/ProcHandler.h>
16 #include <framework/utilities/MakeROOTCompatible.h>
17 #include <framework/utilities/RootFileCreationManager.h>
18 #include <framework/core/ModuleParam.templateDetails.h>
33 setDescription(
"Calculate variables specified by the user for a given ParticleList and save them into a TTree. The Tree is event-based, meaning that the variables of each candidate for each event are saved in an array of a branch of the Tree.");
34 setPropertyFlags(c_ParallelProcessingCertified | c_TerminateInAllProcesses);
36 vector<string> emptylist;
37 addParam(
"particleList", m_particleList,
38 "Name of particle list with reconstructed particles. An empty ParticleList is not supported. Use the VariablesToNtupleModule for this use-case",
40 addParam(
"variables", m_variables,
41 "List of variables (or collections) to save for each candidate. Variables are taken from Variable::Manager, and are identical to those available to e.g. ParticleSelector.",
44 addParam(
"event_variables", m_event_variables,
45 "List of variables (or collections) to save for each event. Variables are taken from Variable::Manager, and are identical to those available to e.g. ParticleSelector. Only event-based variables are allowed here.",
48 addParam(
"fileName", m_fileName,
"Name of ROOT file for output.",
string(
"VariablesToEventBasedTree.root"));
49 addParam(
"treeName", m_treeName,
"Name of the NTuple in the saved file.",
string(
"tree"));
50 addParam(
"maxCandidates", m_maxCandidates,
"The maximum number of candidates in the ParticleList per entry of the Tree.", 100u);
52 std::tuple<std::string, std::map<int, unsigned int>> default_sampling{
"", {}};
53 addParam(
"sampling", m_sampling,
54 "Tuple of variable name and a map of integer values and inverse sampling rate. E.g. (signal, {1: 0, 0:10}) selects all signal events and every 10th background event. Variable must be event-based.",
58 void VariablesToEventBasedTreeModule::initialize()
60 m_eventMetaData.isRequired();
65 m_file = RootFileCreationManager::getInstance().getFile(m_fileName);
67 B2ERROR(
"Could not create file \"" << m_fileName <<
68 "\". Please set a valid root output file name (\"fileName\" module parameter).");
75 if (m_file->Get(m_treeName.c_str())) {
76 B2FATAL(
"Tree with the name " << m_treeName <<
" already exists in the file " << m_fileName);
80 m_variables = Variable::Manager::Instance().resolveCollections(m_variables);
81 m_event_variables = Variable::Manager::Instance().resolveCollections(m_event_variables);
83 m_tree.registerInDataStore(m_fileName + m_treeName, DataStore::c_DontWriteOut);
84 m_tree.construct(m_treeName.c_str(),
"");
86 m_values.resize(m_variables.size());
87 m_event_values.resize(m_event_variables.size());
89 m_tree->get().Branch(
"__event__", &m_event,
"__event__/I");
90 m_tree->get().Branch(
"__run__", &m_run,
"__run__/I");
91 m_tree->get().Branch(
"__experiment__", &m_experiment,
"__experiment__/I");
92 m_tree->get().Branch(
"__production__", &m_production,
"__production__/I");
93 m_tree->get().Branch(
"__ncandidates__", &m_ncandidates,
"__ncandidates__/I");
94 m_tree->get().Branch(
"__weight__", &m_weight,
"__weight__/F");
96 for (
unsigned int i = 0; i < m_event_variables.size(); ++i) {
97 auto varStr = m_event_variables[i];
99 if (Variable::isCounterVariable(varStr)) {
100 B2WARNING(
"The counter '" << varStr
101 <<
"' is handled automatically by VariablesToEventBasedTree, you don't need to add it.");
110 B2ERROR(
"Variable '" << varStr <<
"' is not available in Variable::Manager!");
112 m_event_functions.push_back(var->function);
116 for (
unsigned int i = 0; i < m_variables.size(); ++i) {
117 auto varStr = m_variables[i];
118 m_values[i].resize(m_maxCandidates);
125 B2ERROR(
"Variable '" << varStr <<
"' is not available in Variable::Manager!");
127 m_functions.push_back(var->function);
131 m_sampling_name = std::get<0>(m_sampling);
132 m_sampling_rates = std::get<1>(m_sampling);
134 if (m_sampling_name !=
"") {
135 m_sampling_variable = Variable::Manager::Instance().getVariable(m_sampling_name);
136 if (m_sampling_variable ==
nullptr) {
137 B2FATAL(
"Couldn't find sample variable " << m_sampling_name <<
" via the Variable::Manager. Check the name!");
139 for (
const auto& pair : m_sampling_rates)
140 m_sampling_counts[pair.first] = 0;
142 m_sampling_variable =
nullptr;
148 float VariablesToEventBasedTreeModule::getInverseSamplingRateWeight()
151 if (m_sampling_variable ==
nullptr)
154 long target = std::lround(m_sampling_variable->function(
nullptr));
155 if (m_sampling_rates.find(target) != m_sampling_rates.end() and m_sampling_rates[target] > 0) {
156 m_sampling_counts[target]++;
157 if (m_sampling_counts[target] % m_sampling_rates[target] != 0)
160 m_sampling_counts[target] = 0;
161 return m_sampling_rates[target];
168 void VariablesToEventBasedTreeModule::event()
171 m_event = m_eventMetaData->getEvent();
172 m_run = m_eventMetaData->getRun();
173 m_experiment = m_eventMetaData->getExperiment();
174 m_production = m_eventMetaData->getProduction();
177 m_ncandidates = particlelist->getListSize();
178 m_weight = getInverseSamplingRateWeight();
180 for (
unsigned int iVar = 0; iVar < m_event_functions.size(); iVar++) {
181 m_event_values[iVar] = m_event_functions[iVar](
nullptr);
183 for (
unsigned int iPart = 0; iPart < m_ncandidates; iPart++) {
185 if (iPart >= m_maxCandidates) {
186 B2WARNING(
"Maximum number of candidates exceeded in VariablesToEventBasedTree module. I will skip additional candidates");
190 const Particle* particle = particlelist->getParticle(iPart);
191 for (
unsigned int iVar = 0; iVar < m_functions.size(); iVar++) {
192 m_values[iVar][iPart] = m_functions[iVar](particle);
195 m_tree->get().Fill();
199 void VariablesToEventBasedTreeModule::terminate()
201 if (!ProcHandler::parallelProcessingUsed() or ProcHandler::isOutputProcess()) {
202 B2INFO(
"Writing TTree " << m_treeName);
203 TDirectory::TContext directoryGuard(m_file.get());
204 m_tree->write(m_file.get());
206 const bool writeError = m_file->TestBit(TFile::kWriteError);
208 B2FATAL(
"A write error occurred while saving '" << m_fileName <<
"', please check if enough disk space is available.");
In the store you can park objects that have to be accessed by various modules.
Class to store reconstructed particles.
bool isRequired(const std::string &name="")
Ensure this array/object has been registered previously.
Type-safe access to single objects in the data store.
Module to calculate variables specified by the user for a given ParticleList and save them into a TTr...
std::string makeROOTCompatible(std::string str)
Remove special characters that ROOT dislikes in branch names, e.g.
#define REG_MODULE(moduleName)
Register the given module (without 'Module' suffix) with the framework.
Abstract base class for different kinds of events.
A variable returning a floating-point value for a given Particle.