Belle II Software  release-06-02-00
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 #include <analysis/dataobjects/ParticleList.h>
12 #include <analysis/VariableManager/Manager.h>
13 #include <framework/logging/Logger.h>
14 #include <framework/pcore/ProcHandler.h>
15 #include <framework/utilities/MakeROOTCompatible.h>
16 #include <framework/core/ModuleParam.templateDetails.h>
17 #include <framework/utilities/RootFileCreationManager.h>
18 
19 #include <memory>
20 
21 using namespace std;
22 using namespace Belle2;
23 
24 // Register module in the framework
25 REG_MODULE(VariablesToHistogram)
26 
27 
29  Module()
30 {
31  //Set module properties
32  setDescription("Calculate variables specified by the user for a given ParticleList and save them into one or two dimensional histograms.");
33  setPropertyFlags(c_ParallelProcessingCertified | c_TerminateInAllProcesses);
34 
35  std::vector<std::tuple<std::string, int, float, float>> emptylist;
36  std::vector<std::tuple<std::string, int, float, float, std::string, int, float, float>> emptylist_2d;
37  addParam("particleList", m_particleList,
38  "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)",
39  std::string(""));
40  addParam("variables", m_variables,
41  "List of variables to save. Variables are taken from Variable::Manager, and are identical to those available to e.g. ParticleSelector.",
42  emptylist);
43  addParam("variables_2d", m_variables_2d,
44  "List of variable pairs to save. Variables are taken from Variable::Manager, and are identical to those available to e.g. ParticleSelector.",
45  emptylist_2d);
46 
47  addParam("fileName", m_fileName, "Name of ROOT file for output.", string("VariablesToHistogram.root"));
48  addParam("directory", m_directory, "Directory for all histograms **inside** the file to allow for histograms from multiple "
49  "particlelists in the same file without conflicts", m_directory);
50 
51  m_file = nullptr;
52 }
53 
54 void VariablesToHistogramModule::initialize()
55 {
56  if (not m_particleList.empty())
57  StoreObjPtr<ParticleList>().isRequired(m_particleList);
58 
59  // Check if we can access the given file
60  m_file = RootFileCreationManager::getInstance().getFile(m_fileName);
61  if (!m_file) return;
62  // Make sure we don't disturb the global directory for other modules, friggin side effects everywhere
63  TDirectory::TContext directoryGuard(m_file.get());
64  if (not m_directory.empty()) {
65  m_directory = makeROOTCompatible(m_directory);
66  m_file->mkdir(m_directory.c_str());
67  m_file->cd(m_directory.c_str());
68  }
69 
70  for (const auto& varTuple : m_variables) {
71  std::string varStr;
72  int varNbins = 0;
73  float low = 0;
74  float high = 0;
75  std::tie(varStr, varNbins, low, high) = varTuple;
76  std::string compatibleName = makeROOTCompatible(varStr);
77 
78  auto ptr = std::make_unique<StoreObjPtr<RootMergeable<TH1D>>>("", DataStore::c_Persistent);
79  ptr->registerInDataStore(m_fileName + m_directory + varStr, DataStore::c_DontWriteOut);
80  ptr->construct(compatibleName.c_str(), compatibleName.c_str(), varNbins, low, high);
81  m_hists.emplace_back(std::move(ptr));
82 
83  //also collection function pointers
84  const Variable::Manager::Var* var = Variable::Manager::Instance().getVariable(varStr);
85  if (!var) {
86  B2ERROR("Variable '" << varStr << "' is not available in Variable::Manager!");
87  } else {
88  m_functions.push_back(var->function);
89  }
90  }
91 
92  for (const auto& varTuple : m_variables_2d) {
93  std::string varStr1;
94  int varNbins1 = 0;
95  float low1 = 0;
96  float high1 = 0;
97  std::string varStr2;
98  int varNbins2 = 0;
99  float low2 = 0;
100  float high2 = 0;
101  std::tie(varStr1, varNbins1, low1, high1, varStr2, varNbins2, low2, high2) = varTuple;
102  std::string compatibleName1 = makeROOTCompatible(varStr1);
103  std::string compatibleName2 = makeROOTCompatible(varStr2);
104 
105  auto ptr2d = std::make_unique<StoreObjPtr<RootMergeable<TH2D>>>("", DataStore::c_Persistent);
106  ptr2d->registerInDataStore(m_fileName + m_directory + varStr1 + varStr2, DataStore::c_DontWriteOut);
107  ptr2d->construct((compatibleName1 + compatibleName2).c_str(), (compatibleName1 + compatibleName2).c_str(),
108  varNbins1, low1, high1, varNbins2, low2, high2);
109  m_2d_hists.emplace_back(std::move(ptr2d));
110 
111  //also collection function pointers
112  const Variable::Manager::Var* var1 = Variable::Manager::Instance().getVariable(varStr1);
113  if (!var1) {
114  B2ERROR("Variable '" << varStr1 << "' is not available in Variable::Manager!");
115  } else {
116  m_functions_2d_1.push_back(var1->function);
117  }
118 
119  //also collection function pointers
120  const Variable::Manager::Var* var2 = Variable::Manager::Instance().getVariable(varStr2);
121  if (!var2) {
122  B2ERROR("Variable '" << varStr2 << "' is not available in Variable::Manager!");
123  } else {
124  m_functions_2d_2.push_back(var2->function);
125  }
126  }
127 
128 }
129 
130 void VariablesToHistogramModule::event()
131 {
132  unsigned int nVars = m_variables.size();
133  unsigned int nVars_2d = m_variables_2d.size();
134  std::vector<float> vars(nVars);
135  std::vector<float> vars_2d_1(nVars_2d);
136  std::vector<float> vars_2d_2(nVars_2d);
137 
138  if (m_particleList.empty()) {
139  for (unsigned int iVar = 0; iVar < nVars; iVar++) {
140  vars[iVar] = m_functions[iVar](nullptr);
141  (*m_hists[iVar])->get().Fill(vars[iVar]);
142  }
143  for (unsigned int iVar = 0; iVar < nVars_2d; iVar++) {
144  vars_2d_1[iVar] = m_functions_2d_1[iVar](nullptr);
145  vars_2d_2[iVar] = m_functions_2d_2[iVar](nullptr);
146  (*m_2d_hists[iVar])->get().Fill(vars_2d_1[iVar], vars_2d_2[iVar]);
147  }
148 
149  } else {
150  StoreObjPtr<ParticleList> particlelist(m_particleList);
151  unsigned int nPart = particlelist->getListSize();
152  for (unsigned int iPart = 0; iPart < nPart; iPart++) {
153  const Particle* particle = particlelist->getParticle(iPart);
154  for (unsigned int iVar = 0; iVar < nVars; iVar++) {
155  vars[iVar] = m_functions[iVar](particle);
156  (*m_hists[iVar])->get().Fill(vars[iVar]);
157  }
158  for (unsigned int iVar = 0; iVar < nVars_2d; iVar++) {
159  vars_2d_1[iVar] = m_functions_2d_1[iVar](particle);
160  vars_2d_2[iVar] = m_functions_2d_2[iVar](particle);
161  (*m_2d_hists[iVar])->get().Fill(vars_2d_1[iVar], vars_2d_2[iVar]);
162  }
163  }
164  }
165 }
166 
167 void VariablesToHistogramModule::terminate()
168 {
169  if (!ProcHandler::parallelProcessingUsed() or ProcHandler::isOutputProcess()) {
170  TDirectory::TContext directoryGuard(m_file.get());
171  if (not m_directory.empty()) {
172  m_file->cd(m_directory.c_str());
173  }
174  B2INFO("Writing Histograms to " << gDirectory->GetPath());
175  unsigned int nVars = m_variables.size();
176  for (unsigned int iVar = 0; iVar < nVars; iVar++) {
177  (*m_hists[iVar])->write(gDirectory);
178  }
179  unsigned int nVars_2d = m_variables_2d.size();
180  for (unsigned int iVar = 0; iVar < nVars_2d; iVar++) {
181  (*m_2d_hists[iVar])->write(gDirectory);
182  }
183 
184  const bool writeError = m_file->TestBit(TFile::kWriteError);
185  m_file.reset();
186  if (writeError) {
187  B2FATAL("A write error occurred while saving '" << m_fileName << "', please check if enough disk space is available.");
188  }
189  }
190 }
Base class for Modules.
Definition: Module.h:72
Class to store reconstructed particles.
Definition: Particle.h:74
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:95
Module to calculate variables specified by the user for a given ParticleList and save them into an Hi...
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.
Definition: Module.h:650
Abstract base class for different kinds of events.
A variable returning a floating-point value for a given Particle.
Definition: Manager.h:133
FunctionPtr function
Pointer to function.
Definition: Manager.h:134