Belle II Software development
VariablesToHistogramModule.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
9#include <analysis/modules/VariablesToHistogram/VariablesToHistogramModule.h>
10
11// analysis
12#include <analysis/dataobjects/ParticleList.h>
13#include <analysis/VariableManager/Manager.h>
14
15// framework
16#include <framework/logging/Logger.h>
17#include <framework/pcore/ProcHandler.h>
18#include <framework/core/ModuleParam.templateDetails.h>
19#include <framework/core/Environment.h>
20#include <framework/utilities/MakeROOTCompatible.h>
21#include <framework/utilities/RootFileCreationManager.h>
22
23#include <memory>
24
25using namespace std;
26using namespace Belle2;
27
28// Register module in the framework
29REG_MODULE(VariablesToHistogram);
30
31
33 Module()
34{
35 //Set module properties
36 setDescription("Calculate variables specified by the user for a given ParticleList and save them into one or two dimensional histograms.");
38
39 std::vector<std::tuple<std::string, int, float, float>> emptylist;
40 std::vector<std::tuple<std::string, int, float, float, std::string, int, float, float>> emptylist_2d;
41 addParam("particleList", m_particleList,
42 "Name of particle list with reconstructed particles. If no list is provided the variables are saved once per event (only possible for event-type variables)",
43 std::string(""));
44 addParam("variables", m_variables,
45 "List of variables to save. Variables are taken from Variable::Manager, and are identical to those available to e.g. ParticleSelector.",
46 emptylist);
47 addParam("variables_2d", m_variables_2d,
48 "List of variable pairs to save. Variables are taken from Variable::Manager, and are identical to those available to e.g. ParticleSelector.",
49 emptylist_2d);
50
51 addParam("fileName", m_fileName, "Name of ROOT file for output. Can be overridden using the -o argument of basf2.",
52 string("VariablesToHistogram.root"));
53 addParam("directory", m_directory, "Directory for all histograms **inside** the file to allow for histograms from multiple "
54 "particlelists in the same file without conflicts", m_directory);
55 addParam("fileNameSuffix", m_fileNameSuffix, "The suffix of the output ROOT file to be appended before ``.root``.",
56 string(""));
57 addParam("ignoreCommandLineOverride", m_ignoreCommandLineOverride,
58 "Ignore override of file name via command line argument -o. Useful if you have multiple output modules in one path.", false);
59
60 m_file = nullptr;
61}
62
64{
65 if (not m_particleList.empty())
67
68 // override the output file name with what's been provided with the -o option
70 const std::string& outputFileArgument = Environment::Instance().getOutputFileOverride();
71 if (!outputFileArgument.empty())
72 m_fileName = outputFileArgument;
73 }
74
75 if (!m_fileNameSuffix.empty())
76 m_fileName = m_fileName.insert(m_fileName.rfind(".root"), m_fileNameSuffix);
77
78 // Check if we can access the given file
80 if (!m_file) return;
81 // Make sure we don't disturb the global directory for other modules, friggin side effects everywhere
82 TDirectory::TContext directoryGuard(m_file.get());
83 if (not m_directory.empty()) {
85 m_file->mkdir(m_directory.c_str());
86 m_file->cd(m_directory.c_str());
87 }
88
89 for (const auto& varTuple : m_variables) {
90 std::string varStr;
91 int varNbins = 0;
92 float low = 0;
93 float high = 0;
94 std::tie(varStr, varNbins, low, high) = varTuple;
95 std::string compatibleName = MakeROOTCompatible::makeROOTCompatible(varStr);
96
97 auto ptr = std::make_unique<StoreObjPtr<RootMergeable<TH1D>>>("", DataStore::c_Persistent);
98 ptr->registerInDataStore(m_fileName + m_directory + varStr, DataStore::c_DontWriteOut);
99 ptr->construct(compatibleName.c_str(), compatibleName.c_str(), varNbins, low, high);
100 m_hists.emplace_back(std::move(ptr));
101
102 //also collection function pointers
104 if (!var) {
105 B2ERROR("Variable '" << varStr << "' is not available in Variable::Manager!");
106 } else {
107 m_functions.push_back(var->function);
108 }
109 }
110
111 for (const auto& varTuple : m_variables_2d) {
112 std::string varStr1;
113 int varNbins1 = 0;
114 float low1 = 0;
115 float high1 = 0;
116 std::string varStr2;
117 int varNbins2 = 0;
118 float low2 = 0;
119 float high2 = 0;
120 std::tie(varStr1, varNbins1, low1, high1, varStr2, varNbins2, low2, high2) = varTuple;
121 std::string compatibleName1 = MakeROOTCompatible::makeROOTCompatible(varStr1);
122 std::string compatibleName2 = MakeROOTCompatible::makeROOTCompatible(varStr2);
123
124 auto ptr2d = std::make_unique<StoreObjPtr<RootMergeable<TH2D>>>("", DataStore::c_Persistent);
125 ptr2d->registerInDataStore(m_fileName + m_directory + varStr1 + varStr2, DataStore::c_DontWriteOut);
126 ptr2d->construct((compatibleName1 + compatibleName2).c_str(), (compatibleName1 + compatibleName2).c_str(),
127 varNbins1, low1, high1, varNbins2, low2, high2);
128 m_2d_hists.emplace_back(std::move(ptr2d));
129
130 //also collection function pointers
132 if (!var1) {
133 B2ERROR("Variable '" << varStr1 << "' is not available in Variable::Manager!");
134 } else {
135 m_functions_2d_1.push_back(var1->function);
136 }
137
138 //also collection function pointers
140 if (!var2) {
141 B2ERROR("Variable '" << varStr2 << "' is not available in Variable::Manager!");
142 } else {
143 m_functions_2d_2.push_back(var2->function);
144 }
145 }
146
147}
148
150{
151 unsigned int nVars = m_variables.size();
152 unsigned int nVars_2d = m_variables_2d.size();
153 std::vector<float> vars(nVars);
154 std::vector<float> vars_2d_1(nVars_2d);
155 std::vector<float> vars_2d_2(nVars_2d);
156
157 if (m_particleList.empty()) {
158 for (unsigned int iVar = 0; iVar < nVars; iVar++) {
159 if (std::holds_alternative<double>(m_functions[iVar](nullptr))) {
160 vars[iVar] = std::get<double>(m_functions[iVar](nullptr));
161 } else if (std::holds_alternative<int>(m_functions[iVar](nullptr))) {
162 vars[iVar] = std::get<int>(m_functions[iVar](nullptr));
163 } else if (std::holds_alternative<bool>(m_functions[iVar](nullptr))) {
164 vars[iVar] = std::get<bool>(m_functions[iVar](nullptr));
165 }
166 (*m_hists[iVar])->get().Fill(vars[iVar]);
167 }
168 for (unsigned int iVar = 0; iVar < nVars_2d; iVar++) {
169 if (std::holds_alternative<double>(m_functions_2d_1[iVar](nullptr))) {
170 vars_2d_1[iVar] = std::get<double>(m_functions_2d_1[iVar](nullptr));
171 } else if (std::holds_alternative<int>(m_functions_2d_1[iVar](nullptr))) {
172 vars_2d_1[iVar] = std::get<int>(m_functions_2d_1[iVar](nullptr));
173 } else if (std::holds_alternative<bool>(m_functions_2d_1[iVar](nullptr))) {
174 vars_2d_1[iVar] = std::get<bool>(m_functions_2d_1[iVar](nullptr));
175 }
176 if (std::holds_alternative<double>(m_functions_2d_2[iVar](nullptr))) {
177 vars_2d_2[iVar] = std::get<double>(m_functions_2d_2[iVar](nullptr));
178 } else if (std::holds_alternative<int>(m_functions_2d_2[iVar](nullptr))) {
179 vars_2d_2[iVar] = std::get<int>(m_functions_2d_2[iVar](nullptr));
180 } else if (std::holds_alternative<bool>(m_functions_2d_2[iVar](nullptr))) {
181 vars_2d_2[iVar] = std::get<bool>(m_functions_2d_2[iVar](nullptr));
182 }
183 (*m_2d_hists[iVar])->get().Fill(vars_2d_1[iVar], vars_2d_2[iVar]);
184 }
185
186 } else {
188 unsigned int nPart = particlelist->getListSize();
189 for (unsigned int iPart = 0; iPart < nPart; iPart++) {
190 const Particle* particle = particlelist->getParticle(iPart);
191 for (unsigned int iVar = 0; iVar < nVars; iVar++) {
192 if (std::holds_alternative<double>(m_functions[iVar](particle))) {
193 vars[iVar] = std::get<double>(m_functions[iVar](particle));
194 } else if (std::holds_alternative<int>(m_functions[iVar](particle))) {
195 vars[iVar] = std::get<int>(m_functions[iVar](particle));
196 } else if (std::holds_alternative<bool>(m_functions[iVar](particle))) {
197 vars[iVar] = std::get<bool>(m_functions[iVar](particle));
198 }
199 (*m_hists[iVar])->get().Fill(vars[iVar]);
200 }
201 for (unsigned int iVar = 0; iVar < nVars_2d; iVar++) {
202 if (std::holds_alternative<double>(m_functions_2d_1[iVar](particle))) {
203 vars_2d_1[iVar] = std::get<double>(m_functions_2d_1[iVar](particle));
204 } else if (std::holds_alternative<int>(m_functions_2d_1[iVar](particle))) {
205 vars_2d_1[iVar] = std::get<int>(m_functions_2d_1[iVar](particle));
206 } else if (std::holds_alternative<bool>(m_functions_2d_1[iVar](particle))) {
207 vars_2d_1[iVar] = std::get<bool>(m_functions_2d_1[iVar](particle));
208 }
209 if (std::holds_alternative<double>(m_functions_2d_2[iVar](particle))) {
210 vars_2d_2[iVar] = std::get<double>(m_functions_2d_2[iVar](particle));
211 } else if (std::holds_alternative<int>(m_functions_2d_2[iVar](particle))) {
212 vars_2d_2[iVar] = std::get<int>(m_functions_2d_2[iVar](particle));
213 } else if (std::holds_alternative<bool>(m_functions_2d_2[iVar](particle))) {
214 vars_2d_2[iVar] = std::get<bool>(m_functions_2d_2[iVar](particle));
215 }
216 (*m_2d_hists[iVar])->get().Fill(vars_2d_1[iVar], vars_2d_2[iVar]);
217 }
218 }
219 }
220}
221
223{
225 TDirectory::TContext directoryGuard(m_file.get());
226 if (not m_directory.empty()) {
227 m_file->cd(m_directory.c_str());
228 }
229 B2INFO("Writing Histograms to " << gDirectory->GetPath());
230 unsigned int nVars = m_variables.size();
231 for (unsigned int iVar = 0; iVar < nVars; iVar++) {
232 (*m_hists[iVar])->write(gDirectory);
233 }
234 unsigned int nVars_2d = m_variables_2d.size();
235 for (unsigned int iVar = 0; iVar < nVars_2d; iVar++) {
236 (*m_2d_hists[iVar])->write(gDirectory);
237 }
238
239 const bool writeError = m_file->TestBit(TFile::kWriteError);
240 m_file.reset();
241 if (writeError) {
242 B2FATAL("A write error occurred while saving '" << m_fileName << "', please check if enough disk space is available.");
243 }
244 }
245}
@ c_DontWriteOut
Object/array should be NOT saved by output modules.
Definition: DataStore.h:71
@ c_Persistent
Object is available during entire execution time.
Definition: DataStore.h:60
const std::string & getOutputFileOverride() const
Return overriden output file name, or "" if none was set.
Definition: Environment.h:127
static Environment & Instance()
Static method to get a reference to the Environment instance.
Definition: Environment.cc:28
static std::string makeROOTCompatible(std::string str)
Remove special characters that ROOT dislikes in branch names, e.g.
Base class for Modules.
Definition: Module.h:72
void setDescription(const std::string &description)
Sets the description of the module.
Definition: Module.cc:214
void setPropertyFlags(unsigned int propertyFlags)
Sets the flags for the module properties.
Definition: Module.cc:208
@ c_ParallelProcessingCertified
This module can be run in parallel processing mode safely (All I/O must be done through the data stor...
Definition: Module.h:80
@ c_TerminateInAllProcesses
When using parallel processing, call this module's terminate() function in all processes().
Definition: Module.h:83
Class to store reconstructed particles.
Definition: Particle.h:75
static bool isOutputProcess()
Return true if the process is an output process.
Definition: ProcHandler.cc:232
static bool parallelProcessingUsed()
Returns true if multiple processes have been spawned, false in single-core mode.
Definition: ProcHandler.cc:226
bool isRequired(const std::string &name="")
Ensure this array/object has been registered previously.
Type-safe access to single objects in the data store.
Definition: StoreObjPtr.h:96
const Var * getVariable(std::string name)
Get the variable belonging to the given key.
Definition: Manager.cc:57
static Manager & Instance()
get singleton instance.
Definition: Manager.cc:25
std::string m_directory
Name of the Directory.
virtual void initialize() override
Initialises the module.
std::vector< std::tuple< std::string, int, float, float > > m_variables
List of variables to save.
virtual void event() override
Method called for each event.
virtual void terminate() override
Write TTree to file, and close file if necessary.
std::vector< Variable::Manager::FunctionPtr > m_functions_2d_1
List of function pointers corresponding to given variables.
std::string m_fileName
Name of ROOT file for output.
std::vector< std::tuple< std::string, int, float, float, std::string, int, float, float > > m_variables_2d
List of pairs of variables to save.
std::vector< Variable::Manager::FunctionPtr > m_functions
List of function pointers corresponding to given variables.
std::string m_particleList
Name of particle list with reconstructed particles.
bool m_ignoreCommandLineOverride
if true, ignore override of filename
std::shared_ptr< TFile > m_file
ROOT file for output.
std::vector< Variable::Manager::FunctionPtr > m_functions_2d_2
List of function pointers corresponding to given variables.
std::vector< std::unique_ptr< StoreObjPtr< RootMergeable< TH2D > > > > m_2d_hists
The ROOT TH2Ds for output.
std::vector< std::unique_ptr< StoreObjPtr< RootMergeable< TH1D > > > > m_hists
The ROOT TH1Ds for output.
std::string m_fileNameSuffix
Suffix to be appended to the output file name.
void addParam(const std::string &name, T &paramVariable, const std::string &description, const T &defaultValue)
Adds a new parameter to the module.
Definition: Module.h:560
std::shared_ptr< TFile > getFile(std::string, bool ignoreErrors=false)
Get a file with a specific name, if is does not exist it will be created.
static RootFileCreationManager & getInstance()
Interface for the FileManager.
#define REG_MODULE(moduleName)
Register the given module (without 'Module' suffix) with the framework.
Definition: Module.h:650
Abstract base class for different kinds of events.
STL namespace.
A variable returning a floating-point value for a given Particle.
Definition: Manager.h:146
FunctionPtr function
Pointer to function.
Definition: Manager.h:147