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 <arich/dataobjects/ARICHHit.h>
16#include <mdst/dataobjects/Track.h>
17#include <tracking/dataobjects/ExtHit.h>
18
19// analysis
20#include <analysis/dataobjects/ParticleList.h>
21#include <analysis/VariableManager/Manager.h>
22#include <analysis/VariableManager/Utility.h>
23
24// framework
25#include <framework/logging/Logger.h>
26#include <framework/pcore/ProcHandler.h>
27#include <framework/core/ModuleParam.templateDetails.h>
28
29#include <framework/datastore/DataStore.h>
30#include <framework/datastore/StoreArray.h>
31
32// framework - root utilities
33#include <framework/utilities/MakeROOTCompatible.h>
34#include <framework/utilities/RootFileCreationManager.h>
35
36#include <cmath>
37
38using namespace Belle2;
39
40// Register module in the framework
41REG_MODULE(arichToNtuple);
42
43
45 Module(), m_tree("", DataStore::c_Persistent)
46{
47 //Set module properties
48 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.");
50
51 std::vector<std::string> emptylist;
52 addParam("particleList", m_particleList,
53 "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)",
54 std::string(""));
55 addParam("arichSelector", m_arichSelector,
56 "Decay string with selected particles to which arich info should be appened", std::string(""));
57 addParam("variables", m_variables,
58 "List of variables (or collections) to save. Variables are taken from Variable::Manager, and are identical to those available to e.g. ParticleSelector.",
59 emptylist);
60 addParam("arichVariables", m_arichVariables,
61 "List of aliases for particles to which arich info will be appended (used for tree branch names)",
62 emptylist);
63
64 addParam("fileName", m_fileName, "Name of ROOT file for output.", std::string("arichToNtuple.root"));
65 addParam("treeName", m_treeName, "Name of the NTuple in the saved file.", std::string("ntuple"));
66
67 std::tuple<std::string, std::map<int, unsigned int>> default_sampling{"", {}};
68 addParam("sampling", m_sampling,
69 "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.",
70 default_sampling);
71}
72
74{
75 m_eventMetaData.isRequired();
76
77 StoreArray<Track> tracks;
78 tracks.isRequired();
79 StoreArray<ExtHit> extHits;
80 extHits.isRequired();
81 StoreArray<ARICHTrack> arichTracks;
82 arichTracks.isRequired();
83
84
85 if (not m_particleList.empty())
87
89
90 // Initializing the output root file
91 if (m_fileName.empty()) {
92 B2FATAL("Output root file name is not set. Please set a vaild root output file name (\"fileName\" module parameter).");
93 }
94 // See if there is already a file in which case add a new tree to it ...
95 // otherwise create a new file (all handled by framework)
97 if (!m_file) {
98 B2ERROR("Could not create file \"" << m_fileName <<
99 "\". Please set a vaild root output file name (\"fileName\" module parameter).");
100 return;
101 }
102
103 TDirectory::TContext directoryGuard(m_file.get());
104
105 // check if TTree with that name already exists
106 if (m_file->Get(m_treeName.c_str())) {
107 B2FATAL("Tree with the name \"" << m_treeName
108 << "\" already exists in the file \"" << m_fileName << "\"\n"
109 << "\nYou probably want to either set the output fileName or the treeName to something else:\n\n"
110 << " from modularAnalysis import arichToNtuple\n"
111 << " arichToNtuple('pi+:all', ['p'], treename='pions', filename='arichToNtuple.root')\n"
112 << " arichToNtuple('gamma:all', ['p'], treename='photons', filename='arichToNtuple.root') # two trees, same file\n"
113 << "\n == Or ==\n"
114 << " from modularAnalysis import arichToNtuple\n"
115 << " arichToNtuple('pi+:all', ['p'], filename='pions.root')\n"
116 << " arichToNtuple('gamma:all', ['p'], filename='photons.root') # two files\n"
117 );
118 return;
119 }
120
121 // set up tree and register it in the datastore
123 m_tree.construct(m_treeName.c_str(), "");
124 m_tree->get().SetCacheSize(100000);
125
126 // declare counter branches - pass through variable list, remove counters added by user
127 m_tree->get().Branch("__experiment__", &m_experiment, "__experiment__/I");
128 m_tree->get().Branch("__run__", &m_run, "__run__/I");
129 m_tree->get().Branch("__event__", &m_event, "__event__/I");
130 if (not m_particleList.empty()) {
131 m_tree->get().Branch("__candidate__", &m_candidate, "__candidate__/I");
132 m_tree->get().Branch("__ncandidates__", &m_ncandidates, "__ncandidates__/I");
133 }
134 for (const auto& variable : m_variables)
135 if (Variable::isCounterVariable(variable)) {
136 B2WARNING("The counter '" << variable
137 << "' is handled automatically by arichToNtuple, you don't need to add it.");
138 }
139
140 // declare branches and get the variable strings
142 m_branchAddresses.resize(m_variables.size() + 1);
143 m_tree->get().Branch("__weight__", &m_branchAddresses[0], "__weight__/D");
144 size_t enumerate = 1;
145 for (const std::string& varStr : m_variables) {
146
147 std::string branchName = MakeROOTCompatible::makeROOTCompatible(varStr);
148 m_tree->get().Branch(branchName.c_str(), &m_branchAddresses[enumerate], (branchName + "/D").c_str());
149
150 // also collection function pointers
152 if (!var) {
153 B2ERROR("Variable '" << varStr << "' is not available in Variable::Manager!");
154 } else {
155 m_functions.push_back(var->function);
156 }
157 enumerate++;
158 }
159
160 // add arich related branches
161 for (const std::string& varStr : m_arichVariables) {
162 std::string branchName = MakeROOTCompatible::makeROOTCompatible(varStr);
163 addARICHBranches(branchName);
164 }
165
166 m_tree->get().SetBasketSize("*", 1600);
167
168 m_sampling_name = std::get<0>(m_sampling);
169 m_sampling_rates = std::get<1>(m_sampling);
170
171 if (m_sampling_name != "") {
173 if (m_sampling_variable == nullptr) {
174 B2FATAL("Couldn't find sample variable " << m_sampling_name << " via the Variable::Manager. Check the name!");
175 }
176 for (const auto& samplingPair : m_sampling_rates)
177 m_sampling_counts[samplingPair.first] = 0;
178 } else {
179 m_sampling_variable = nullptr;
180 }
181}
182
183
185{
186 if (m_sampling_variable == nullptr)
187 return 1.0;
188
189 long target = 0;
190 if (m_sampling_variable->variabletype == Variable::Manager::VariableDataType::c_double) {
191 target = std::lround(std::get<double>(m_sampling_variable->function(particle)));
192 } else if (m_sampling_variable->variabletype == Variable::Manager::VariableDataType::c_int) {
193 target = std::lround(std::get<int>(m_sampling_variable->function(particle)));
194 } else if (m_sampling_variable->variabletype == Variable::Manager::VariableDataType::c_bool) {
195 target = std::lround(std::get<bool>(m_sampling_variable->function(particle)));
196 }
197 if (m_sampling_rates.find(target) != m_sampling_rates.end() and m_sampling_rates[target] > 0) {
198 m_sampling_counts[target]++;
199 if (m_sampling_counts[target] % m_sampling_rates[target] != 0)
200 return 0;
201 else {
202 m_sampling_counts[target] = 0;
203 return m_sampling_rates[target];
204 }
205 }
206 return 1.0;
207}
208
210{
211 m_event = m_eventMetaData->getEvent();
212 m_run = m_eventMetaData->getRun();
213 m_experiment = m_eventMetaData->getExperiment();
214
215 if (m_particleList.empty()) {
217 if (m_branchAddresses[0] > 0) {
218 for (unsigned int iVar = 0; iVar < m_variables.size(); iVar++) {
219 if (std::holds_alternative<double>(m_functions[iVar](nullptr))) {
220 m_branchAddresses[iVar + 1] = std::get<double>(m_functions[iVar](nullptr));
221 } else if (std::holds_alternative<int>(m_functions[iVar](nullptr))) {
222 m_branchAddresses[iVar + 1] = (double)std::get<int>(m_functions[iVar](nullptr));
223 } else if (std::holds_alternative<bool>(m_functions[iVar](nullptr))) {
224 m_branchAddresses[iVar + 1] = (double)std::get<bool>(m_functions[iVar](nullptr));
225 }
226 }
227 for (auto& arich : m_arich) arich->clear();
228 m_tree->get().Fill();
229 }
230
231 } else {
233 m_ncandidates = particlelist->getListSize();
234
235 for (unsigned int iPart = 0; iPart < m_ncandidates; iPart++) {
236 m_candidate = iPart;
237 const Particle* particle = particlelist->getParticle(iPart);
239 if (m_branchAddresses[0] > 0) {
240 for (unsigned int iVar = 0; iVar < m_variables.size(); iVar++) {
241 if (std::holds_alternative<double>(m_functions[iVar](particle))) {
242 m_branchAddresses[iVar + 1] = std::get<double>(m_functions[iVar](particle));
243 } else if (std::holds_alternative<int>(m_functions[iVar](particle))) {
244 m_branchAddresses[iVar + 1] = (double)std::get<int>(m_functions[iVar](particle));
245 } else if (std::holds_alternative<bool>(m_functions[iVar](particle))) {
246 m_branchAddresses[iVar + 1] = (double)std::get<bool>(m_functions[iVar](particle));
247 }
248 }
249 for (auto& arich : m_arich) arich->clear();
250 fillARICHTree(particle);
251 m_tree->get().Fill();
252 }
253 }
254 }
255}
256
258{
260 B2INFO("Writing NTuple " << m_treeName);
261 TDirectory::TContext directoryGuard(m_file.get());
262 m_tree->write(m_file.get());
263
264 const bool writeError = m_file->TestBit(TFile::kWriteError);
265 m_file.reset();
266 if (writeError) {
267 B2FATAL("A write error occured while saving '" << m_fileName << "', please check if enough disk space is available.");
268 }
269 }
270}
271
272void arichToNtupleModule::addARICHBranches(const std::string& name)
273{
274
276 m_arich.push_back(tree);
277 m_tree->get().Branch((name + "_detPhot").c_str(), &tree->detPhot, "detPhot/I");
278 m_tree->get().Branch((name + "_expPhot").c_str(), &tree->expPhot, "e/F:mu:pi:K:p:d");
279 m_tree->get().Branch((name + "_logL").c_str(), &tree->logL, "e/F:mu:pi:K:p:d");
280 m_tree->get().Branch((name + "_recHit").c_str(), &tree->recHit, "PDG/I:x/F:y:z:p:theta:phi");
281 m_tree->get().Branch((name + "_mcHit").c_str(), &tree->mcHit, "PDG/I:x/F:y:z:p:theta:phi");
282 m_tree->get().Branch((name + "_winHit").c_str(), &tree->winHit, "x/F:y");
283 m_tree->get().Branch((name + "_photons").c_str(), "std::vector<Belle2::ARICHPhoton>", &tree->photons);
284
285}
286
288{
289
290 std::vector<const Particle*> selParticles = m_decaydescriptor.getSelectionParticles(particle);
291 int iTree = 0;
292 for (auto p : selParticles) {
293 const Track* track = p->getTrack();
294 if (!track) continue;
295 for (const ExtHit& hit : track->getRelationsTo<ExtHit>()) {
296 const ARICHTrack* atrk = hit.getRelated<ARICHTrack>();
297 if (!atrk) continue;
298
299 if (atrk->hitsWindow()) {
300 m_arich[iTree]->winHit[0] = atrk->windowHitPosition().X();
301 m_arich[iTree]->winHit[1] = atrk->windowHitPosition().Y();
302 }
303
304 m_arich[iTree]->photons = atrk->getPhotons();
305
306 ROOT::Math::XYZVector recPos = atrk->getPosition();
307 m_arich[iTree]->recHit.x = recPos.X();
308 m_arich[iTree]->recHit.y = recPos.Y();
309 m_arich[iTree]->recHit.z = recPos.Z();
310
311 ROOT::Math::XYZVector recMom = atrk->getDirection() * atrk->getMomentum();
312 m_arich[iTree]->recHit.p = recMom.R();
313 m_arich[iTree]->recHit.theta = recMom.Theta();
314 m_arich[iTree]->recHit.phi = recMom.Phi();
315
316 const ARICHLikelihood* lkh = NULL;
317 lkh = track->getRelated<ARICHLikelihood>();
318 if (lkh) {
319 m_arich[iTree]->logL.e = lkh->getLogL(Const::electron);
320 m_arich[iTree]->logL.mu = lkh->getLogL(Const::muon);
321 m_arich[iTree]->logL.pi = lkh->getLogL(Const::pion);
322 m_arich[iTree]->logL.K = lkh->getLogL(Const::kaon);
323 m_arich[iTree]->logL.p = lkh->getLogL(Const::proton);
324 m_arich[iTree]->logL.d = lkh->getLogL(Const::deuteron);
325
326 m_arich[iTree]->expPhot.e = lkh->getExpPhot(Const::electron);
327 m_arich[iTree]->expPhot.mu = lkh->getExpPhot(Const::muon);
328 m_arich[iTree]->expPhot.pi = lkh->getExpPhot(Const::pion);
329 m_arich[iTree]->expPhot.K = lkh->getExpPhot(Const::kaon);
330 m_arich[iTree]->expPhot.p = lkh->getExpPhot(Const::proton);
331 m_arich[iTree]->expPhot.d = lkh->getExpPhot(Const::deuteron);
332
333 m_arich[iTree]->detPhot = lkh->getDetPhot();
334 }
335
336 const ARICHAeroHit* aeroHit = atrk->getRelated<ARICHAeroHit>();
337 if (aeroHit) {
338 ROOT::Math::XYZVector truePos = aeroHit->getPosition();
339 m_arich[iTree]->mcHit.x = truePos.X();
340 m_arich[iTree]->mcHit.y = truePos.Y();
341 m_arich[iTree]->mcHit.z = truePos.Z();
342
343 ROOT::Math::XYZVector trueMom = aeroHit->getMomentum();
344 m_arich[iTree]->mcHit.p = trueMom.R();
345 m_arich[iTree]->mcHit.theta = trueMom.Theta();
346 m_arich[iTree]->mcHit.phi = trueMom.Phi();
347 m_arich[iTree]->mcHit.PDG = aeroHit->getPDG();
348
349 }
350 }
351 iTree++;
352 }
353}
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: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
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:96
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:179
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::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 appendend.
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: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.
Structure of a flat ntuple.
VariableDataType variabletype
data type of variable
Definition: Manager.h:133
A variable returning a floating-point value for a given Particle.
Definition: Manager.h:146
FunctionPtr function
Pointer to function.
Definition: Manager.h:147