Belle II Software development
arichToNtupleModule.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 <arich/modules/arichToNtuple/arichToNtupleModule.h>
10
11#include <arich/dataobjects/ARICHLikelihood.h>
12#include <arich/dataobjects/ARICHAeroHit.h>
13#include <arich/dataobjects/ARICHTrack.h>
14#include <arich/dataobjects/ARICHPhoton.h>
15#include <mdst/dataobjects/Track.h>
16#include <tracking/dataobjects/ExtHit.h>
17
18// analysis
19#include <analysis/dataobjects/ParticleList.h>
20#include <analysis/VariableManager/Manager.h>
21#include <analysis/VariableManager/Utility.h>
22
23// framework
24#include <framework/logging/Logger.h>
25#include <framework/pcore/ProcHandler.h>
26#include <framework/core/ModuleParam.templateDetails.h>
27
28#include <framework/datastore/DataStore.h>
29#include <framework/datastore/StoreArray.h>
30
31// framework - root utilities
32#include <framework/utilities/MakeROOTCompatible.h>
33#include <framework/utilities/RootFileCreationManager.h>
34
35#include <cmath>
36
37using namespace Belle2;
38
39// Register module in the framework
40REG_MODULE(arichToNtuple);
41
42
44 Module(), m_tree("", DataStore::c_Persistent)
45{
46 //Set module properties
47 setDescription("Local arich extension of VariblesToNtuple module to append detailed arich information to reconstructed candidates in the analysis output Ntuple. The TNtuple is candidate-based, meaning that the variables of each candidate are saved separate rows.");
49
50 std::vector<std::string> emptylist;
51 addParam("particleList", m_particleList,
52 "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)",
53 std::string(""));
54 addParam("arichSelector", m_arichSelector,
55 "Decay string with selected particles to which arich info should be appened", std::string(""));
56 addParam("variables", m_variables,
57 "List of variables (or collections) to save. Variables are taken from Variable::Manager, and are identical to those available to e.g. ParticleSelector.",
58 emptylist);
59 addParam("arichVariables", m_arichVariables,
60 "List of aliases for particles to which arich info will be appended (used for tree branch names)",
61 emptylist);
62
63 addParam("fileName", m_fileName, "Name of ROOT file for output.", std::string("arichToNtuple.root"));
64 addParam("treeName", m_treeName, "Name of the NTuple in the saved file.", std::string("ntuple"));
65
66 std::tuple<std::string, std::map<int, unsigned int>> default_sampling{"", {}};
67 addParam("sampling", m_sampling,
68 "Tuple of variable name and a map of integer values and inverse sampling rate. E.g. (signal, {1: 0, 0:10}) selects all signal candidates and every 10th background candidate.",
69 default_sampling);
70}
71
73{
74 m_eventMetaData.isRequired();
75
76 StoreArray<Track> tracks;
77 tracks.isRequired();
78 StoreArray<ExtHit> extHits;
79 extHits.isRequired();
80 StoreArray<ARICHTrack> arichTracks;
81 arichTracks.isRequired();
82
83
84 if (not m_particleList.empty())
86
88
89 // Initializing the output root file
90 if (m_fileName.empty()) {
91 B2FATAL("Output root file name is not set. Please set a valid root output file name (\"fileName\" module parameter).");
92 }
93 // See if there is already a file in which case add a new tree to it ...
94 // otherwise create a new file (all handled by framework)
96 if (!m_file) {
97 B2ERROR("Could not create file \"" << m_fileName <<
98 "\". Please set a valid root output file name (\"fileName\" module parameter).");
99 return;
100 }
101
102 TDirectory::TContext directoryGuard(m_file.get());
103
104 // check if TTree with that name already exists
105 if (m_file->Get(m_treeName.c_str())) {
106 B2FATAL("Tree with the name \"" << m_treeName
107 << "\" already exists in the file \"" << m_fileName << "\"\n"
108 << "\nYou probably want to either set the output fileName or the treeName to something else:\n\n"
109 << " from modularAnalysis import arichToNtuple\n"
110 << " arichToNtuple('pi+:all', ['p'], treename='pions', filename='arichToNtuple.root')\n"
111 << " arichToNtuple('gamma:all', ['p'], treename='photons', filename='arichToNtuple.root') # two trees, same file\n"
112 << "\n == Or ==\n"
113 << " from modularAnalysis import arichToNtuple\n"
114 << " arichToNtuple('pi+:all', ['p'], filename='pions.root')\n"
115 << " arichToNtuple('gamma:all', ['p'], filename='photons.root') # two files\n"
116 );
117 return;
118 }
119
120 // set up tree and register it in the datastore
122 m_tree.construct(m_treeName.c_str(), "");
123 m_tree->get().SetCacheSize(100000);
124
125 // declare counter branches - pass through variable list, remove counters added by user
126 m_tree->get().Branch("__experiment__", &m_experiment, "__experiment__/I");
127 m_tree->get().Branch("__run__", &m_run, "__run__/I");
128 m_tree->get().Branch("__event__", &m_event, "__event__/I");
129 if (not m_particleList.empty()) {
130 m_tree->get().Branch("__candidate__", &m_candidate, "__candidate__/I");
131 m_tree->get().Branch("__ncandidates__", &m_ncandidates, "__ncandidates__/I");
132 }
133 for (const auto& variable : m_variables)
134 if (Variable::isCounterVariable(variable)) {
135 B2WARNING("The counter '" << variable
136 << "' is handled automatically by arichToNtuple, you don't need to add it.");
137 }
138
139 // declare branches and get the variable strings
141 m_branchAddresses.resize(m_variables.size() + 1);
142 m_tree->get().Branch("__weight__", &m_branchAddresses[0], "__weight__/D");
143 size_t enumerate = 1;
144 for (const std::string& varStr : m_variables) {
145
146 std::string branchName = MakeROOTCompatible::makeROOTCompatible(varStr);
147 m_tree->get().Branch(branchName.c_str(), &m_branchAddresses[enumerate], (branchName + "/D").c_str());
148
149 // also collection function pointers
151 if (!var) {
152 B2ERROR("Variable '" << varStr << "' is not available in Variable::Manager!");
153 } else {
154 m_functions.push_back(var->function);
155 }
156 enumerate++;
157 }
158
159 // add arich related branches
160 for (const std::string& varStr : m_arichVariables) {
161 std::string branchName = MakeROOTCompatible::makeROOTCompatible(varStr);
162 addARICHBranches(branchName);
163 }
164
165 m_tree->get().SetBasketSize("*", 1600);
166
167 m_sampling_name = std::get<0>(m_sampling);
168 m_sampling_rates = std::get<1>(m_sampling);
169
170 if (m_sampling_name != "") {
172 if (m_sampling_variable == nullptr) {
173 B2FATAL("Couldn't find sample variable " << m_sampling_name << " via the Variable::Manager. Check the name!");
174 }
175 for (const auto& samplingPair : m_sampling_rates)
176 m_sampling_counts[samplingPair.first] = 0;
177 } else {
178 m_sampling_variable = nullptr;
179 }
180}
181
182
184{
185 if (m_sampling_variable == nullptr)
186 return 1.0;
187
188 long target = 0;
189 if (m_sampling_variable->variabletype == Variable::Manager::VariableDataType::c_double) {
190 target = std::lround(std::get<double>(m_sampling_variable->function(particle)));
191 } else if (m_sampling_variable->variabletype == Variable::Manager::VariableDataType::c_int) {
192 target = std::lround(std::get<int>(m_sampling_variable->function(particle)));
193 } else if (m_sampling_variable->variabletype == Variable::Manager::VariableDataType::c_bool) {
194 target = std::lround(std::get<bool>(m_sampling_variable->function(particle)));
195 }
196 if (m_sampling_rates.find(target) != m_sampling_rates.end() and m_sampling_rates[target] > 0) {
197 m_sampling_counts[target]++;
198 if (m_sampling_counts[target] % m_sampling_rates[target] != 0)
199 return 0;
200 else {
201 m_sampling_counts[target] = 0;
202 return m_sampling_rates[target];
203 }
204 }
205 return 1.0;
206}
207
209{
210 m_event = m_eventMetaData->getEvent();
211 m_run = m_eventMetaData->getRun();
212 m_experiment = m_eventMetaData->getExperiment();
213
214 if (m_particleList.empty()) {
216 if (m_branchAddresses[0] > 0) {
217 for (unsigned int iVar = 0; iVar < m_variables.size(); iVar++) {
218 if (std::holds_alternative<double>(m_functions[iVar](nullptr))) {
219 m_branchAddresses[iVar + 1] = std::get<double>(m_functions[iVar](nullptr));
220 } else if (std::holds_alternative<int>(m_functions[iVar](nullptr))) {
221 m_branchAddresses[iVar + 1] = (double)std::get<int>(m_functions[iVar](nullptr));
222 } else if (std::holds_alternative<bool>(m_functions[iVar](nullptr))) {
223 m_branchAddresses[iVar + 1] = (double)std::get<bool>(m_functions[iVar](nullptr));
224 }
225 }
226 for (auto& arich : m_arich) arich->clear();
227 m_tree->get().Fill();
228 }
229
230 } else {
232 m_ncandidates = particlelist->getListSize();
233
234 for (unsigned int iPart = 0; iPart < m_ncandidates; iPart++) {
235 m_candidate = iPart;
236 const Particle* particle = particlelist->getParticle(iPart);
238 if (m_branchAddresses[0] > 0) {
239 for (unsigned int iVar = 0; iVar < m_variables.size(); iVar++) {
240 if (std::holds_alternative<double>(m_functions[iVar](particle))) {
241 m_branchAddresses[iVar + 1] = std::get<double>(m_functions[iVar](particle));
242 } else if (std::holds_alternative<int>(m_functions[iVar](particle))) {
243 m_branchAddresses[iVar + 1] = (double)std::get<int>(m_functions[iVar](particle));
244 } else if (std::holds_alternative<bool>(m_functions[iVar](particle))) {
245 m_branchAddresses[iVar + 1] = (double)std::get<bool>(m_functions[iVar](particle));
246 }
247 }
248 for (auto& arich : m_arich) arich->clear();
249 fillARICHTree(particle);
250 m_tree->get().Fill();
251 }
252 }
253 }
254}
255
257{
259 B2INFO("Writing NTuple " << m_treeName);
260 TDirectory::TContext directoryGuard(m_file.get());
261 m_tree->write(m_file.get());
262
263 const bool writeError = m_file->TestBit(TFile::kWriteError);
264 m_file.reset();
265 if (writeError) {
266 B2FATAL("A write error occurred while saving '" << m_fileName << "', please check if enough disk space is available.");
267 }
268 }
269}
270
271void arichToNtupleModule::addARICHBranches(const std::string& name)
272{
273
275 m_arich.push_back(tree);
276 m_tree->get().Branch((name + "_detPhot").c_str(), &tree->detPhot, "detPhot/I");
277 m_tree->get().Branch((name + "_expPhot").c_str(), &tree->expPhot, "e/F:mu:pi:K:p:d");
278 m_tree->get().Branch((name + "_logL").c_str(), &tree->logL, "e/F:mu:pi:K:p:d");
279 m_tree->get().Branch((name + "_recHit").c_str(), &tree->recHit, "PDG/I:x/F:y:z:p:theta:phi");
280 m_tree->get().Branch((name + "_mcHit").c_str(), &tree->mcHit, "PDG/I:x/F:y:z:p:theta:phi");
281 m_tree->get().Branch((name + "_winHit").c_str(), &tree->winHit, "x/F:y");
282 m_tree->get().Branch((name + "_photons").c_str(), "std::vector<Belle2::ARICHPhoton>", &tree->photons);
283
284}
285
287{
288
289 std::vector<const Particle*> selParticles = m_decaydescriptor.getSelectionParticles(particle);
290 int iTree = 0;
291 for (auto p : selParticles) {
292 const Track* track = p->getTrack();
293 if (!track) continue;
294 for (const ExtHit& hit : track->getRelationsTo<ExtHit>()) {
295 const ARICHTrack* atrk = hit.getRelated<ARICHTrack>();
296 if (!atrk) continue;
297
298 if (atrk->hitsWindow()) {
299 m_arich[iTree]->winHit[0] = atrk->windowHitPosition().X();
300 m_arich[iTree]->winHit[1] = atrk->windowHitPosition().Y();
301 }
302
303 m_arich[iTree]->photons = atrk->getPhotons();
304
305 ROOT::Math::XYZVector recPos = atrk->getPosition();
306 m_arich[iTree]->recHit.x = recPos.X();
307 m_arich[iTree]->recHit.y = recPos.Y();
308 m_arich[iTree]->recHit.z = recPos.Z();
309
310 ROOT::Math::XYZVector recMom = atrk->getDirection() * atrk->getMomentum();
311 m_arich[iTree]->recHit.p = recMom.R();
312 m_arich[iTree]->recHit.theta = recMom.Theta();
313 m_arich[iTree]->recHit.phi = recMom.Phi();
314
315 const ARICHLikelihood* lkh = NULL;
316 lkh = track->getRelated<ARICHLikelihood>();
317 if (lkh) {
318 m_arich[iTree]->logL.e = lkh->getLogL(Const::electron);
319 m_arich[iTree]->logL.mu = lkh->getLogL(Const::muon);
320 m_arich[iTree]->logL.pi = lkh->getLogL(Const::pion);
321 m_arich[iTree]->logL.K = lkh->getLogL(Const::kaon);
322 m_arich[iTree]->logL.p = lkh->getLogL(Const::proton);
323 m_arich[iTree]->logL.d = lkh->getLogL(Const::deuteron);
324
325 m_arich[iTree]->expPhot.e = lkh->getExpPhot(Const::electron);
326 m_arich[iTree]->expPhot.mu = lkh->getExpPhot(Const::muon);
327 m_arich[iTree]->expPhot.pi = lkh->getExpPhot(Const::pion);
328 m_arich[iTree]->expPhot.K = lkh->getExpPhot(Const::kaon);
329 m_arich[iTree]->expPhot.p = lkh->getExpPhot(Const::proton);
330 m_arich[iTree]->expPhot.d = lkh->getExpPhot(Const::deuteron);
331
332 m_arich[iTree]->detPhot = lkh->getDetPhot();
333 }
334
335 const ARICHAeroHit* aeroHit = atrk->getRelated<ARICHAeroHit>();
336 if (aeroHit) {
337 ROOT::Math::XYZVector truePos = aeroHit->getPosition();
338 m_arich[iTree]->mcHit.x = truePos.X();
339 m_arich[iTree]->mcHit.y = truePos.Y();
340 m_arich[iTree]->mcHit.z = truePos.Z();
341
342 ROOT::Math::XYZVector trueMom = aeroHit->getMomentum();
343 m_arich[iTree]->mcHit.p = trueMom.R();
344 m_arich[iTree]->mcHit.theta = trueMom.Theta();
345 m_arich[iTree]->mcHit.phi = trueMom.Phi();
346 m_arich[iTree]->mcHit.PDG = aeroHit->getPDG();
347
348 }
349 }
350 iTree++;
351 }
352}
Datastore class that holds information on track parameters at the entrance in aerogel.
Definition: ARICHAeroHit.h:27
int getPDG() const
Get particle PDG identity number.
Definition: ARICHAeroHit.h:64
ROOT::Math::XYZVector getMomentum() const
Get track momentum (at entrance in 1. aerogel plane)
Definition: ARICHAeroHit.h:70
ROOT::Math::XYZVector getPosition() const
Get track position (at entrance in 1. aerogel plane)
Definition: ARICHAeroHit.h:67
This is a class to store ARICH likelihoods in the datastore.
float getDetPhot() const
Return number of detected photons for a given particle.
float getLogL(const Const::ChargedStable &part) const
Return log likelihood for a given particle.
float getExpPhot(const Const::ChargedStable &part) const
Return number of expected photons for a given particle.
Datastore class that holds position and momentum information of tracks that hit ARICH.
Definition: ARICHTrack.h:35
bool hitsWindow() const
Returns true if track hits HAPD window.
Definition: ARICHTrack.h:154
ROOT::Math::XYZVector getDirection() const
returns track direction vector
Definition: ARICHTrack.h:142
const std::vector< ARICHPhoton > & getPhotons() const
Returns vector of ARICHPhoton's associated with track.
Definition: ARICHTrack.h:192
ROOT::Math::XYZVector getPosition() const
returns track position vector
Definition: ARICHTrack.h:136
ROOT::Math::XYVector windowHitPosition() const
Get HAPD window hit position.
Definition: ARICHTrack.h:160
double getMomentum() const
returns track momentum
Definition: ARICHTrack.h:148
static const ChargedStable muon
muon particle
Definition: Const.h:660
static const ChargedStable pion
charged pion particle
Definition: Const.h:661
static const ChargedStable proton
proton particle
Definition: Const.h:663
static const ChargedStable kaon
charged kaon particle
Definition: Const.h:662
static const ChargedStable electron
electron particle
Definition: Const.h:659
static const ChargedStable deuteron
deuteron particle
Definition: Const.h:664
In the store you can park objects that have to be accessed by various modules.
Definition: DataStore.h:51
@ c_DontWriteOut
Object/array should be NOT saved by output modules.
Definition: DataStore.h:71
bool init(const std::string &str)
Initialise the DecayDescriptor from given string.
std::vector< const Particle * > getSelectionParticles(const Particle *particle)
Get a vector of pointers with selected daughters in the decay tree.
Store one Ext hit as a ROOT object.
Definition: ExtHit.h:31
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:76
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
T * getRelated(const std::string &name="", const std::string &namedRelation="") const
Get the object to or from which this object has a relation.
bool isRequired(const std::string &name="")
Ensure this array/object has been registered previously.
Accessor to arrays stored in the data store.
Definition: StoreArray.h:113
Type-safe access to single objects in the data store.
Definition: StoreObjPtr.h:95
Class that bundles various TrackFitResults.
Definition: Track.h:25
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...
Definition: Manager.cc:180
const Var * getVariable(std::string name)
Get the variable belonging to the given key.
Definition: Manager.cc:58
static Manager & Instance()
get singleton instance.
Definition: Manager.cc:26
std::vector< ARICH::ARICHTree * > m_arich
Vector of arich branch addresses.
void addARICHBranches(const std::string &name)
Add arich branches to the output TTree.
std::vector< std::string > m_variables
List of variables to save.
virtual void initialize() override
Initialises the module.
std::map< int, unsigned int > m_sampling_rates
Inverse sampling rates.
virtual void event() override
Method called for each event.
void fillARICHTree(const Particle *particle)
Fill data to arich branches.
unsigned int m_ncandidates
total n candidates
virtual void terminate() override
Write TTree to file, and close file if necessary.
StoreObjPtr< EventMetaData > m_eventMetaData
the event information
std::vector< double > m_branchAddresses
Variable branch addresses.
std::map< int, unsigned long int > m_sampling_counts
Current number of samples with this value.
std::string m_fileName
Name of ROOT file for output.
std::tuple< std::string, std::map< int, unsigned int > > m_sampling
Tuple of variable name and a map of integer values and inverse sampling rate.
int m_experiment
experiment number
std::vector< std::string > m_arichVariables
List of aliases of particles to which arich info will be appended (used for tree branch naming)
std::vector< Variable::Manager::FunctionPtr > m_functions
List of function pointers corresponding to given variables.
std::string m_arichSelector
Decay string with selected particles to which arich info should be appended.
std::string m_particleList
Name of particle list with reconstructed particles.
StoreObjPtr< RootMergeable< TTree > > m_tree
The ROOT TNtuple for output.
std::shared_ptr< TFile > m_file
ROOT file for output.
DecayDescriptor m_decaydescriptor
Decay descriptor for selected particles to append arich info.
std::string m_sampling_name
Variable name of sampling variable.
float getInverseSamplingRateWeight(const Particle *particle)
Calculate inverse sampling rate weight.
std::string m_treeName
Name of the TTree.
const Variable::Manager::Var * m_sampling_variable
Variable Pointer to target variable.
int m_candidate
candidate counter
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:559
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:649
Abstract base class for different kinds of events.
Structure of a flat ntuple.
VariableDataType variabletype
data type of variable
Definition: Manager.h:132
A variable returning a floating-point value for a given Particle.
Definition: Manager.h:145
FunctionPtr function
Pointer to function.
Definition: Manager.h:146